1
Fork 0

libsyntax/librustc: Allow mut qualifier in patterns.

This commit is contained in:
Luqman Aden 2013-10-20 08:31:23 -04:00
parent c16a95c587
commit 12308db3d2
20 changed files with 111 additions and 148 deletions

View file

@ -727,7 +727,7 @@ impl<'self> GatherLoanCtxt<'self> {
loan_mutability, loan_mutability,
scope_r); scope_r);
} }
ast::BindInfer => { ast::BindByValue(_) => {
// No borrows here, but there may be moves // No borrows here, but there may be moves
if self.bccx.is_move(pat.id) { if self.bccx.is_move(pat.id) {
gather_moves::gather_move_from_pat( gather_moves::gather_move_from_pat(

View file

@ -884,7 +884,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
BindByRef(_) => { BindByRef(_) => {
by_ref_span = Some(span); by_ref_span = Some(span);
} }
BindInfer => { BindByValue(_) => {
if cx.moves_map.contains(&id) { if cx.moves_map.contains(&id) {
any_by_move = true; any_by_move = true;
} }

View file

@ -432,14 +432,12 @@ fn is_nullary_variant(cx: &Context, ex: @Expr) -> bool {
fn check_imm_free_var(cx: &Context, def: Def, sp: Span) { fn check_imm_free_var(cx: &Context, def: Def, sp: Span) {
match def { match def {
DefLocal(_, is_mutbl) => { DefLocal(_, BindByValue(MutMutable)) => {
if is_mutbl { cx.tcx.sess.span_err(
cx.tcx.sess.span_err( sp,
sp, "mutable variables cannot be implicitly captured");
"mutable variables cannot be implicitly captured");
}
} }
DefArg(*) => { /* ok */ } DefLocal(*) | DefArg(*) => { /* ok */ }
DefUpvar(_, def1, _, _) => { check_imm_free_var(cx, *def1, sp); } DefUpvar(_, def1, _, _) => { check_imm_free_var(cx, *def1, sp); }
DefBinding(*) | DefSelf(*) => { /*ok*/ } DefBinding(*) | DefSelf(*) => { /*ok*/ }
_ => { _ => {

View file

@ -813,28 +813,32 @@ fn check_unused_unsafe(cx: &Context, e: &ast::Expr) {
} }
fn check_unused_mut_pat(cx: &Context, p: @ast::Pat) { fn check_unused_mut_pat(cx: &Context, p: @ast::Pat) {
let mut used = false; fn check_unused_mut_pat_inner(cx: &Context, p: @ast::Pat) {
let mut bindings = 0; let mut used = false;
do pat_util::pat_bindings(cx.tcx.def_map, p) |_, id, _, _| { let mut bindings = 0;
used = used || cx.tcx.used_mut_nodes.contains(&id); do pat_util::pat_bindings(cx.tcx.def_map, p) |_, id, _, _| {
bindings += 1; used = used || cx.tcx.used_mut_nodes.contains(&id);
} bindings += 1;
if !used { }
let msg = if bindings == 1 { if !used {
"variable does not need to be mutable" let msg = if bindings == 1 {
} else { "variable does not need to be mutable"
"variables do not need to be mutable" } else {
}; "variables do not need to be mutable"
cx.span_lint(unused_mut, p.span, msg); };
} 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);
} }
} }
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 check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
@ -1075,6 +1079,8 @@ impl Visitor<()> for Context {
fn visit_pat(&mut self, p: @ast::Pat, _: ()) { fn visit_pat(&mut self, p: @ast::Pat, _: ()) {
check_pat_non_uppercase_statics(self, p); check_pat_non_uppercase_statics(self, p);
check_unused_mut_pat(self, p);
visit::walk_pat(self, p, ()); visit::walk_pat(self, p, ());
} }
@ -1095,30 +1101,9 @@ impl Visitor<()> for Context {
visit::walk_stmt(self, s, ()); 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, fn visit_fn(&mut self, fk: &visit::fn_kind, decl: &ast::fn_decl,
body: &ast::Block, span: Span, id: ast::NodeId, _: ()) { body: &ast::Block, span: Span, id: ast::NodeId, _: ()) {
let recurse = |this: &mut Context| { let recurse = |this: &mut Context| {
check_unused_mut_fn_decl(this, decl);
visit::walk_fn(this, fk, decl, body, span, id, ()); visit::walk_fn(this, fk, decl, body, span, id, ());
}; };

View file

@ -429,7 +429,7 @@ fn visit_fn(v: &mut LivenessVisitor,
fn visit_local(v: &mut LivenessVisitor, local: @Local, this: @mut IrMaps) { fn visit_local(v: &mut LivenessVisitor, local: @Local, this: @mut IrMaps) {
let def_map = this.tcx.def_map; 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); debug!("adding local variable {}", p_id);
let name = ast_util::path_to_ident(path); let name = ast_util::path_to_ident(path);
this.add_live_node_for_node(p_id, VarDefNode(sp)); 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, Some(_) => FromLetWithInitializer,
None => FromLetNoInitializer None => FromLetNoInitializer
}; };
let mutbl = match bm {
BindByValue(MutMutable) => true,
_ => false
};
this.add_variable(Local(LocalInfo { this.add_variable(Local(LocalInfo {
id: p_id, id: p_id,
ident: name, ident: name,
is_mutbl: local.is_mutbl, is_mutbl: mutbl,
kind: kind 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 {:?}", debug!("adding local variable {} from match with bm {:?}",
p_id, bm); p_id, bm);
let name = ast_util::path_to_ident(path); 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_live_node_for_node(p_id, VarDefNode(sp));
this.add_variable(Local(LocalInfo { this.add_variable(Local(LocalInfo {
id: p_id, id: p_id,
ident: name, ident: name,
is_mutbl: false, is_mutbl: mutbl,
kind: FromMatch(bm) kind: FromMatch(bm)
})); }));
} }

View file

@ -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 // Idea: make this could be rewritten to model by-ref
// stuff as `&const` and `&mut`? // stuff as `&const` and `&mut`?
// m: mutability of the argument // m: mutability of the argument
let m = if mutbl {McDeclared} else {McImmutable}; let m = match binding_mode {
ast::BindByValue(ast::MutMutable) => McDeclared,
_ => McImmutable
};
@cmt_ { @cmt_ {
id: id, id: id,
span: span, span: span,
@ -548,25 +551,20 @@ impl mem_categorization_ctxt {
} }
} }
ast::DefLocal(vid, mutbl) => { ast::DefLocal(vid, binding_mode) |
let m = if mutbl {McDeclared} else {McImmutable}; ast::DefBinding(vid, binding_mode) => {
@cmt_ {
id:id,
span:span,
cat:cat_local(vid),
mutbl:m,
ty:expr_ty
}
}
ast::DefBinding(vid, _) => {
// by-value/by-ref bindings are local variables // by-value/by-ref bindings are local variables
let m = match binding_mode {
ast::BindByValue(ast::MutMutable) => McDeclared,
_ => McImmutable
};
@cmt_ { @cmt_ {
id:id, id: id,
span:span, span: span,
cat:cat_local(vid), cat: cat_local(vid),
mutbl:McImmutable, mutbl: m,
ty:expr_ty ty: expr_ty
} }
} }
} }

View file

@ -618,7 +618,7 @@ impl VisitContext {
do pat_bindings(self.tcx.def_map, pat) |bm, id, _span, path| { do pat_bindings(self.tcx.def_map, pat) |bm, id, _span, path| {
let binding_moves = match bm { let binding_moves = match bm {
BindByRef(_) => false, BindByRef(_) => false,
BindInfer => { BindByValue(_) => {
let pat_ty = ty::node_id_to_type(self.tcx, id); let pat_ty = ty::node_id_to_type(self.tcx, id);
debug!("pattern {:?} {} type is {}", debug!("pattern {:?} {} type is {}",
id, id,

View file

@ -3817,11 +3817,8 @@ impl Resolver {
Some(declaration) => { Some(declaration) => {
for argument in declaration.inputs.iter() { for argument in declaration.inputs.iter() {
let binding_mode = ArgumentIrrefutableMode; let binding_mode = ArgumentIrrefutableMode;
let mutability =
if argument.is_mutbl {Mutable} else {Immutable};
this.resolve_pattern(argument.pat, this.resolve_pattern(argument.pat,
binding_mode, binding_mode,
mutability,
None); None);
this.resolve_type(&argument.ty); this.resolve_type(&argument.ty);
@ -4036,8 +4033,6 @@ impl Resolver {
} }
fn resolve_local(&mut self, local: @Local) { fn resolve_local(&mut self, local: @Local) {
let mutability = if local.is_mutbl {Mutable} else {Immutable};
// Resolve the type. // Resolve the type.
self.resolve_type(&local.ty); self.resolve_type(&local.ty);
@ -4052,7 +4047,7 @@ impl Resolver {
} }
// Resolve the pattern. // 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. // build a map from pattern identifiers to binding-info's.
@ -4116,8 +4111,7 @@ impl Resolver {
let bindings_list = @mut HashMap::new(); let bindings_list = @mut HashMap::new();
for pattern in arm.pats.iter() { for pattern in arm.pats.iter() {
self.resolve_pattern(*pattern, RefutableMode, Immutable, self.resolve_pattern(*pattern, RefutableMode, Some(bindings_list));
Some(bindings_list));
} }
// This has to happen *after* we determine which // This has to happen *after* we determine which
@ -4261,7 +4255,6 @@ impl Resolver {
fn resolve_pattern(&mut self, fn resolve_pattern(&mut self,
pattern: @Pat, pattern: @Pat,
mode: PatternBindingMode, mode: PatternBindingMode,
mutability: Mutability,
// Maps idents to the node ID for the (outermost) // Maps idents to the node ID for the (outermost)
// pattern that binds them // pattern that binds them
bindings_list: Option<@mut HashMap<Name,NodeId>>) { bindings_list: Option<@mut HashMap<Name,NodeId>>) {
@ -4324,8 +4317,6 @@ impl Resolver {
debug!("(resolving pattern) binding `{}`", debug!("(resolving pattern) binding `{}`",
interner_get(renamed)); interner_get(renamed));
let is_mutable = mutability == Mutable;
let def = match mode { let def = match mode {
RefutableMode => { RefutableMode => {
// For pattern arms, we must use // For pattern arms, we must use
@ -4335,11 +4326,11 @@ impl Resolver {
} }
LocalIrrefutableMode => { LocalIrrefutableMode => {
// But for locals, we use `def_local`. // But for locals, we use `def_local`.
DefLocal(pattern.id, is_mutable) DefLocal(pattern.id, binding_mode)
} }
ArgumentIrrefutableMode => { ArgumentIrrefutableMode => {
// And for function arguments, `def_arg`. // 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, pat_binding_mode: BindingMode,
descr: &str) { descr: &str) {
match pat_binding_mode { match pat_binding_mode {
BindInfer => {} BindByValue(_) => {}
BindByRef(*) => { BindByRef(*) => {
self.resolve_error( self.resolve_error(
pat.span, pat.span,

View file

@ -1842,7 +1842,7 @@ fn create_bindings_map(bcx: @mut Block, pat: @ast::Pat) -> BindingsMap {
let llmatch; let llmatch;
let trmode; let trmode;
match bm { match bm {
ast::BindInfer => { ast::BindByValue(_) => {
// in this case, the final type of the variable will be T, // in this case, the final type of the variable will be T,
// but during matching we need to store a *T as explained // but during matching we need to store a *T as explained
// above // above
@ -2130,7 +2130,7 @@ fn bind_irrefutable_pat(bcx: @mut Block,
bcx, pat.id, path, binding_mode, bcx, pat.id, path, binding_mode,
|bcx, variable_ty, llvariable_val| { |bcx, variable_ty, llvariable_val| {
match pat_binding_mode { match pat_binding_mode {
ast::BindInfer => { ast::BindByValue(_) => {
// By value binding: move the value that `val` // By value binding: move the value that `val`
// points at into the binding's stack slot. // points at into the binding's stack slot.
let datum = Datum {val: val, 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> { fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Path> {
match pat.node { match pat.node {
ast::PatIdent(ast::BindInfer, ref path, None) => { ast::PatIdent(ast::BindByValue(_), ref path, None) => {
Some(path) Some(path)
} }
_ => { _ => {

View file

@ -2100,7 +2100,6 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
// Translate variant arguments to function arguments. // Translate variant arguments to function arguments.
let fn_args = do args.map |varg| { let fn_args = do args.map |varg| {
ast::arg { ast::arg {
is_mutbl: false,
ty: (*varg.ty()).clone(), ty: (*varg.ty()).clone(),
pat: ast_util::ident_to_pat( pat: ast_util::ident_to_pat(
ccx.tcx.sess.next_node_id(), ccx.tcx.sess.next_node_id(),

View file

@ -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); demand::eqtype(fcx, pat.span, region_ty, typ);
} }
// otherwise the type of x is the expected type T // otherwise the type of x is the expected type T
ast::BindInfer => { ast::BindByValue(_) => {
demand::eqtype(fcx, pat.span, expected, typ); demand::eqtype(fcx, pat.span, expected, typ);
} }
} }

View file

@ -232,8 +232,8 @@ pub enum Def {
DefMod(DefId), DefMod(DefId),
DefForeignMod(DefId), DefForeignMod(DefId),
DefStatic(DefId, bool /* is_mutbl */), DefStatic(DefId, bool /* is_mutbl */),
DefArg(NodeId, bool /* is_mutbl */), DefArg(NodeId, BindingMode),
DefLocal(NodeId, bool /* is_mutbl */), DefLocal(NodeId, BindingMode),
DefVariant(DefId /* enum */, DefId /* variant */, bool /* is_structure */), DefVariant(DefId /* enum */, DefId /* variant */, bool /* is_structure */),
DefTy(DefId), DefTy(DefId),
DefTrait(DefId), DefTrait(DefId),
@ -324,7 +324,7 @@ pub struct FieldPat {
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum BindingMode { pub enum BindingMode {
BindByRef(Mutability), BindByRef(Mutability),
BindInfer BindByValue(Mutability),
} }
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
@ -445,7 +445,6 @@ pub enum Stmt_ {
// a refinement on pat. // a refinement on pat.
#[deriving(Eq, Encodable, Decodable,IterBytes)] #[deriving(Eq, Encodable, Decodable,IterBytes)]
pub struct Local { pub struct Local {
is_mutbl: bool,
ty: Ty, ty: Ty,
pat: @Pat, pat: @Pat,
init: Option<@Expr>, init: Option<@Expr>,
@ -880,7 +879,6 @@ pub struct inline_asm {
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub struct arg { pub struct arg {
is_mutbl: bool,
ty: Ty, ty: Ty,
pat: @Pat, pat: @Pat,
id: NodeId, id: NodeId,

View file

@ -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 { pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> @Pat {
@ast::Pat { id: id, @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 } span: s }
} }

View file

@ -399,9 +399,12 @@ impl AstBuilder for @ExtCtxt {
} }
fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: @ast::Expr) -> @ast::Stmt { 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 { let local = @ast::Local {
is_mutbl: mutbl,
ty: self.ty_infer(sp), ty: self.ty_infer(sp),
pat: pat, pat: pat,
init: Some(ex), init: Some(ex),
@ -419,9 +422,12 @@ impl AstBuilder for @ExtCtxt {
typ: ast::Ty, typ: ast::Ty,
ex: @ast::Expr) ex: @ast::Expr)
-> @ast::Stmt { -> @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 { let local = @ast::Local {
is_mutbl: mutbl,
ty: typ, ty: typ,
pat: pat, pat: pat,
init: Some(ex), init: Some(ex),
@ -624,7 +630,7 @@ impl AstBuilder for @ExtCtxt {
self.pat(span, ast::PatLit(expr)) self.pat(span, ast::PatLit(expr))
} }
fn pat_ident(&self, span: Span, ident: ast::Ident) -> @ast::Pat { 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 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 { fn arg(&self, span: Span, ident: ast::Ident, ty: ast::Ty) -> ast::arg {
let arg_pat = self.pat_ident(span, ident); let arg_pat = self.pat_ident(span, ident);
ast::arg { ast::arg {
is_mutbl: false,
ty: ty, ty: ty,
pat: arg_pat, pat: arg_pat,
id: ast::DUMMY_NODE_ID id: ast::DUMMY_NODE_ID

View file

@ -922,7 +922,7 @@ fn create_struct_pattern(cx: @ExtCtxt,
if struct_def.fields.is_empty() { if struct_def.fields.is_empty() {
return ( return (
cx.pat_ident_binding_mode( 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) => { ast::tuple_variant_kind(ref variant_args) => {
if variant_args.is_empty() { if variant_args.is_empty() {
return (cx.pat_ident_binding_mode( 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 matching_path = cx.path_ident(span, variant_ident);

View file

@ -551,13 +551,13 @@ fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander)
let pending_renames = block_info.pending_renames; let pending_renames = block_info.pending_renames;
// take it apart: // take it apart:
let @Local{is_mutbl:is_mutbl, let @Local {
ty:_, ty: _,
pat:pat, pat: pat,
init:init, init: init,
id:id, id: id,
span:span span: span
} = *local; } = *local;
// types can't be copied automatically because of the owned ptr in ty_tup... // types can't be copied automatically because of the owned ptr in ty_tup...
let ty = local.ty.clone(); let ty = local.ty.clone();
// expand the pat (it might contain exprs... #:(o)> // 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 new_init_opt = init.map(|e| fld.fold_expr(e));
let rewritten_local = let rewritten_local =
@Local { @Local {
is_mutbl: is_mutbl,
ty: ty, ty: ty,
pat: rewritten_pat, pat: rewritten_pat,
init: new_init_opt, init: new_init_opt,

View file

@ -356,7 +356,6 @@ pub trait ast_fold {
fn fold_local(&self, l: @Local) -> @Local { fn fold_local(&self, l: @Local) -> @Local {
@Local { @Local {
is_mutbl: l.is_mutbl,
ty: self.fold_ty(&l.ty), ty: self.fold_ty(&l.ty),
pat: self.fold_pat(l.pat), pat: self.fold_pat(l.pat),
init: l.init.map(|e| self.fold_expr(e)), init: l.init.map(|e| self.fold_expr(e)),
@ -426,7 +425,6 @@ fn fold_attribute_<T:ast_fold>(at: Attribute, fld: &T) -> Attribute {
//used in noop_fold_foreign_item and noop_fold_fn_decl //used in noop_fold_foreign_item and noop_fold_fn_decl
fn fold_arg_<T:ast_fold>(a: &arg, fld: &T) -> arg { fn fold_arg_<T:ast_fold>(a: &arg, fld: &T) -> arg {
ast::arg { ast::arg {
is_mutbl: a.is_mutbl,
ty: fld.fold_ty(&a.ty), ty: fld.fold_ty(&a.ty),
pat: fld.fold_pat(a.pat), pat: fld.fold_pat(a.pat),
id: fld.new_id(a.id), id: fld.new_id(a.id),

View file

@ -639,7 +639,7 @@ mod test {
assert_eq!(parser.parse_pat(), assert_eq!(parser.parse_pat(),
@ast::Pat{id: ast::DUMMY_NODE_ID, @ast::Pat{id: ast::DUMMY_NODE_ID,
node: ast::PatIdent( node: ast::PatIdent(
ast::BindInfer, ast::BindByValue(ast::MutImmutable),
ast::Path { ast::Path {
span:sp(0,1), span:sp(0,1),
global:false, global:false,
@ -666,7 +666,6 @@ mod test {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::item_fn(ast::fn_decl{ node: ast::item_fn(ast::fn_decl{
inputs: ~[ast::arg{ inputs: ~[ast::arg{
is_mutbl: false,
ty: ast::Ty{id: ast::DUMMY_NODE_ID, ty: ast::Ty{id: ast::DUMMY_NODE_ID,
node: ast::ty_path(ast::Path{ node: ast::ty_path(ast::Path{
span:sp(10,13), span:sp(10,13),
@ -685,7 +684,7 @@ mod test {
pat: @ast::Pat { pat: @ast::Pat {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::PatIdent( node: ast::PatIdent(
ast::BindInfer, ast::BindByValue(ast::MutImmutable),
ast::Path { ast::Path {
span:sp(6,7), span:sp(6,7),
global:false, global:false,

View file

@ -17,7 +17,7 @@ use ast::{CallSugar, NoSugar, DoSugar};
use ast::{TyBareFn, TyClosure}; use ast::{TyBareFn, TyClosure};
use ast::{RegionTyParamBound, TraitTyParamBound}; use ast::{RegionTyParamBound, TraitTyParamBound};
use ast::{provided, public, purity}; 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::{BiBitAnd, BiBitOr, BiBitXor, Block};
use ast::{BlockCheckMode, UnBox}; use ast::{BlockCheckMode, UnBox};
use ast::{Crate, CrateConfig, Decl, DeclItem}; use ast::{Crate, CrateConfig, Decl, DeclItem};
@ -1193,6 +1193,7 @@ impl Parser {
1 1
} }
}, },
_ if token::is_keyword(keywords::Mut, self.token) => 1,
_ => 0 _ => 0
}; };
@ -1210,16 +1211,11 @@ impl Parser {
// This version of parse arg doesn't necessarily require // This version of parse arg doesn't necessarily require
// identifier names. // identifier names.
pub fn parse_arg_general(&self, require_name: bool) -> arg { 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() { let pat = if require_name || self.is_named_argument() {
debug!("parse_arg_general parse_pat (require_name:{:?})", debug!("parse_arg_general parse_pat (require_name:{:?})",
require_name); require_name);
let pat = self.parse_pat(); let pat = self.parse_pat();
if is_mutbl && !ast_util::pat_is_ident(pat) {
self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
}
self.expect(&token::COLON); self.expect(&token::COLON);
pat pat
} else { } else {
@ -1232,7 +1228,6 @@ impl Parser {
let t = self.parse_ty(false); let t = self.parse_ty(false);
ast::arg { ast::arg {
is_mutbl: is_mutbl,
ty: t, ty: t,
pat: pat, pat: pat,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -1246,7 +1241,6 @@ impl Parser {
// parse an argument in a lambda header e.g. |arg, arg| // parse an argument in a lambda header e.g. |arg, arg|
pub fn parse_fn_block_arg(&self) -> arg { pub fn parse_fn_block_arg(&self) -> arg {
let is_mutbl = self.eat_keyword(keywords::Mut);
let pat = self.parse_pat(); let pat = self.parse_pat();
let t = if self.eat(&token::COLON) { let t = if self.eat(&token::COLON) {
self.parse_ty(false) self.parse_ty(false)
@ -1258,7 +1252,6 @@ impl Parser {
} }
}; };
ast::arg { ast::arg {
is_mutbl: is_mutbl,
ty: t, ty: t,
pat: pat, pat: pat,
id: ast::DUMMY_NODE_ID id: ast::DUMMY_NODE_ID
@ -2681,7 +2674,7 @@ impl Parser {
} else { } else {
subpat = @ast::Pat { subpat = @ast::Pat {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: PatIdent(BindInfer, fieldpath, None), node: PatIdent(BindByValue(MutImmutable), fieldpath, None),
span: *self.last_span span: *self.last_span
}; };
} }
@ -2863,6 +2856,8 @@ impl Parser {
} else { } else {
pat = PatLit(val); pat = PatLit(val);
} }
} else if self.eat_keyword(keywords::Mut) {
pat = self.parse_pat_ident(BindByValue(MutMutable));
} else if self.eat_keyword(keywords::Ref) { } else if self.eat_keyword(keywords::Ref) {
// parse ref pat // parse ref pat
let mutbl = self.parse_mutability(); let mutbl = self.parse_mutability();
@ -2891,7 +2886,7 @@ impl Parser {
// or just foo // or just foo
sub = None; sub = None;
} }
pat = PatIdent(BindInfer, name, sub); pat = PatIdent(BindByValue(MutImmutable), name, sub);
} else { } else {
// parse an enum pat // parse an enum pat
let enum_path = self.parse_path(LifetimeAndTypesWithColons) let enum_path = self.parse_path(LifetimeAndTypesWithColons)
@ -2935,7 +2930,7 @@ impl Parser {
// it could still be either an enum // it could still be either an enum
// or an identifier pattern, resolve // or an identifier pattern, resolve
// will sort it out: // will sort it out:
pat = PatIdent(BindInfer, pat = PatIdent(BindByValue(MutImmutable),
enum_path, enum_path,
None); None);
} else { } else {
@ -2989,14 +2984,10 @@ impl Parser {
} }
// parse a local variable declaration // parse a local variable declaration
fn parse_local(&self, is_mutbl: bool) -> @Local { fn parse_local(&self) -> @Local {
let lo = self.span.lo; let lo = self.span.lo;
let pat = self.parse_pat(); let pat = self.parse_pat();
if is_mutbl && !ast_util::pat_is_ident(pat) {
self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
}
let mut ty = Ty { let mut ty = Ty {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ty_infer, node: ty_infer,
@ -3005,7 +2996,6 @@ impl Parser {
if self.eat(&token::COLON) { ty = self.parse_ty(false); } if self.eat(&token::COLON) { ty = self.parse_ty(false); }
let init = self.parse_initializer(); let init = self.parse_initializer();
@ast::Local { @ast::Local {
is_mutbl: is_mutbl,
ty: ty, ty: ty,
pat: pat, pat: pat,
init: init, init: init,
@ -3016,11 +3006,10 @@ impl Parser {
// parse a "let" stmt // parse a "let" stmt
fn parse_let(&self) -> @Decl { fn parse_let(&self) -> @Decl {
let is_mutbl = self.eat_keyword(keywords::Mut);
let lo = self.span.lo; let lo = self.span.lo;
let local = self.parse_local(is_mutbl); let local = self.parse_local();
while self.eat(&token::COMMA) { while self.eat(&token::COMMA) {
let _ = self.parse_local(is_mutbl); let _ = self.parse_local();
self.obsolete(*self.span, ObsoleteMultipleLocalDecl); self.obsolete(*self.span, ObsoleteMultipleLocalDecl);
} }
return @spanned(lo, self.last_span.hi, DeclLocal(local)); return @spanned(lo, self.last_span.hi, DeclLocal(local));

View file

@ -1476,10 +1476,6 @@ pub fn print_decl(s: @ps, decl: &ast::Decl) {
ibox(s, indent_unit); ibox(s, indent_unit);
word_nbsp(s, "let"); word_nbsp(s, "let");
if loc.is_mutbl {
word_nbsp(s, "mut");
}
fn print_local(s: @ps, loc: &ast::Local) { fn print_local(s: @ps, loc: &ast::Local) {
ibox(s, indent_unit); ibox(s, indent_unit);
print_local_decl(s, loc); print_local_decl(s, loc);
@ -1589,7 +1585,10 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
word_nbsp(s, "ref"); word_nbsp(s, "ref");
print_mutability(s, mutbl); print_mutability(s, mutbl);
} }
ast::BindInfer => {} ast::BindByValue(ast::MutImmutable) => {}
ast::BindByValue(ast::MutMutable) => {
word_nbsp(s, "mut");
}
} }
print_path(s, path, true); print_path(s, path, true);
match sub { match sub {
@ -1932,9 +1931,6 @@ pub fn print_mt(s: @ps, mt: &ast::mt) {
pub fn print_arg(s: @ps, input: &ast::arg) { pub fn print_arg(s: @ps, input: &ast::arg) {
ibox(s, indent_unit); ibox(s, indent_unit);
if input.is_mutbl {
word_space(s, "mut");
}
match input.ty.node { match input.ty.node {
ast::ty_infer => print_pat(s, input.pat), ast::ty_infer => print_pat(s, input.pat),
_ => { _ => {