loan_mutability,
scope_r);
}
- ast::BindInfer => {
+ ast::BindByValue(_) => {
// No borrows here, but there may be moves
if self.bccx.is_move(pat.id) {
gather_moves::gather_move_from_pat(
BindByRef(_) => {
by_ref_span = Some(span);
}
- BindInfer => {
+ BindByValue(_) => {
if cx.moves_map.contains(&id) {
any_by_move = true;
}
fn check_imm_free_var(cx: &Context, def: Def, sp: Span) {
match def {
- DefLocal(_, is_mutbl) => {
- if is_mutbl {
- cx.tcx.sess.span_err(
- sp,
- "mutable variables cannot be implicitly captured");
- }
+ DefLocal(_, BindByValue(MutMutable)) => {
+ cx.tcx.sess.span_err(
+ sp,
+ "mutable variables cannot be implicitly captured");
}
- DefArg(*) => { /* ok */ }
+ DefLocal(*) | DefArg(*) => { /* ok */ }
DefUpvar(_, def1, _, _) => { check_imm_free_var(cx, *def1, sp); }
DefBinding(*) | DefSelf(*) => { /*ok*/ }
_ => {
}
fn check_unused_mut_pat(cx: &Context, p: @ast::Pat) {
- let mut used = false;
- let mut bindings = 0;
- do pat_util::pat_bindings(cx.tcx.def_map, p) |_, id, _, _| {
- used = used || cx.tcx.used_mut_nodes.contains(&id);
- bindings += 1;
- }
- if !used {
- let msg = if bindings == 1 {
- "variable does not need to be mutable"
- } else {
- "variables do not need to be mutable"
- };
- cx.span_lint(unused_mut, p.span, msg);
- }
-}
-
-fn check_unused_mut_fn_decl(cx: &Context, fd: &ast::fn_decl) {
- for arg in fd.inputs.iter() {
- if arg.is_mutbl {
- check_unused_mut_pat(cx, arg.pat);
+ fn check_unused_mut_pat_inner(cx: &Context, p: @ast::Pat) {
+ let mut used = false;
+ let mut bindings = 0;
+ do pat_util::pat_bindings(cx.tcx.def_map, p) |_, id, _, _| {
+ used = used || cx.tcx.used_mut_nodes.contains(&id);
+ bindings += 1;
+ }
+ if !used {
+ let msg = if bindings == 1 {
+ "variable does not need to be mutable"
+ } else {
+ "variables do not need to be mutable"
+ };
+ cx.span_lint(unused_mut, p.span, msg);
}
}
+ do ast_util::walk_pat(p) |pat| {
+ match pat.node {
+ ast::PatIdent(ast::BindByValue(ast::MutMutable), _, _) => {
+ check_unused_mut_pat_inner(cx, pat);
+ }
+ _ => {}
+ }
+
+ true
+ };
}
fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
fn visit_pat(&mut self, p: @ast::Pat, _: ()) {
check_pat_non_uppercase_statics(self, p);
+ check_unused_mut_pat(self, p);
+
visit::walk_pat(self, p, ());
}
visit::walk_stmt(self, s, ());
}
- fn visit_ty_method(&mut self, tm: &ast::TypeMethod, _: ()) {
- check_unused_mut_fn_decl(self, &tm.decl);
- visit::walk_ty_method(self, tm, ());
- }
-
- fn visit_trait_method(&mut self, tm: &ast::trait_method, _: ()) {
- match *tm {
- ast::required(ref m) => check_unused_mut_fn_decl(self, &m.decl),
- ast::provided(ref m) => check_unused_mut_fn_decl(self, &m.decl)
- }
- visit::walk_trait_method(self, tm, ());
- }
-
- fn visit_local(&mut self, l: @ast::Local, _: ()) {
- if l.is_mutbl {
- check_unused_mut_pat(self, l.pat);
- }
- visit::walk_local(self, l, ());
- }
-
fn visit_fn(&mut self, fk: &visit::fn_kind, decl: &ast::fn_decl,
body: &ast::Block, span: Span, id: ast::NodeId, _: ()) {
let recurse = |this: &mut Context| {
- check_unused_mut_fn_decl(this, decl);
visit::walk_fn(this, fk, decl, body, span, id, ());
};
fn visit_local(v: &mut LivenessVisitor, local: @Local, this: @mut IrMaps) {
let def_map = this.tcx.def_map;
- do pat_util::pat_bindings(def_map, local.pat) |_bm, p_id, sp, path| {
+ do pat_util::pat_bindings(def_map, local.pat) |bm, p_id, sp, path| {
debug!("adding local variable {}", p_id);
let name = ast_util::path_to_ident(path);
this.add_live_node_for_node(p_id, VarDefNode(sp));
Some(_) => FromLetWithInitializer,
None => FromLetNoInitializer
};
+ let mutbl = match bm {
+ BindByValue(MutMutable) => true,
+ _ => false
+ };
this.add_variable(Local(LocalInfo {
id: p_id,
ident: name,
- is_mutbl: local.is_mutbl,
+ is_mutbl: mutbl,
kind: kind
}));
}
debug!("adding local variable {} from match with bm {:?}",
p_id, bm);
let name = ast_util::path_to_ident(path);
+ let mutbl = match bm {
+ BindByValue(MutMutable) => true,
+ _ => false
+ };
this.add_live_node_for_node(p_id, VarDefNode(sp));
this.add_variable(Local(LocalInfo {
id: p_id,
ident: name,
- is_mutbl: false,
+ is_mutbl: mutbl,
kind: FromMatch(bm)
}));
}
}
}
- ast::DefArg(vid, mutbl) => {
+ ast::DefArg(vid, binding_mode) => {
// Idea: make this could be rewritten to model by-ref
// stuff as `&const` and `&mut`?
// m: mutability of the argument
- let m = if mutbl {McDeclared} else {McImmutable};
+ let m = match binding_mode {
+ ast::BindByValue(ast::MutMutable) => McDeclared,
+ _ => McImmutable
+ };
@cmt_ {
id: id,
span: span,
}
}
- ast::DefLocal(vid, mutbl) => {
- let m = if mutbl {McDeclared} else {McImmutable};
- @cmt_ {
- id:id,
- span:span,
- cat:cat_local(vid),
- mutbl:m,
- ty:expr_ty
- }
- }
-
- ast::DefBinding(vid, _) => {
+ ast::DefLocal(vid, binding_mode) |
+ ast::DefBinding(vid, binding_mode) => {
// by-value/by-ref bindings are local variables
+ let m = match binding_mode {
+ ast::BindByValue(ast::MutMutable) => McDeclared,
+ _ => McImmutable
+ };
+
@cmt_ {
- id:id,
- span:span,
- cat:cat_local(vid),
- mutbl:McImmutable,
- ty:expr_ty
+ id: id,
+ span: span,
+ cat: cat_local(vid),
+ mutbl: m,
+ ty: expr_ty
}
}
}
do pat_bindings(self.tcx.def_map, pat) |bm, id, _span, path| {
let binding_moves = match bm {
BindByRef(_) => false,
- BindInfer => {
+ BindByValue(_) => {
let pat_ty = ty::node_id_to_type(self.tcx, id);
debug!("pattern {:?} {} type is {}",
id,
Some(declaration) => {
for argument in declaration.inputs.iter() {
let binding_mode = ArgumentIrrefutableMode;
- let mutability =
- if argument.is_mutbl {Mutable} else {Immutable};
this.resolve_pattern(argument.pat,
binding_mode,
- mutability,
None);
this.resolve_type(&argument.ty);
}
fn resolve_local(&mut self, local: @Local) {
- let mutability = if local.is_mutbl {Mutable} else {Immutable};
-
// Resolve the type.
self.resolve_type(&local.ty);
}
// Resolve the pattern.
- self.resolve_pattern(local.pat, LocalIrrefutableMode, mutability, None);
+ self.resolve_pattern(local.pat, LocalIrrefutableMode, None);
}
// build a map from pattern identifiers to binding-info's.
let bindings_list = @mut HashMap::new();
for pattern in arm.pats.iter() {
- self.resolve_pattern(*pattern, RefutableMode, Immutable,
- Some(bindings_list));
+ self.resolve_pattern(*pattern, RefutableMode, Some(bindings_list));
}
// This has to happen *after* we determine which
fn resolve_pattern(&mut self,
pattern: @Pat,
mode: PatternBindingMode,
- mutability: Mutability,
// Maps idents to the node ID for the (outermost)
// pattern that binds them
bindings_list: Option<@mut HashMap<Name,NodeId>>) {
debug!("(resolving pattern) binding `{}`",
interner_get(renamed));
- let is_mutable = mutability == Mutable;
-
let def = match mode {
RefutableMode => {
// For pattern arms, we must use
}
LocalIrrefutableMode => {
// But for locals, we use `def_local`.
- DefLocal(pattern.id, is_mutable)
+ DefLocal(pattern.id, binding_mode)
}
ArgumentIrrefutableMode => {
// And for function arguments, `def_arg`.
- DefArg(pattern.id, is_mutable)
+ DefArg(pattern.id, binding_mode)
}
};
pat_binding_mode: BindingMode,
descr: &str) {
match pat_binding_mode {
- BindInfer => {}
+ BindByValue(_) => {}
BindByRef(*) => {
self.resolve_error(
pat.span,
let llmatch;
let trmode;
match bm {
- ast::BindInfer => {
+ ast::BindByValue(_) => {
// in this case, the final type of the variable will be T,
// but during matching we need to store a *T as explained
// above
bcx, pat.id, path, binding_mode,
|bcx, variable_ty, llvariable_val| {
match pat_binding_mode {
- ast::BindInfer => {
+ ast::BindByValue(_) => {
// By value binding: move the value that `val`
// points at into the binding's stack slot.
let datum = Datum {val: val,
fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Path> {
match pat.node {
- ast::PatIdent(ast::BindInfer, ref path, None) => {
+ ast::PatIdent(ast::BindByValue(_), ref path, None) => {
Some(path)
}
_ => {
// Translate variant arguments to function arguments.
let fn_args = do args.map |varg| {
ast::arg {
- is_mutbl: false,
ty: (*varg.ty()).clone(),
pat: ast_util::ident_to_pat(
ccx.tcx.sess.next_node_id(),
demand::eqtype(fcx, pat.span, region_ty, typ);
}
// otherwise the type of x is the expected type T
- ast::BindInfer => {
+ ast::BindByValue(_) => {
demand::eqtype(fcx, pat.span, expected, typ);
}
}
DefMod(DefId),
DefForeignMod(DefId),
DefStatic(DefId, bool /* is_mutbl */),
- DefArg(NodeId, bool /* is_mutbl */),
- DefLocal(NodeId, bool /* is_mutbl */),
+ DefArg(NodeId, BindingMode),
+ DefLocal(NodeId, BindingMode),
DefVariant(DefId /* enum */, DefId /* variant */, bool /* is_structure */),
DefTy(DefId),
DefTrait(DefId),
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum BindingMode {
BindByRef(Mutability),
- BindInfer
+ BindByValue(Mutability),
}
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
// a refinement on pat.
#[deriving(Eq, Encodable, Decodable,IterBytes)]
pub struct Local {
- is_mutbl: bool,
ty: Ty,
pat: @Pat,
init: Option<@Expr>,
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub struct arg {
- is_mutbl: bool,
ty: Ty,
pat: @Pat,
id: NodeId,
pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> @Pat {
@ast::Pat { id: id,
- node: PatIdent(BindInfer, ident_to_path(s, i), None),
+ node: PatIdent(BindByValue(MutImmutable), ident_to_path(s, i), None),
span: s }
}
}
fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: @ast::Expr) -> @ast::Stmt {
- let pat = self.pat_ident(sp, ident);
+ let pat = if mutbl {
+ self.pat_ident_binding_mode(sp, ident, ast::BindByValue(ast::MutMutable))
+ } else {
+ self.pat_ident(sp, ident)
+ };
let local = @ast::Local {
- is_mutbl: mutbl,
ty: self.ty_infer(sp),
pat: pat,
init: Some(ex),
typ: ast::Ty,
ex: @ast::Expr)
-> @ast::Stmt {
- let pat = self.pat_ident(sp, ident);
+ let pat = if mutbl {
+ self.pat_ident_binding_mode(sp, ident, ast::BindByValue(ast::MutMutable))
+ } else {
+ self.pat_ident(sp, ident)
+ };
let local = @ast::Local {
- is_mutbl: mutbl,
ty: typ,
pat: pat,
init: Some(ex),
self.pat(span, ast::PatLit(expr))
}
fn pat_ident(&self, span: Span, ident: ast::Ident) -> @ast::Pat {
- self.pat_ident_binding_mode(span, ident, ast::BindInfer)
+ self.pat_ident_binding_mode(span, ident, ast::BindByValue(ast::MutImmutable))
}
fn pat_ident_binding_mode(&self,
fn arg(&self, span: Span, ident: ast::Ident, ty: ast::Ty) -> ast::arg {
let arg_pat = self.pat_ident(span, ident);
ast::arg {
- is_mutbl: false,
ty: ty,
pat: arg_pat,
id: ast::DUMMY_NODE_ID
if struct_def.fields.is_empty() {
return (
cx.pat_ident_binding_mode(
- span, struct_ident, ast::BindInfer),
+ span, struct_ident, ast::BindByValue(ast::MutImmutable)),
~[]);
}
ast::tuple_variant_kind(ref variant_args) => {
if variant_args.is_empty() {
return (cx.pat_ident_binding_mode(
- span, variant_ident, ast::BindInfer), ~[]);
+ span, variant_ident, ast::BindByValue(ast::MutImmutable)), ~[]);
}
let matching_path = cx.path_ident(span, variant_ident);
let pending_renames = block_info.pending_renames;
// take it apart:
- let @Local{is_mutbl:is_mutbl,
- ty:_,
- pat:pat,
- init:init,
- id:id,
- span:span
- } = *local;
+ let @Local {
+ ty: _,
+ pat: pat,
+ init: init,
+ id: id,
+ span: span
+ } = *local;
// types can't be copied automatically because of the owned ptr in ty_tup...
let ty = local.ty.clone();
// expand the pat (it might contain exprs... #:(o)>
let new_init_opt = init.map(|e| fld.fold_expr(e));
let rewritten_local =
@Local {
- is_mutbl: is_mutbl,
ty: ty,
pat: rewritten_pat,
init: new_init_opt,
fn fold_local(&self, l: @Local) -> @Local {
@Local {
- is_mutbl: l.is_mutbl,
ty: self.fold_ty(&l.ty),
pat: self.fold_pat(l.pat),
init: l.init.map(|e| self.fold_expr(e)),
//used in noop_fold_foreign_item and noop_fold_fn_decl
fn fold_arg_<T:ast_fold>(a: &arg, fld: &T) -> arg {
ast::arg {
- is_mutbl: a.is_mutbl,
ty: fld.fold_ty(&a.ty),
pat: fld.fold_pat(a.pat),
id: fld.new_id(a.id),
assert_eq!(parser.parse_pat(),
@ast::Pat{id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(
- ast::BindInfer,
+ ast::BindByValue(ast::MutImmutable),
ast::Path {
span:sp(0,1),
global:false,
id: ast::DUMMY_NODE_ID,
node: ast::item_fn(ast::fn_decl{
inputs: ~[ast::arg{
- is_mutbl: false,
ty: ast::Ty{id: ast::DUMMY_NODE_ID,
node: ast::ty_path(ast::Path{
span:sp(10,13),
pat: @ast::Pat {
id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(
- ast::BindInfer,
+ ast::BindByValue(ast::MutImmutable),
ast::Path {
span:sp(6,7),
global:false,
use ast::{TyBareFn, TyClosure};
use ast::{RegionTyParamBound, TraitTyParamBound};
use ast::{provided, public, purity};
-use ast::{_mod, BiAdd, arg, Arm, Attribute, BindByRef, BindInfer};
+use ast::{_mod, BiAdd, arg, Arm, Attribute, BindByRef, BindByValue};
use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
use ast::{BlockCheckMode, UnBox};
use ast::{Crate, CrateConfig, Decl, DeclItem};
1
}
},
+ _ if token::is_keyword(keywords::Mut, self.token) => 1,
_ => 0
};
// This version of parse arg doesn't necessarily require
// identifier names.
pub fn parse_arg_general(&self, require_name: bool) -> arg {
- let is_mutbl = self.eat_keyword(keywords::Mut);
let pat = if require_name || self.is_named_argument() {
debug!("parse_arg_general parse_pat (require_name:{:?})",
require_name);
let pat = self.parse_pat();
- if is_mutbl && !ast_util::pat_is_ident(pat) {
- self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
- }
-
self.expect(&token::COLON);
pat
} else {
let t = self.parse_ty(false);
ast::arg {
- is_mutbl: is_mutbl,
ty: t,
pat: pat,
id: ast::DUMMY_NODE_ID,
// parse an argument in a lambda header e.g. |arg, arg|
pub fn parse_fn_block_arg(&self) -> arg {
- let is_mutbl = self.eat_keyword(keywords::Mut);
let pat = self.parse_pat();
let t = if self.eat(&token::COLON) {
self.parse_ty(false)
}
};
ast::arg {
- is_mutbl: is_mutbl,
ty: t,
pat: pat,
id: ast::DUMMY_NODE_ID
} else {
subpat = @ast::Pat {
id: ast::DUMMY_NODE_ID,
- node: PatIdent(BindInfer, fieldpath, None),
+ node: PatIdent(BindByValue(MutImmutable), fieldpath, None),
span: *self.last_span
};
}
} else {
pat = PatLit(val);
}
+ } else if self.eat_keyword(keywords::Mut) {
+ pat = self.parse_pat_ident(BindByValue(MutMutable));
} else if self.eat_keyword(keywords::Ref) {
// parse ref pat
let mutbl = self.parse_mutability();
// or just foo
sub = None;
}
- pat = PatIdent(BindInfer, name, sub);
+ pat = PatIdent(BindByValue(MutImmutable), name, sub);
} else {
// parse an enum pat
let enum_path = self.parse_path(LifetimeAndTypesWithColons)
// it could still be either an enum
// or an identifier pattern, resolve
// will sort it out:
- pat = PatIdent(BindInfer,
+ pat = PatIdent(BindByValue(MutImmutable),
enum_path,
None);
} else {
}
// parse a local variable declaration
- fn parse_local(&self, is_mutbl: bool) -> @Local {
+ fn parse_local(&self) -> @Local {
let lo = self.span.lo;
let pat = self.parse_pat();
- if is_mutbl && !ast_util::pat_is_ident(pat) {
- self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
- }
-
let mut ty = Ty {
id: ast::DUMMY_NODE_ID,
node: ty_infer,
if self.eat(&token::COLON) { ty = self.parse_ty(false); }
let init = self.parse_initializer();
@ast::Local {
- is_mutbl: is_mutbl,
ty: ty,
pat: pat,
init: init,
// parse a "let" stmt
fn parse_let(&self) -> @Decl {
- let is_mutbl = self.eat_keyword(keywords::Mut);
let lo = self.span.lo;
- let local = self.parse_local(is_mutbl);
+ let local = self.parse_local();
while self.eat(&token::COMMA) {
- let _ = self.parse_local(is_mutbl);
+ let _ = self.parse_local();
self.obsolete(*self.span, ObsoleteMultipleLocalDecl);
}
return @spanned(lo, self.last_span.hi, DeclLocal(local));
ibox(s, indent_unit);
word_nbsp(s, "let");
- if loc.is_mutbl {
- word_nbsp(s, "mut");
- }
-
fn print_local(s: @ps, loc: &ast::Local) {
ibox(s, indent_unit);
print_local_decl(s, loc);
word_nbsp(s, "ref");
print_mutability(s, mutbl);
}
- ast::BindInfer => {}
+ ast::BindByValue(ast::MutImmutable) => {}
+ ast::BindByValue(ast::MutMutable) => {
+ word_nbsp(s, "mut");
+ }
}
print_path(s, path, true);
match sub {
pub fn print_arg(s: @ps, input: &ast::arg) {
ibox(s, indent_unit);
- if input.is_mutbl {
- word_space(s, "mut");
- }
match input.ty.node {
ast::ty_infer => print_pat(s, input.pat),
_ => {