diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 6c927794dc811..ea5c05e9ec80e 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -727,7 +727,7 @@ impl<'self> GatherLoanCtxt<'self> { 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( diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index de5e00d241eb1..482ba43ae259d 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -884,7 +884,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, BindByRef(_) => { by_ref_span = Some(span); } - BindInfer => { + BindByValue(_) => { if cx.moves_map.contains(&id) { any_by_move = true; } diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 5737039f83c35..fd5114889fddb 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -432,14 +432,12 @@ fn is_nullary_variant(cx: &Context, ex: @Expr) -> bool { 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*/ } _ => { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index b0cdd53de922c..1ac14dfc4b1e5 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -813,27 +813,24 @@ fn check_unused_unsafe(cx: &Context, e: &ast::Expr) { } 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); + match p.node { + ast::PatIdent(ast::BindByValue(ast::MutMutable), _, _) => { + 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); + } } + _ => () } } @@ -1075,6 +1072,8 @@ impl Visitor<()> for Context { 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, ()); } @@ -1095,30 +1094,9 @@ impl Visitor<()> for Context { 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, ()); }; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 695f4a6fd13b5..e9e416124af9f 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -429,7 +429,7 @@ fn visit_fn(v: &mut LivenessVisitor, 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)); @@ -437,10 +437,14 @@ fn visit_local(v: &mut LivenessVisitor, local: @Local, this: @mut IrMaps) { 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 })); } @@ -454,11 +458,15 @@ fn visit_arm(v: &mut LivenessVisitor, arm: &Arm, this: @mut IrMaps) { 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) })); } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index eb03027ad71ff..5e26201522c41 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -473,12 +473,15 @@ impl mem_categorization_ctxt { } } - 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, @@ -548,25 +551,20 @@ impl mem_categorization_ctxt { } } - 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 } } } diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 5001614647a88..d4dce789192d7 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -618,7 +618,7 @@ impl VisitContext { 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, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index ee36b807ac79c..c16c39b5a09ba 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -3817,11 +3817,8 @@ impl Resolver { 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); @@ -4036,8 +4033,6 @@ impl Resolver { } fn resolve_local(&mut self, local: @Local) { - let mutability = if local.is_mutbl {Mutable} else {Immutable}; - // Resolve the type. self.resolve_type(&local.ty); @@ -4052,7 +4047,7 @@ impl Resolver { } // 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. @@ -4116,8 +4111,7 @@ impl Resolver { 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 @@ -4261,7 +4255,6 @@ impl Resolver { 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>) { @@ -4324,8 +4317,6 @@ impl Resolver { debug!("(resolving pattern) binding `{}`", interner_get(renamed)); - let is_mutable = mutability == Mutable; - let def = match mode { RefutableMode => { // For pattern arms, we must use @@ -4335,11 +4326,11 @@ impl Resolver { } 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) } }; @@ -5361,7 +5352,7 @@ impl Resolver { pat_binding_mode: BindingMode, descr: &str) { match pat_binding_mode { - BindInfer => {} + BindByValue(_) => {} BindByRef(*) => { self.resolve_error( pat.span, diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 6bb41929db1d1..a36d938052a91 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1842,7 +1842,7 @@ fn create_bindings_map(bcx: @mut Block, pat: @ast::Pat) -> BindingsMap { 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 @@ -2130,7 +2130,7 @@ fn bind_irrefutable_pat(bcx: @mut Block, 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, @@ -2241,7 +2241,7 @@ fn bind_irrefutable_pat(bcx: @mut Block, 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) } _ => { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f00fa3e70e1bf..47c1cf0064d55 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2100,7 +2100,6 @@ pub fn trans_enum_variant_or_tuple_like_struct( // 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(), diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 25048d888fa8c..93c3d94f5dc69 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -476,7 +476,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::Pat, expected: ty::t) { 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); } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 372f1950c1de0..6647c4c811ec3 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -232,8 +232,8 @@ pub enum Def { 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), @@ -324,7 +324,7 @@ pub struct FieldPat { #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub enum BindingMode { BindByRef(Mutability), - BindInfer + BindByValue(Mutability), } #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] @@ -445,7 +445,6 @@ pub enum Stmt_ { // a refinement on pat. #[deriving(Eq, Encodable, Decodable,IterBytes)] pub struct Local { - is_mutbl: bool, ty: Ty, pat: @Pat, init: Option<@Expr>, @@ -880,7 +879,6 @@ pub struct inline_asm { #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub struct arg { - is_mutbl: bool, ty: Ty, pat: @Pat, id: NodeId, diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 456d344b838c5..3ec87dbdd26fb 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -234,7 +234,7 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path { 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 } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 78cdc3f585ba0..4c3ab840b440f 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -399,9 +399,12 @@ impl AstBuilder for @ExtCtxt { } 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), @@ -419,9 +422,12 @@ impl AstBuilder for @ExtCtxt { 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), @@ -624,7 +630,7 @@ impl AstBuilder for @ExtCtxt { 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, @@ -710,7 +716,6 @@ impl AstBuilder for @ExtCtxt { 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 diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index c31c609d4e74a..82a779546fcea 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -922,7 +922,7 @@ fn create_struct_pattern(cx: @ExtCtxt, if struct_def.fields.is_empty() { return ( cx.pat_ident_binding_mode( - span, struct_ident, ast::BindInfer), + span, struct_ident, ast::BindByValue(ast::MutImmutable)), ~[]); } @@ -985,7 +985,7 @@ fn create_enum_variant_pattern(cx: @ExtCtxt, 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); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 99bcb36eedbf5..9526357f9ae8e 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -551,13 +551,13 @@ fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander) 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)> @@ -585,7 +585,6 @@ fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander) 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, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 37bc00d5827b9..e9ecb95c54530 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -356,7 +356,6 @@ pub trait ast_fold { 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)), @@ -426,7 +425,6 @@ fn fold_attribute_(at: Attribute, fld: &T) -> Attribute { //used in noop_fold_foreign_item and noop_fold_fn_decl fn fold_arg_(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), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index fad9eab754200..0de571978a0e4 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -639,7 +639,7 @@ mod test { 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, @@ -666,7 +666,6 @@ mod test { 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), @@ -685,7 +684,7 @@ mod test { 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, diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 8c26793605c61..20ad13dace61c 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -34,7 +34,6 @@ pub enum ObsoleteSyntax { ObsoleteBareFnType, ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl, - ObsoleteMutWithMultipleBindings, ObsoleteUnsafeExternFn, ObsoleteTraitFuncVisibility, ObsoleteConstPointer, @@ -91,11 +90,6 @@ impl ParserObsoleteMethods for Parser { "instead of e.g. `let a = 1, b = 2`, write \ `let (a, b) = (1, 2)`." ), - ObsoleteMutWithMultipleBindings => ( - "`mut` with multiple bindings", - "use multiple local declarations instead of e.g. `let mut \ - (x, y) = ...`." - ), ObsoleteUnsafeExternFn => ( "unsafe external function", "external functions are always unsafe; remove the `unsafe` \ diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 605e259cf0c2b..5a5e310e56f43 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -17,7 +17,7 @@ use ast::{CallSugar, NoSugar, DoSugar}; 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}; @@ -1184,15 +1184,8 @@ impl Parser { pub fn is_named_argument(&self) -> bool { let offset = match *self.token { token::BINOP(token::AND) => 1, - token::BINOP(token::MINUS) => 1, token::ANDAND => 1, - token::BINOP(token::PLUS) => { - if self.look_ahead(1, |t| *t == token::BINOP(token::PLUS)) { - 2 - } else { - 1 - } - }, + _ if token::is_keyword(keywords::Mut, self.token) => 1, _ => 0 }; @@ -1210,16 +1203,11 @@ impl Parser { // 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 { @@ -1232,7 +1220,6 @@ impl Parser { let t = self.parse_ty(false); ast::arg { - is_mutbl: is_mutbl, ty: t, pat: pat, id: ast::DUMMY_NODE_ID, @@ -1246,7 +1233,6 @@ impl Parser { // 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) @@ -1258,7 +1244,6 @@ impl Parser { } }; ast::arg { - is_mutbl: is_mutbl, ty: t, pat: pat, id: ast::DUMMY_NODE_ID @@ -1809,7 +1794,7 @@ impl Parser { return self.mk_mac_expr(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT)); } else if *self.token == token::LBRACE { // This might be a struct literal. - if self.looking_at_record_literal() { + if self.looking_at_struct_literal() { // It's a struct literal. self.bump(); let mut fields = ~[]; @@ -2520,12 +2505,11 @@ impl Parser { } } - // For distingishing between record literals and blocks - fn looking_at_record_literal(&self) -> bool { + // For distingishing between struct literals and blocks + fn looking_at_struct_literal(&self) -> bool { *self.token == token::LBRACE && - (self.look_ahead(1, |t| token::is_keyword(keywords::Mut, t)) || - (self.look_ahead(1, |t| token::is_plain_ident(t)) && - self.look_ahead(2, |t| *t == token::COLON))) + (self.look_ahead(1, |t| token::is_plain_ident(t)) && + self.look_ahead(2, |t| *t == token::COLON)) } fn parse_match_expr(&self) -> @Expr { @@ -2681,7 +2665,7 @@ impl Parser { } else { subpat = @ast::Pat { id: ast::DUMMY_NODE_ID, - node: PatIdent(BindInfer, fieldpath, None), + node: PatIdent(BindByValue(MutImmutable), fieldpath, None), span: *self.last_span }; } @@ -2863,6 +2847,8 @@ impl Parser { } 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(); @@ -2891,7 +2877,7 @@ impl Parser { // 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) @@ -2935,7 +2921,7 @@ impl Parser { // 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 { @@ -2989,14 +2975,10 @@ impl Parser { } // 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, @@ -3005,7 +2987,6 @@ impl Parser { 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, @@ -3016,11 +2997,10 @@ impl Parser { // 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)); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 400ff80448523..121934119107e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1476,10 +1476,6 @@ pub fn print_decl(s: @ps, decl: &ast::Decl) { 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); @@ -1589,7 +1585,10 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) { 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 { @@ -1932,9 +1931,6 @@ pub fn print_mt(s: @ps, mt: &ast::mt) { 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), _ => { diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs index 9b0249bdc2a59..4b382a3116a6b 100644 --- a/src/test/compile-fail/lint-unused-mut-variables.rs +++ b/src/test/compile-fail/lint-unused-mut-variables.rs @@ -20,6 +20,14 @@ fn main() { let mut a = 2; //~ ERROR: variable does not need to be mutable let mut b = 3; //~ ERROR: variable does not need to be mutable let mut a = ~[3]; //~ ERROR: variable does not need to be mutable + let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable + + match 30 { + mut x => {} //~ ERROR: variable does not need to be mutable + } + + let x = |mut y: int| 10; //~ ERROR: variable does not need to be mutable + fn what(mut foo: int) {} //~ ERROR: variable does not need to be mutable // positive cases let mut a = 2; @@ -30,6 +38,17 @@ fn main() { do callback { a.push(3); } + let (mut a, b) = (1, 2); + a = 34; + + match 30 { + mut x => { + x = 21; + } + } + + let x = |mut y: int| y = 32; + fn nothing(mut foo: int) { foo = 37; } } fn callback(f: &fn()) {} diff --git a/src/test/compile-fail/mut-patterns.rs b/src/test/compile-fail/mut-patterns.rs new file mode 100644 index 0000000000000..d9cdae4a4995f --- /dev/null +++ b/src/test/compile-fail/mut-patterns.rs @@ -0,0 +1,16 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Can't put mut in non-ident pattern + +pub fn main() { + struct Foo { x: int } + let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected `;` but found `{` +} diff --git a/src/test/run-pass/mut-in-ident-patterns.rs b/src/test/run-pass/mut-in-ident-patterns.rs new file mode 100644 index 0000000000000..13303e7b10881 --- /dev/null +++ b/src/test/run-pass/mut-in-ident-patterns.rs @@ -0,0 +1,80 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + fn foo(&self, mut x: int) -> int { + let val = x; + x = 37 * x; + val + x + } +} + +struct X; +impl Foo for X {} + +pub fn main() { + let (a, mut b) = (23, 4); + assert_eq!(a, 23); + assert_eq!(b, 4); + b = a + b; + assert_eq!(b, 27); + + + assert_eq!(X.foo(2), 76); + + enum Bar { + Foo(int), + Baz(f32, u8) + } + + let (x, mut y) = (32, Foo(21)); + + match x { + mut z @ 32 => { + assert_eq!(z, 32); + z = 34; + assert_eq!(z, 34); + } + _ => {} + } + + check_bar(&y); + y = Baz(10.0, 3); + check_bar(&y); + + fn check_bar(y: &Bar) { + match y { + &Foo(a) => { + assert_eq!(a, 21); + } + &Baz(a, b) => { + assert_eq!(a, 10.0); + assert_eq!(b, 3); + } + } + } + + fn foo1((x, mut y): (f64, int), mut z: int) -> int { + y = 2 * 6; + z = y + (x as int); + y - z + } + + struct A { + x: int + } + let A { x: mut x } = A { x: 10 }; + assert_eq!(x, 10); + x = 30; + assert_eq!(x, 30); + + (|A { x: mut t }: A| { t = t+1; t })(A { x: 34 }); + +}