commit
16b8a41531
|
@ -730,7 +730,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(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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*/ }
|
||||
_ => {
|
||||
|
|
|
@ -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, ());
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<Name,NodeId>>) {
|
||||
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -2065,7 +2065,6 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
|||
// 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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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_<T:ast_fold>(at: Attribute, fld: &T) -> Attribute {
|
|||
//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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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` \
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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),
|
||||
_ => {
|
||||
|
|
|
@ -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()) {}
|
||||
|
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 `{`
|
||||
}
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 });
|
||||
|
||||
}
|
Loading…
Reference in New Issue