From 9a857b4472142b6d0bf65e9185c4c2619e722fb0 Mon Sep 17 00:00:00 2001 From: Adolfo Ochagavía Date: Sat, 22 Nov 2014 16:02:49 +0100 Subject: libsyntax: Forbid type parameters in tuple indices This breaks code like ``` let t = (42i, 42i); ... t.0:: ...; ``` Change this code to not contain an unused type parameter. For example: ``` let t = (42i, 42i); ... t.0 ...; ``` Closes https://github.com/rust-lang/rust/issues/19096 [breaking-change] --- src/libsyntax/parse/parser.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ab0543d64b7..e4fa6508820 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -49,8 +49,7 @@ use ast::{PolyTraitRef}; use ast::{QPath, RequiredMethod}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; -use ast::{StructVariantKind, BiSub}; -use ast::StrStyle; +use ast::{StructVariantKind, BiSub, StrStyle}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; use ast::{TtDelimited, TtSequence, TtToken}; @@ -65,10 +64,8 @@ use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause, WherePredicate}; use ast; -use ast_util::{as_prec, ident_to_path, operator_prec}; -use ast_util; -use codemap::{Span, BytePos, Spanned, spanned, mk_sp}; -use codemap; +use ast_util::{mod, as_prec, ident_to_path, operator_prec}; +use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp}; use diagnostic; use ext::tt::macro_parser; use parse; @@ -2472,24 +2469,19 @@ impl<'a> Parser<'a> { } token::Literal(token::Integer(n), suf) => { let sp = self.span; + + // A tuple index may not have a suffix self.expect_no_suffix(sp, "tuple index", suf); - let index = n.as_str(); let dot = self.last_span.hi; hi = self.span.hi; self.bump(); - let (_, tys) = if self.eat(&token::ModSep) { - self.expect_lt(); - self.parse_generic_values_after_lt() - } else { - (Vec::new(), Vec::new()) - }; - let num = from_str::(index); - match num { + let index = from_str::(n.as_str()); + match index { Some(n) => { let id = spanned(dot, hi, n); - let field = self.mk_tup_field(e, id, tys); + let field = self.mk_tup_field(e, id, Vec::new()); e = self.mk_expr(lo, hi, field); } None => { -- cgit 1.4.1-3-g733a5 From 35316972ff2e7ea02a4583141d3ac69b79610067 Mon Sep 17 00:00:00 2001 From: Adolfo Ochagavía Date: Sun, 23 Nov 2014 12:14:35 +0100 Subject: Remove type parameters from ExprField and ExprTupField --- src/librustc/lint/builtin.rs | 18 +++----- src/librustc/middle/cfg/construct.rs | 4 +- src/librustc/middle/const_eval.rs | 15 +++--- src/librustc/middle/dead.rs | 14 ++---- src/librustc/middle/expr_use_visitor.rs | 8 ++-- src/librustc/middle/liveness.rs | 23 ++++------ src/librustc/middle/mem_categorization.rs | 4 +- src/librustc/middle/privacy.rs | 27 ++++------- src/librustc/middle/region.rs | 9 ++-- src/librustc/middle/resolve.rs | 12 ++--- src/librustc/middle/typeck/check/method/confirm.rs | 13 ++---- src/librustc/middle/typeck/check/mod.rs | 53 +++++++--------------- src/librustc_back/svh.rs | 4 +- src/librustc_trans/save/mod.rs | 26 ++++------- src/librustc_trans/trans/consts.rs | 20 +++----- src/librustc_trans/trans/debuginfo.rs | 12 ++--- src/librustc_trans/trans/expr.rs | 43 +++++------------- src/libsyntax/ast.rs | 4 +- src/libsyntax/ext/build.rs | 4 +- src/libsyntax/fold.rs | 10 ++-- src/libsyntax/parse/parser.rs | 28 +++++------- src/libsyntax/print/pprust.rs | 18 +------- src/libsyntax/visit.rs | 10 +--- 23 files changed, 125 insertions(+), 254 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 00c68f42c32..9fe7a21243f 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -37,22 +37,18 @@ use util::ppaux::{ty_to_string}; use util::nodemap::{FnvHashMap, NodeSet}; use lint::{Context, LintPass, LintArray}; -use std::cmp; +use std::{cmp, slice}; use std::collections::hash_map::{Occupied, Vacant}; use std::num::SignedInt; -use std::slice; use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; -use syntax::abi; -use syntax::ast_map; -use syntax::ast_util::is_shift_binop; -use syntax::attr::AttrMetaMethods; -use syntax::attr; +use syntax::{abi, ast, ast_map}; +use syntax::ast_util::{mod, is_shift_binop}; +use syntax::attr::{mod, AttrMetaMethods}; use syntax::codemap::{Span, DUMMY_SP}; use syntax::parse::token; -use syntax::{ast, ast_util, visit}; use syntax::ast::{TyI, TyU, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; use syntax::ptr::P; -use syntax::visit::Visitor; +use syntax::visit::{mod, Visitor}; declare_lint!(WHILE_TRUE, Warn, "suggest using `loop { }` instead of `while true { }`") @@ -1112,8 +1108,8 @@ impl UnusedParens { } ast::ExprUnary(_, ref x) | ast::ExprCast(ref x, _) | - ast::ExprField(ref x, _, _) | - ast::ExprTupField(ref x, _, _) | + ast::ExprField(ref x, _) | + ast::ExprTupField(ref x, _) | ast::ExprIndex(ref x, _) => { // &X { y: 1 }, X { y: 1 }.y contains_exterior_struct_lit(&**x) diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 42e1ede147e..61c56cf9ecc 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -475,8 +475,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { ast::ExprCast(ref e, _) | ast::ExprUnary(_, ref e) | ast::ExprParen(ref e) | - ast::ExprField(ref e, _, _) | - ast::ExprTupField(ref e, _, _) => { + ast::ExprField(ref e, _) | + ast::ExprTupField(ref e, _) => { self.straightline(expr, pred, Some(&**e).into_iter()) } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index c7c67e8a67b..98ac7e413ca 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -15,19 +15,16 @@ pub use self::const_val::*; pub use self::constness::*; use metadata::csearch; -use middle::astencode; -use middle::def; +use middle::{astencode, def}; use middle::pat_util::def_to_path; use middle::ty::{mod, Ty}; -use middle::typeck::astconv; -use middle::typeck::check; -use util::nodemap::{DefIdMap}; +use middle::typeck::{astconv, check}; +use util::nodemap::DefIdMap; use syntax::ast::{mod, Expr}; use syntax::parse::token::InternedString; use syntax::ptr::P; -use syntax::visit::Visitor; -use syntax::visit; +use syntax::visit::{mod, Visitor}; use syntax::{ast_map, ast_util, codemap}; use std::rc::Rc; @@ -234,9 +231,9 @@ impl<'a, 'tcx> ConstEvalVisitor<'a, 'tcx> { } } - ast::ExprField(ref base, _, _) => self.classify(&**base), + ast::ExprField(ref base, _) => self.classify(&**base), - ast::ExprTupField(ref base, _, _) => self.classify(&**base), + ast::ExprTupField(ref base, _) => self.classify(&**base), ast::ExprIndex(ref base, ref idx) => join(self.classify(&**base), self.classify(&**idx)), diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 62a5d23e333..cf2e9a65859 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -12,20 +12,14 @@ // closely. The idea is that all reachable symbols are live, codes called // from live codes are live, and everything else is dead. -use middle::def; -use middle::pat_util; -use middle::privacy; -use middle::ty; -use middle::typeck; +use middle::{def, pat_util, privacy, ty, typeck}; use lint; use util::nodemap::NodeSet; use std::collections::HashSet; -use syntax::ast; -use syntax::ast_map; +use syntax::{ast, ast_map, codemap}; use syntax::ast_util::{local_def, is_local, PostExpansionMethod}; use syntax::attr::{mod, AttrMetaMethods}; -use syntax::codemap; use syntax::visit::{mod, Visitor}; // Any local node that may call something in its body block should be @@ -277,10 +271,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { ast::ExprMethodCall(..) => { self.lookup_and_handle_method(expr.id, expr.span); } - ast::ExprField(ref lhs, ref ident, _) => { + ast::ExprField(ref lhs, ref ident) => { self.handle_field_access(&**lhs, &ident.node); } - ast::ExprTupField(ref lhs, idx, _) => { + ast::ExprTupField(ref lhs, idx) => { self.handle_tup_field_access(&**lhs, idx.node); } _ => () diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 645a1aef3dc..fa0f59f6860 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -20,11 +20,9 @@ pub use self::ConsumeMode::*; pub use self::MoveReason::*; use self::OverloadedCallType::*; +use middle::{def, region, pat_util}; use middle::mem_categorization as mc; -use middle::def; use middle::mem_categorization::Typer; -use middle::region; -use middle::pat_util; use middle::ty::{mod, Ty}; use middle::typeck::{MethodCall, MethodObject, MethodTraitObject}; use middle::typeck::{MethodOrigin, MethodParam, MethodTypeParam}; @@ -331,11 +329,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } } - ast::ExprField(ref base, _, _) => { // base.f + ast::ExprField(ref base, _) => { // base.f self.select_from_expr(&**base); } - ast::ExprTupField(ref base, _, _) => { // base. + ast::ExprTupField(ref base, _) => { // base. self.select_from_expr(&**base); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 7d13d2e5f94..15d9e87a9d5 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -113,24 +113,19 @@ use self::VarKind::*; use middle::def::*; use middle::mem_categorization::Typer; -use middle::pat_util; -use middle::typeck; -use middle::ty; +use middle::{pat_util, typeck, ty}; use lint; use util::nodemap::NodeMap; -use std::fmt; -use std::io; +use std::{fmt, io, uint}; use std::rc::Rc; -use std::uint; use syntax::ast::{mod, NodeId, Expr}; use syntax::codemap::{BytePos, original_sp, Span}; -use syntax::parse::token::special_idents; -use syntax::parse::token; +use syntax::parse::token::{mod, special_idents}; use syntax::print::pprust::{expr_to_string, block_to_string}; use syntax::ptr::P; -use syntax::{visit, ast_util}; -use syntax::visit::{Visitor, FnKind}; +use syntax::ast_util; +use syntax::visit::{mod, Visitor, FnKind}; /// For use with `propagate_through_loop`. enum LoopKind<'a> { @@ -967,11 +962,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.access_path(expr, succ, ACC_READ | ACC_USE) } - ast::ExprField(ref e, _, _) => { + ast::ExprField(ref e, _) => { self.propagate_through_expr(&**e, succ) } - ast::ExprTupField(ref e, _, _) => { + ast::ExprTupField(ref e, _) => { self.propagate_through_expr(&**e, succ) } @@ -1295,8 +1290,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match expr.node { ast::ExprPath(_) => succ, - ast::ExprField(ref e, _, _) => self.propagate_through_expr(&**e, succ), - ast::ExprTupField(ref e, _, _) => self.propagate_through_expr(&**e, succ), + ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ), + ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ), _ => self.propagate_through_expr(expr, succ) } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 78b6c19874a..e9986e47e4a 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -477,7 +477,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { Ok(self.cat_deref(expr, base_cmt, 0, false)) } - ast::ExprField(ref base, f_name, _) => { + ast::ExprField(ref base, f_name) => { let base_cmt = if_ok!(self.cat_expr(&**base)); debug!("cat_expr(cat_field): id={} expr={} base={}", expr.id, @@ -486,7 +486,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { Ok(self.cat_field(expr, base_cmt, f_name.node.name, expr_ty)) } - ast::ExprTupField(ref base, idx, _) => { + ast::ExprTupField(ref base, idx) => { let base_cmt = if_ok!(self.cat_expr(&**base)); Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty)) } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index c2835ba5647..66c782877f9 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -17,20 +17,17 @@ use self::FieldName::*; use std::mem::replace; use metadata::csearch; -use middle::def; -use middle::resolve; +use middle::{def, resolve}; use middle::ty::{mod, Ty}; use middle::typeck::{MethodCall, MethodMap, MethodOrigin, MethodParam, MethodTypeParam}; use middle::typeck::{MethodStatic, MethodStaticUnboxedClosure, MethodObject, MethodTraitObject}; use util::nodemap::{NodeMap, NodeSet}; -use syntax::ast; -use syntax::ast_map; +use syntax::{ast, ast_map}; use syntax::ast_util::{is_local, local_def, PostExpansionMethod}; use syntax::codemap::Span; use syntax::parse::token; -use syntax::visit; -use syntax::visit::Visitor; +use syntax::visit::{mod, Visitor}; type Context<'a, 'tcx> = (&'a MethodMap<'tcx>, &'a resolve::ExportMap2); @@ -836,20 +833,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &ast::Expr) { match expr.node { - ast::ExprField(ref base, ident, _) => { - match ty::expr_ty_adjusted(self.tcx, &**base).sty { - ty::ty_struct(id, _) => { - self.check_field(expr.span, id, NamedField(ident.node)); - } - _ => {} + ast::ExprField(ref base, ident) => { + if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty { + self.check_field(expr.span, id, NamedField(ident.node)); } } - ast::ExprTupField(ref base, idx, _) => { - match ty::expr_ty_adjusted(self.tcx, &**base).sty { - ty::ty_struct(id, _) => { - self.check_field(expr.span, id, UnnamedField(idx.node)); - } - _ => {} + ast::ExprTupField(ref base, idx) => { + if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty { + self.check_field(expr.span, id, UnnamedField(idx.node)); } } ast::ExprMethodCall(ident, _, _) => { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 8a50cb4ed4e..c5511f995bc 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -22,8 +22,7 @@ Most of the documentation on regions can be found in use session::Session; -use middle::ty::{FreeRegion}; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, Ty, FreeRegion}; use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap}; use util::common::can_reach; @@ -33,7 +32,6 @@ use syntax::codemap::Span; use syntax::{ast, visit}; use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local}; use syntax::ast_util::{stmt_id}; -use syntax::ptr::P; use syntax::visit::{Visitor, FnKind}; /// CodeExtent represents a statically-describable extent that can be @@ -824,11 +822,10 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { match expr.node { ast::ExprAddrOf(_, ref subexpr) | ast::ExprUnary(ast::UnDeref, ref subexpr) | - ast::ExprField(ref subexpr, _, _) | - ast::ExprTupField(ref subexpr, _, _) | + ast::ExprField(ref subexpr, _) | + ast::ExprTupField(ref subexpr, _) | ast::ExprIndex(ref subexpr, _) | ast::ExprParen(ref subexpr) => { - let subexpr: &'a P = subexpr; // FIXME(#11586) expr = &**subexpr; } _ => { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 6ad3d67af0a..68a31c83ea4 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -71,17 +71,13 @@ use syntax::ast::{Variant, ViewItem, ViewItemExternCrate}; use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::ast::{Visibility}; use syntax::ast; -use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat}; -use syntax::ast_util; +use syntax::ast_util::{mod, PostExpansionMethod, local_def, walk_pat}; use syntax::attr::AttrMetaMethods; use syntax::ext::mtwt; -use syntax::parse::token::special_names; -use syntax::parse::token::special_idents; -use syntax::parse::token; +use syntax::parse::token::{mod, special_names, special_idents}; use syntax::codemap::{Span, DUMMY_SP, Pos}; use syntax::owned_slice::OwnedSlice; -use syntax::visit; -use syntax::visit::Visitor; +use syntax::visit::{mod, Visitor}; use std::collections::{HashMap, HashSet}; use std::collections::hash_map::{Occupied, Vacant}; @@ -5959,7 +5955,7 @@ impl<'a> Resolver<'a> { fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) { match expr.node { - ExprField(_, ident, _) => { + ExprField(_, ident) => { // FIXME(#6890): Even though you can't treat a method like a // field, we need to add any trait methods we find that match // the field name so that we can do some nice error reporting diff --git a/src/librustc/middle/typeck/check/method/confirm.rs b/src/librustc/middle/typeck/check/method/confirm.rs index c53befcc10d..5bcd96e66ef 100644 --- a/src/librustc/middle/typeck/check/method/confirm.rs +++ b/src/librustc/middle/typeck/check/method/confirm.rs @@ -10,16 +10,13 @@ use super::probe; -use middle::subst; -use middle::subst::Subst; +use middle::subst::{mod, Subst}; use middle::traits; use middle::ty::{mod, Ty}; -use middle::typeck::check; -use middle::typeck::check::{FnCtxt, NoPreference, PreferMutLvalue}; +use middle::typeck::check::{mod, FnCtxt, NoPreference, PreferMutLvalue}; use middle::typeck::{MethodCall, MethodCallee, MethodObject, MethodOrigin, MethodParam, MethodStatic, MethodTraitObject, MethodTypeParam}; -use middle::typeck::infer; -use middle::typeck::infer::InferCtxt; +use middle::typeck::infer::{mod, InferCtxt}; use middle::ty_fold::HigherRankedFoldable; use syntax::ast; use syntax::codemap::Span; @@ -510,8 +507,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { let last = exprs[exprs.len() - 1]; match last.node { ast::ExprParen(ref expr) | - ast::ExprField(ref expr, _, _) | - ast::ExprTupField(ref expr, _, _) | + ast::ExprField(ref expr, _) | + ast::ExprTupField(ref expr, _) | ast::ExprSlice(ref expr, _, _, _) | ast::ExprIndex(ref expr, _) | ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr), diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 85d2f573615..d38c5bc0ca9 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -83,62 +83,41 @@ use self::IsBinopAssignment::*; use self::TupleArgumentsFlag::*; use session::Session; -use middle::const_eval; -use middle::def; +use middle::{const_eval, def, traits}; use middle::lang_items::IteratorItem; -use middle::mem_categorization::McResult; -use middle::mem_categorization; -use middle::pat_util::pat_id_map; -use middle::pat_util; +use middle::mem_categorization::{mod, McResult}; +use middle::pat_util::{mod, pat_id_map}; use middle::region::CodeExtent; -use middle::subst; -use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace}; -use middle::traits; -use middle::ty::{FnSig, VariantInfo}; -use middle::ty::{Polytype}; +use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace}; +use middle::ty::{FnSig, VariantInfo, Polytype}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; use middle::ty::{mod, Ty}; use middle::ty::liberate_late_bound_regions; use middle::ty_fold::TypeFolder; -use middle::typeck::astconv::AstConv; -use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty}; -use middle::typeck::astconv; +use middle::typeck::astconv::{mod, ast_region_to_region, ast_ty_to_ty, AstConv}; use middle::typeck::check::_match::pat_ctxt; -use middle::typeck::CrateCtxt; -use middle::typeck::infer; use middle::typeck::rscope::RegionScope; -use middle::typeck::{lookup_def_ccx}; -use middle::typeck::no_params; -use middle::typeck::{require_same_types}; -use middle::typeck::{MethodCall, MethodCallee, MethodMap, ObjectCastMap}; -use middle::typeck::{TypeAndSubsts}; -use middle::typeck; +use middle::typeck::{mod, CrateCtxt, infer, lookup_def_ccx, no_params, require_same_types}; +use middle::typeck::{MethodCall, MethodCallee, MethodMap, ObjectCastMap, TypeAndSubsts}; use middle::lang_items::TypeIdLangItem; use lint; use util::common::{block_query, indenter, loop_query}; -use util::ppaux; -use util::ppaux::{UserString, Repr}; +use util::ppaux::{mod, UserString, Repr}; use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; use std::cell::{Cell, Ref, RefCell}; use std::collections::hash_map::{Occupied, Vacant}; use std::mem::replace; use std::rc::Rc; -use syntax::abi; -use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem}; -use syntax::ast; -use syntax::ast_util::{local_def, PostExpansionMethod}; -use syntax::ast_util; -use syntax::attr; -use syntax::codemap::Span; -use syntax::codemap; +use syntax::{mod, abi, attr}; +use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem}; +use syntax::ast_util::{mod, local_def, PostExpansionMethod}; +use syntax::codemap::{mod, Span}; use syntax::owned_slice::OwnedSlice; use syntax::parse::token; use syntax::print::pprust; use syntax::ptr::P; -use syntax::visit; -use syntax::visit::Visitor; -use syntax; +use syntax::visit::{mod, Visitor}; pub mod _match; pub mod vtable; @@ -4405,10 +4384,10 @@ fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized); } - ast::ExprField(ref base, ref field, _) => { + ast::ExprField(ref base, ref field) => { check_field(fcx, expr, lvalue_pref, &**base, field); } - ast::ExprTupField(ref base, idx, _) => { + ast::ExprTupField(ref base, idx) => { check_tup_field(fcx, expr, lvalue_pref, &**base, idx); } ast::ExprIndex(ref base, ref idx) => { diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index cda8a1b1b5f..549d636e8cb 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -278,8 +278,8 @@ mod svh_visitor { ExprBlock(..) => SawExprBlock, ExprAssign(..) => SawExprAssign, ExprAssignOp(op, _, _) => SawExprAssignOp(op), - ExprField(_, id, _) => SawExprField(content(id.node)), - ExprTupField(_, id, _) => SawExprTupField(id.node), + ExprField(_, id) => SawExprField(content(id.node)), + ExprTupField(_, id) => SawExprTupField(id.node), ExprIndex(..) => SawExprIndex, ExprSlice(..) => SawExprSlice, ExprPath(..) => SawExprPath, diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 67ed95f83fd..ec228c8aa15 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -30,34 +30,26 @@ use driver::driver::CrateAnalysis; use session::Session; -use middle::def; +use middle::{def, typeck}; use middle::ty::{mod, Ty}; -use middle::typeck; use std::cell::Cell; -use std::io; -use std::io::File; -use std::io::fs; +use std::io::{mod, File, fs}; use std::os; -use syntax::ast; -use syntax::ast_util; -use syntax::ast_util::PostExpansionMethod; -use syntax::ast::{NodeId,DefId}; +use syntax::ast_util::{mod, PostExpansionMethod}; +use syntax::ast::{mod, NodeId, DefId}; use syntax::ast_map::NodeItem; use syntax::attr; use syntax::codemap::*; -use syntax::parse::token; -use syntax::parse::token::{get_ident,keywords}; +use syntax::parse::token::{mod, get_ident, keywords}; use syntax::owned_slice::OwnedSlice; -use syntax::visit; -use syntax::visit::Visitor; +use syntax::visit::{mod, Visitor}; use syntax::print::pprust::{path_to_string,ty_to_string}; use syntax::ptr::P; use self::span_utils::SpanUtils; -use self::recorder::Recorder; -use self::recorder::FmtStrs; +use self::recorder::{Recorder, FmtStrs}; use util::ppaux; @@ -1293,7 +1285,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { ast::ExprStruct(ref path, ref fields, ref base) => self.process_struct_lit(ex, path, fields, base), ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args), - ast::ExprField(ref sub_ex, ident, _) => { + ast::ExprField(ref sub_ex, ident) => { if generated_code(sub_ex.span) { return } @@ -1319,7 +1311,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { "Expected struct type, but not ty_struct"), } }, - ast::ExprTupField(ref sub_ex, idx, _) => { + ast::ExprTupField(ref sub_ex, idx) => { if generated_code(sub_ex.span) { return } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 4213e941727..c7cdf937049 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -13,22 +13,14 @@ use back::abi; use llvm; use llvm::{ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, Bool, True, False}; use llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE, - RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE}; + RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE}; use metadata::csearch; -use middle::const_eval; -use middle::def; -use trans::adt; -use trans::base; -use trans::base::push_ctxt; -use trans::closure; +use middle::{const_eval, def}; +use trans::{adt, closure, consts, debuginfo, expr, inline, machine}; +use trans::base::{mod, push_ctxt}; use trans::common::*; -use trans::consts; -use trans::expr; -use trans::inline; -use trans::machine; use trans::type_::Type; use trans::type_of; -use trans::debuginfo; use middle::ty::{mod, Ty}; use util::ppaux::{Repr, ty_to_string}; @@ -418,7 +410,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { } } } - ast::ExprField(ref base, field, _) => { + ast::ExprField(ref base, field) => { let (bv, bt) = const_expr(cx, &**base); let brepr = adt::represent_type(cx, bt); expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| { @@ -426,7 +418,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { adt::const_get_field(cx, &*brepr, bv, discr, ix) }) } - ast::ExprTupField(ref base, idx, _) => { + ast::ExprTupField(ref base, idx) => { let (bv, bt) = const_expr(cx, &**base); let brepr = adt::represent_type(cx, bt); expr::with_field_tys(cx.tcx(), bt, None, |discr, _| { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 075b6b0dd6e..a3472e194cf 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -197,13 +197,10 @@ use llvm::{ModuleRef, ContextRef, ValueRef}; use llvm::debuginfo::*; use metadata::csearch; use middle::subst::{mod, Subst, Substs}; -use trans::adt; +use trans::{mod, adt, machine, type_of}; use trans::common::*; -use trans::machine; use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef}; -use trans::type_of; use trans::type_::Type; -use trans; use middle::ty::{mod, Ty}; use middle::pat_util; use session::config::{mod, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; @@ -219,8 +216,7 @@ use syntax::util::interner::Interner; use syntax::codemap::{Span, Pos}; use syntax::{ast, codemap, ast_util, ast_map}; use syntax::ast_util::PostExpansionMethod; -use syntax::parse::token; -use syntax::parse::token::special_idents; +use syntax::parse::token::{mod, special_idents}; static DW_LANG_RUST: c_uint = 0x9000; @@ -3456,8 +3452,8 @@ fn populate_scope_map(cx: &CrateContext, ast::ExprCast(ref sub_exp, _) | ast::ExprAddrOf(_, ref sub_exp) | - ast::ExprField(ref sub_exp, _, _) | - ast::ExprTupField(ref sub_exp, _, _) | + ast::ExprField(ref sub_exp, _) | + ast::ExprTupField(ref sub_exp, _) | ast::ExprParen(ref sub_exp) => walk_expr(cx, &**sub_exp, scope_stack, scope_map), diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 670e893cc0e..9e004b137bb 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -38,47 +38,26 @@ pub use self::Dest::*; use self::lazy_binop_ty::*; use back::abi; -use llvm; -use llvm::{ValueRef}; +use llvm::{mod, ValueRef}; use middle::def; use middle::mem_categorization::Typer; -use middle::subst; -use middle::subst::Subst; -use trans::_match; -use trans::adt; -use trans::asm; +use middle::subst::{mod, Subst}; +use trans::{_match, adt, asm, base, callee, closure, consts, controlflow}; +use trans::{debuginfo, glue, machine, meth, inline, tvec, type_of}; use trans::base::*; -use trans::base; use trans::build::*; -use trans::callee; -use trans::cleanup; -use trans::cleanup::CleanupMethods; -use trans::closure; +use trans::cleanup::{mod, CleanupMethods}; use trans::common::*; -use trans::consts; -use trans::controlflow; use trans::datum::*; -use trans::debuginfo; -use trans::glue; -use trans::machine; -use trans::meth; -use trans::inline; -use trans::tvec; -use trans::type_of; -use middle::ty::{struct_fields, tup_fields}; -use middle::ty::{AdjustDerefRef, AdjustAddEnv, AutoUnsafe}; -use middle::ty::{AutoPtr}; -use middle::ty::{mod, Ty}; -use middle::typeck; -use middle::typeck::MethodCall; +use middle::ty::{mod, struct_fields, tup_fields}; +use middle::ty::{AdjustDerefRef, AdjustAddEnv, AutoUnsafe, AutoPtr, Ty}; +use middle::typeck::{mod, MethodCall}; use util::common::indenter; use util::ppaux::Repr; use trans::machine::{llsize_of, llsize_of_alloc}; use trans::type_::Type; -use syntax::ast; -use syntax::ast_util; -use syntax::codemap; +use syntax::{ast, ast_util, codemap}; use syntax::print::pprust::{expr_to_string}; use syntax::ptr::P; use std::rc::Rc; @@ -599,10 +578,10 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprPath(_) => { trans_def(bcx, expr, bcx.def(expr.id)) } - ast::ExprField(ref base, ident, _) => { + ast::ExprField(ref base, ident) => { trans_rec_field(bcx, &**base, ident.node) } - ast::ExprTupField(ref base, idx, _) => { + ast::ExprTupField(ref base, idx) => { trans_rec_tup_field(bcx, &**base, idx.node) } ast::ExprIndex(ref base, ref idx) => { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5d4fd2704a2..3d33774aa55 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -673,8 +673,8 @@ pub enum Expr_ { ExprAssign(P, P), ExprAssignOp(BinOp, P, P), - ExprField(P, SpannedIdent, Vec>), - ExprTupField(P, Spanned, Vec>), + ExprField(P, SpannedIdent), + ExprTupField(P, Spanned), ExprIndex(P, P), ExprSlice(P, Option>, Option>, Mutability), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index b18a0c8411c..2c7f9e889f8 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -577,7 +577,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }; let id = Spanned { node: ident, span: field_span }; - self.expr(sp, ast::ExprField(expr, id, Vec::new())) + self.expr(sp, ast::ExprField(expr, id)) } fn expr_tup_field_access(&self, sp: Span, expr: P, idx: uint) -> P { let field_span = Span { @@ -587,7 +587,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }; let id = Spanned { node: idx, span: field_span }; - self.expr(sp, ast::ExprTupField(expr, id, Vec::new())) + self.expr(sp, ast::ExprTupField(expr, id)) } fn expr_addr_of(&self, sp: Span, e: P) -> P { self.expr(sp, ast::ExprAddrOf(ast::MutImmutable, e)) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1bdf9ea73df..6941c0e9c18 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1345,15 +1345,13 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> folder.fold_expr(el), folder.fold_expr(er)) } - ExprField(el, ident, tys) => { + ExprField(el, ident) => { ExprField(folder.fold_expr(el), - respan(ident.span, folder.fold_ident(ident.node)), - tys.move_map(|x| folder.fold_ty(x))) + respan(ident.span, folder.fold_ident(ident.node))) } - ExprTupField(el, ident, tys) => { + ExprTupField(el, ident) => { ExprTupField(folder.fold_expr(el), - respan(ident.span, folder.fold_uint(ident.node)), - tys.move_map(|x| folder.fold_ty(x))) + respan(ident.span, folder.fold_uint(ident.node))) } ExprIndex(el, er) => { ExprIndex(folder.fold_expr(el), folder.fold_expr(er)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e4fa6508820..a9306c71240 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -71,14 +71,11 @@ use ext::tt::macro_parser; use parse; use parse::attr::ParserAttr; use parse::classify; -use parse::common::{SeqSep, seq_sep_none}; -use parse::common::{seq_sep_trailing_allowed}; -use parse::lexer::Reader; -use parse::lexer::TokenAndSpan; +use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed}; +use parse::lexer::{Reader, TokenAndSpan}; use parse::obsolete::*; -use parse::token::{MatchNt, SubstNt, InternedString}; +use parse::token::{mod, MatchNt, SubstNt, InternedString}; use parse::token::{keywords, special_idents}; -use parse::token; use parse::{new_sub_parser_from_file, ParseSess}; use print::pprust; use ptr::P; @@ -86,7 +83,6 @@ use owned_slice::OwnedSlice; use std::collections::HashSet; use std::io::fs::PathExtensions; -use std::mem::replace; use std::mem; use std::num::Float; use std::rc::Rc; @@ -912,7 +908,7 @@ impl<'a> Parser<'a> { tok: token::Underscore, sp: self.span, }; - replace(&mut self.buffer[buffer_start], placeholder) + mem::replace(&mut self.buffer[buffer_start], placeholder) }; self.span = next.sp; self.token = next.tok; @@ -921,7 +917,7 @@ impl<'a> Parser<'a> { /// Advance the parser by one token and return the bumped token. pub fn bump_and_get(&mut self) -> token::Token { - let old_token = replace(&mut self.token, token::Underscore); + let old_token = mem::replace(&mut self.token, token::Underscore); self.bump(); old_token } @@ -2100,14 +2096,12 @@ impl<'a> Parser<'a> { ExprSlice(expr, start, end, mutbl) } - pub fn mk_field(&mut self, expr: P, ident: ast::SpannedIdent, - tys: Vec>) -> ast::Expr_ { - ExprField(expr, ident, tys) + pub fn mk_field(&mut self, expr: P, ident: ast::SpannedIdent) -> ast::Expr_ { + ExprField(expr, ident) } - pub fn mk_tup_field(&mut self, expr: P, idx: codemap::Spanned, - tys: Vec>) -> ast::Expr_ { - ExprTupField(expr, idx, tys) + pub fn mk_tup_field(&mut self, expr: P, idx: codemap::Spanned) -> ast::Expr_ { + ExprTupField(expr, idx) } pub fn mk_assign_op(&mut self, binop: ast::BinOp, @@ -2462,7 +2456,7 @@ impl<'a> Parser<'a> { } let id = spanned(dot, hi, i); - let field = self.mk_field(e, id, tys); + let field = self.mk_field(e, id); e = self.mk_expr(lo, hi, field); } } @@ -2481,7 +2475,7 @@ impl<'a> Parser<'a> { match index { Some(n) => { let id = spanned(dot, hi, n); - let field = self.mk_tup_field(e, id, Vec::new()); + let field = self.mk_tup_field(e, id); e = self.mk_expr(lo, hi, field); } None => { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4ce0d74bd37..2b80be0bf2a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1734,29 +1734,15 @@ impl<'a> State<'a> { try!(self.word_space("=")); try!(self.print_expr(&**rhs)); } - ast::ExprField(ref expr, id, ref tys) => { + ast::ExprField(ref expr, id) => { try!(self.print_expr(&**expr)); try!(word(&mut self.s, ".")); try!(self.print_ident(id.node)); - if tys.len() > 0u { - try!(word(&mut self.s, "::<")); - try!(self.commasep( - Inconsistent, tys.as_slice(), - |s, ty| s.print_type(&**ty))); - try!(word(&mut self.s, ">")); - } } - ast::ExprTupField(ref expr, id, ref tys) => { + ast::ExprTupField(ref expr, id) => { try!(self.print_expr(&**expr)); try!(word(&mut self.s, ".")); try!(self.print_uint(id.node)); - if tys.len() > 0u { - try!(word(&mut self.s, "::<")); - try!(self.commasep( - Inconsistent, tys.as_slice(), - |s, ty| s.print_type(&**ty))); - try!(word(&mut self.s, ">")); - } } ast::ExprIndex(ref expr, ref index) => { try!(self.print_expr(&**expr)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a0bdd739113..3f87dbc0740 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -838,17 +838,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(&**right_expression); visitor.visit_expr(&**left_expression) } - ExprField(ref subexpression, _, ref types) => { + ExprField(ref subexpression, _) => { visitor.visit_expr(&**subexpression); - for typ in types.iter() { - visitor.visit_ty(&**typ) - } } - ExprTupField(ref subexpression, _, ref types) => { + ExprTupField(ref subexpression, _) => { visitor.visit_expr(&**subexpression); - for typ in types.iter() { - visitor.visit_ty(&**typ) - } } ExprIndex(ref main_expression, ref index_expression) => { visitor.visit_expr(&**main_expression); -- cgit 1.4.1-3-g733a5 From 3293ab14e24d136d0482bb18afef577aebed251e Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 21 Nov 2014 17:10:42 -0500 Subject: Deprecate MaybeOwned[Vector] in favor of Cow --- src/libcollections/hash/mod.rs | 8 +++ src/libcollections/str.rs | 54 +++++++++++++++++---- src/libcollections/string.rs | 48 +++++++++++------- src/libcollections/vec.rs | 22 +++++++++ src/libcore/borrow.rs | 69 ++++++++++++++++++++++++++ src/libgraphviz/lib.rs | 63 ++++++++++++------------ src/libgraphviz/maybe_owned_vec.rs | 10 ++++ src/libregex/re.rs | 16 +++--- src/librustc/middle/borrowck/graphviz.rs | 5 +- src/librustc/middle/cfg/graphviz.rs | 12 ++--- src/libstd/path/mod.rs | 6 +-- src/libstd/path/posix.rs | 4 +- src/libstd/path/windows.rs | 4 +- src/libstd/prelude.rs | 3 +- src/libstd/rt/mod.rs | 4 +- src/libstd/task.rs | 20 ++++---- src/libsyntax/parse/lexer/mod.rs | 8 +-- src/libsyntax/parse/parser.rs | 4 +- src/test/run-fail/panic-task-name-send-str.rs | 2 +- src/test/run-pass/send_str_hashmap.rs | 70 +++++++++++++-------------- src/test/run-pass/send_str_treemap.rs | 66 ++++++++++++------------- 21 files changed, 326 insertions(+), 172 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index b1ff3da947b..4173ffc5d2f 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -67,6 +67,7 @@ use core::prelude::*; use alloc::boxed::Box; use alloc::rc::Rc; +use core::borrow::{Cow, ToOwned}; use core::intrinsics::TypeId; use core::mem; use core::num::Int; @@ -284,6 +285,13 @@ impl, U: Hash> Hash for Result { } } +impl<'a, T, Sized? B, S> Hash for Cow<'a, T, B> where B: Hash + ToOwned { + #[inline] + fn hash(&self, state: &mut S) { + Hash::hash(&**self, state) + } +} + ////////////////////////////////////////////////////////////////////////////// #[cfg(test)] diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 9982eaefff8..7b53fead6b2 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -54,7 +54,7 @@ pub use self::MaybeOwned::*; use self::RecompositionState::*; use self::DecompositionType::*; -use core::borrow::{BorrowFrom, ToOwned}; +use core::borrow::{BorrowFrom, Cow, ToOwned}; use core::default::Default; use core::fmt; use core::cmp; @@ -67,7 +67,7 @@ use core::prelude::{range}; use hash; use ring_buf::RingBuf; -use string::{String, ToString}; +use string::String; use unicode; use vec::Vec; @@ -425,6 +425,7 @@ Section: MaybeOwned /// A string type that can hold either a `String` or a `&str`. /// This can be useful as an optimization when an allocation is sometimes /// needed but not always. +#[deprecated = "use std::str::CowString"] pub enum MaybeOwned<'a> { /// A borrowed string. Slice(&'a str), @@ -432,15 +433,16 @@ pub enum MaybeOwned<'a> { Owned(String) } -/// A specialization of `MaybeOwned` to be sendable. -pub type SendStr = MaybeOwned<'static>; +/// A specialization of `CowString` to be sendable. +pub type SendStr = CowString<'static>; +#[deprecated = "use std::str::CowString"] impl<'a> MaybeOwned<'a> { /// Returns `true` if this `MaybeOwned` wraps an owned string. /// /// # Example /// - /// ```rust + /// ``` ignore /// let string = String::from_str("orange"); /// let maybe_owned_string = string.into_maybe_owned(); /// assert_eq!(true, maybe_owned_string.is_owned()); @@ -457,7 +459,7 @@ impl<'a> MaybeOwned<'a> { /// /// # Example /// - /// ```rust + /// ``` ignore /// let string = "orange"; /// let maybe_owned_string = string.as_slice().into_maybe_owned(); /// assert_eq!(true, maybe_owned_string.is_slice()); @@ -475,46 +477,56 @@ impl<'a> MaybeOwned<'a> { pub fn len(&self) -> uint { self.as_slice().len() } /// Returns true if the string contains no bytes + #[allow(deprecated)] #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } } +#[deprecated = "use std::borrow::IntoCow"] /// Trait for moving into a `MaybeOwned`. pub trait IntoMaybeOwned<'a> { /// Moves `self` into a `MaybeOwned`. fn into_maybe_owned(self) -> MaybeOwned<'a>; } +#[deprecated = "use std::borrow::IntoCow"] +#[allow(deprecated)] impl<'a> IntoMaybeOwned<'a> for String { /// # Example /// - /// ```rust + /// ``` ignore /// let owned_string = String::from_str("orange"); /// let maybe_owned_string = owned_string.into_maybe_owned(); /// assert_eq!(true, maybe_owned_string.is_owned()); /// ``` + #[allow(deprecated)] #[inline] fn into_maybe_owned(self) -> MaybeOwned<'a> { Owned(self) } } +#[deprecated = "use std::borrow::IntoCow"] +#[allow(deprecated)] impl<'a> IntoMaybeOwned<'a> for &'a str { /// # Example /// - /// ```rust + /// ``` ignore /// let string = "orange"; /// let maybe_owned_str = string.as_slice().into_maybe_owned(); /// assert_eq!(false, maybe_owned_str.is_owned()); /// ``` + #[allow(deprecated)] #[inline] fn into_maybe_owned(self) -> MaybeOwned<'a> { Slice(self) } } +#[allow(deprecated)] +#[deprecated = "use std::borrow::IntoCow"] impl<'a> IntoMaybeOwned<'a> for MaybeOwned<'a> { /// # Example /// - /// ```rust + /// ``` ignore /// let str = "orange"; /// let maybe_owned_str = str.as_slice().into_maybe_owned(); /// let maybe_maybe_owned_str = maybe_owned_str.into_maybe_owned(); @@ -524,6 +536,7 @@ impl<'a> IntoMaybeOwned<'a> for MaybeOwned<'a> { fn into_maybe_owned(self) -> MaybeOwned<'a> { self } } +#[deprecated = "use std::str::CowString"] impl<'a> PartialEq for MaybeOwned<'a> { #[inline] fn eq(&self, other: &MaybeOwned) -> bool { @@ -531,8 +544,10 @@ impl<'a> PartialEq for MaybeOwned<'a> { } } +#[deprecated = "use std::str::CowString"] impl<'a> Eq for MaybeOwned<'a> {} +#[deprecated = "use std::str::CowString"] impl<'a> PartialOrd for MaybeOwned<'a> { #[inline] fn partial_cmp(&self, other: &MaybeOwned) -> Option { @@ -540,6 +555,7 @@ impl<'a> PartialOrd for MaybeOwned<'a> { } } +#[deprecated = "use std::str::CowString"] impl<'a> Ord for MaybeOwned<'a> { #[inline] fn cmp(&self, other: &MaybeOwned) -> Ordering { @@ -547,6 +563,7 @@ impl<'a> Ord for MaybeOwned<'a> { } } +#[deprecated = "use std::str::CowString"] impl<'a, S: Str> Equiv for MaybeOwned<'a> { #[inline] fn equiv(&self, other: &S) -> bool { @@ -554,7 +571,9 @@ impl<'a, S: Str> Equiv for MaybeOwned<'a> { } } +#[deprecated = "use std::str::CowString"] impl<'a> Str for MaybeOwned<'a> { + #[allow(deprecated)] #[inline] fn as_slice<'b>(&'b self) -> &'b str { match *self { @@ -564,7 +583,9 @@ impl<'a> Str for MaybeOwned<'a> { } } +#[deprecated = "use std::str::CowString"] impl<'a> StrAllocating for MaybeOwned<'a> { + #[allow(deprecated)] #[inline] fn into_string(self) -> String { match self { @@ -574,7 +595,9 @@ impl<'a> StrAllocating for MaybeOwned<'a> { } } +#[deprecated = "use std::str::CowString"] impl<'a> Clone for MaybeOwned<'a> { + #[allow(deprecated)] #[inline] fn clone(&self) -> MaybeOwned<'a> { match *self { @@ -584,11 +607,14 @@ impl<'a> Clone for MaybeOwned<'a> { } } +#[deprecated = "use std::str::CowString"] impl<'a> Default for MaybeOwned<'a> { + #[allow(deprecated)] #[inline] fn default() -> MaybeOwned<'a> { Slice("") } } +#[deprecated = "use std::str::CowString"] impl<'a, H: hash::Writer> hash::Hash for MaybeOwned<'a> { #[inline] fn hash(&self, hasher: &mut H) { @@ -596,6 +622,7 @@ impl<'a, H: hash::Writer> hash::Hash for MaybeOwned<'a> { } } +#[deprecated = "use std::str::CowString"] impl<'a> fmt::Show for MaybeOwned<'a> { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -613,7 +640,7 @@ impl BorrowFrom for str { #[unstable = "trait is unstable"] impl ToOwned for str { - fn to_owned(&self) -> String { self.to_string() } + fn to_owned(&self) -> String { self.into_string() } } /// Unsafe string operations. @@ -622,6 +649,13 @@ pub mod raw { pub use core::str::raw::{slice_unchecked}; } +/* +Section: CowString +*/ + +/// A clone-on-write string +pub type CowString<'a> = Cow<'a, String, str>; + /* Section: Trait implementations */ diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index dd9dad9a42f..38b67fbd744 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -14,6 +14,7 @@ use core::prelude::*; +use core::borrow::{Cow, IntoCow}; use core::default::Default; use core::fmt; use core::mem; @@ -25,8 +26,7 @@ use core::raw::Slice as RawSlice; use hash; use slice::CloneSliceAllocPrelude; use str; -use str::{CharRange, FromStr, StrAllocating, MaybeOwned, Owned}; -use str::Slice as MaybeOwnedSlice; // So many `Slice`s... +use str::{CharRange, CowString, FromStr, StrAllocating, Owned}; use vec::{DerefVec, Vec, as_vec}; /// A growable string stored as a UTF-8 encoded buffer. @@ -121,9 +121,9 @@ impl String { /// assert_eq!(output.as_slice(), "Hello \uFFFDWorld"); /// ``` #[unstable = "return type may change"] - pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> MaybeOwned<'a> { + pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> CowString<'a> { if str::is_utf8(v) { - return MaybeOwnedSlice(unsafe { mem::transmute(v) }) + return Cow::Borrowed(unsafe { mem::transmute(v) }) } static TAG_CONT_U8: u8 = 128u8; @@ -234,7 +234,7 @@ impl String { res.as_mut_vec().push_all(v[subseqidx..total]) }; } - Owned(res.into_string()) + Cow::Owned(res.into_string()) } /// Decode a UTF-16 encoded vector `v` into a `String`, returning `None` @@ -868,6 +868,18 @@ impl ToString for T { } } +impl IntoCow<'static, String, str> for String { + fn into_cow(self) -> CowString<'static> { + Cow::Owned(self) + } +} + +impl<'a> IntoCow<'a, String, str> for &'a str { + fn into_cow(self) -> CowString<'a> { + Cow::Borrowed(self) + } +} + /// Unsafe operations #[deprecated] pub mod raw { @@ -921,11 +933,11 @@ mod tests { use std::prelude::*; use test::Bencher; + use slice::CloneSliceAllocPrelude; + use str::{Str, StrPrelude}; use str; - use str::{Str, StrPrelude, Owned}; use super::{as_string, String, ToString}; use vec::Vec; - use slice::CloneSliceAllocPrelude; #[test] fn test_as_string() { @@ -955,39 +967,39 @@ mod tests { #[test] fn test_from_utf8_lossy() { let xs = b"hello"; - assert_eq!(String::from_utf8_lossy(xs), str::Slice("hello")); + assert_eq!(String::from_utf8_lossy(xs), "hello".into_cow()); let xs = "ศไทย中华Việt Nam".as_bytes(); - assert_eq!(String::from_utf8_lossy(xs), str::Slice("ศไทย中华Việt Nam")); + assert_eq!(String::from_utf8_lossy(xs), "ศไทย中华Việt Nam".into_cow()); let xs = b"Hello\xC2 There\xFF Goodbye"; assert_eq!(String::from_utf8_lossy(xs), - Owned(String::from_str("Hello\uFFFD There\uFFFD Goodbye"))); + String::from_str("Hello\uFFFD There\uFFFD Goodbye").into_cow()); let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; assert_eq!(String::from_utf8_lossy(xs), - Owned(String::from_str("Hello\uFFFD\uFFFD There\uFFFD Goodbye"))); + String::from_str("Hello\uFFFD\uFFFD There\uFFFD Goodbye").into_cow()); let xs = b"\xF5foo\xF5\x80bar"; assert_eq!(String::from_utf8_lossy(xs), - Owned(String::from_str("\uFFFDfoo\uFFFD\uFFFDbar"))); + String::from_str("\uFFFDfoo\uFFFD\uFFFDbar").into_cow()); let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; assert_eq!(String::from_utf8_lossy(xs), - Owned(String::from_str("\uFFFDfoo\uFFFDbar\uFFFDbaz"))); + String::from_str("\uFFFDfoo\uFFFDbar\uFFFDbaz").into_cow()); let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; assert_eq!(String::from_utf8_lossy(xs), - Owned(String::from_str("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz"))); + String::from_str("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz").into_cow()); let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; - assert_eq!(String::from_utf8_lossy(xs), Owned(String::from_str("\uFFFD\uFFFD\uFFFD\uFFFD\ - foo\U00010000bar"))); + assert_eq!(String::from_utf8_lossy(xs), String::from_str("\uFFFD\uFFFD\uFFFD\uFFFD\ + foo\U00010000bar").into_cow()); // surrogates let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; - assert_eq!(String::from_utf8_lossy(xs), Owned(String::from_str("\uFFFD\uFFFD\uFFFDfoo\ - \uFFFD\uFFFD\uFFFDbar"))); + assert_eq!(String::from_utf8_lossy(xs), String::from_str("\uFFFD\uFFFD\uFFFDfoo\ + \uFFFD\uFFFD\uFFFDbar").into_cow()); } #[test] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a3291e01942..ec520a93c1e 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -16,6 +16,7 @@ use core::prelude::*; use alloc::boxed::Box; use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; +use core::borrow::{Cow, IntoCow}; use core::cmp::max; use core::default::Default; use core::fmt; @@ -107,6 +108,27 @@ pub struct Vec { cap: uint, } +/// A clone-on-write vector +pub type CowVec<'a, T> = Cow<'a, Vec, [T]>; + +impl<'a, T> FromIterator for CowVec<'a, T> where T: Clone { + fn from_iter>(it: I) -> CowVec<'a, T> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +impl<'a, T: 'a> IntoCow<'a, Vec, [T]> for Vec where T: Clone { + fn into_cow(self) -> CowVec<'a, T> { + Cow::Owned(self) + } +} + +impl<'a, T> IntoCow<'a, Vec, [T]> for &'a [T] where T: Clone { + fn into_cow(self) -> CowVec<'a, T> { + Cow::Borrowed(self) + } +} + impl Vec { /// Constructs a new, empty `Vec`. /// diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index da0e23e1a5e..06fda8d6092 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -45,8 +45,11 @@ #![unstable = "recently added as part of collections reform"] use clone::Clone; +use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use fmt; use kinds::Sized; use ops::Deref; +use option::Option; use self::Cow::*; /// A trait for borrowing data. @@ -81,6 +84,24 @@ impl<'a, Sized? T> BorrowFromMut<&'a mut T> for T { fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned } } +impl<'a, T, Sized? B> BorrowFrom> for B where B: ToOwned { + fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B { + &**owned + } +} + +/// Trait for moving into a `Cow` +pub trait IntoCow<'a, T, Sized? B> { + /// Moves `self` into `Cow` + fn into_cow(self) -> Cow<'a, T, B>; +} + +impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned { + fn into_cow(self) -> Cow<'a, T, B> { + self + } +} + /// A generalization of Clone to borrowed data. pub trait ToOwned for Sized?: BorrowFrom { /// Create owned data from borrowed data, usually by copying. @@ -139,6 +160,22 @@ impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned { Owned(owned) => owned } } + + /// Returns true if this `Cow` wraps a borrowed value + pub fn is_borrowed(&self) -> bool { + match *self { + Borrowed(_) => true, + _ => false, + } + } + + /// Returns true if this `Cow` wraps an owned value + pub fn is_owned(&self) -> bool { + match *self { + Owned(_) => true, + _ => false, + } + } } impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned { @@ -149,3 +186,35 @@ impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned { } } } + +impl<'a, T, Sized? B> Eq for Cow<'a, T, B> where B: Eq + ToOwned {} + +impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned { + #[inline] + fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +impl<'a, T, Sized? B> PartialEq for Cow<'a, T, B> where B: PartialEq + ToOwned { + #[inline] + fn eq(&self, other: &Cow<'a, T, B>) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +impl<'a, T, Sized? B> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned { + #[inline] + fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +impl<'a, T, Sized? B> fmt::Show for Cow<'a, T, B> where B: fmt::Show + ToOwned, T: fmt::Show { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Show::fmt(b, f), + Owned(ref o) => fmt::Show::fmt(o, f), + } + } +} diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 3ad546edf8d..f149ec509af 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -37,7 +37,7 @@ pairs of ints, representing the edges (the node set is implicit). Each node label is derived directly from the int representing the node, while the edge labels are all empty strings. -This example also illustrates how to use `MaybeOwnedVector` to return +This example also illustrates how to use `CowVec` to return an owned vector or a borrowed slice as appropriate: we construct the node vector from scratch, but borrow the edge list (rather than constructing a copy of all the edges from scratch). @@ -48,7 +48,6 @@ which is cyclic. ```rust use graphviz as dot; -use graphviz::maybe_owned_vec::IntoMaybeOwnedVector; type Nd = int; type Ed = (int,int); @@ -77,12 +76,12 @@ impl<'a> dot::GraphWalk<'a, Nd, Ed> for Edges { } nodes.sort(); nodes.dedup(); - nodes.into_maybe_owned() + nodes.into_cow() } fn edges(&'a self) -> dot::Edges<'a,Ed> { let &Edges(ref edges) = self; - edges.as_slice().into_maybe_owned() + edges.as_slice().into_cow() } fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s } @@ -137,8 +136,8 @@ edges stored in `self`. Since both the set of nodes and the set of edges are always constructed from scratch via iterators, we use the `collect()` method from the `Iterator` trait to collect the nodes and edges into freshly -constructed growable `Vec` values (rather use the `into_maybe_owned` -from the `IntoMaybeOwnedVector` trait as was used in the first example +constructed growable `Vec` values (rather use the `into_cow` +from the `IntoCow` trait as was used in the first example above). The output from this example renders four nodes that make up the @@ -148,7 +147,6 @@ entity `&sube`). ```rust use graphviz as dot; -use std::str; type Nd = uint; type Ed<'a> = &'a (uint, uint); @@ -168,10 +166,10 @@ impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph { dot::Id::new(format!("N{}", n)).unwrap() } fn node_label<'a>(&'a self, n: &Nd) -> dot::LabelText<'a> { - dot::LabelStr(str::Slice(self.nodes[*n].as_slice())) + dot::LabelStr(self.nodes[*n].as_slice().into_cow()) } fn edge_label<'a>(&'a self, _: &Ed) -> dot::LabelText<'a> { - dot::LabelStr(str::Slice("⊆")) + dot::LabelStr("⊆".into_cow()) } } @@ -204,7 +202,6 @@ Hasse-diagram for the subsets of the set `{x, y}`. ```rust use graphviz as dot; -use std::str; type Nd<'a> = (uint, &'a str); type Ed<'a> = (Nd<'a>, Nd<'a>); @@ -225,10 +222,10 @@ impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph { } fn node_label<'a>(&'a self, n: &Nd<'a>) -> dot::LabelText<'a> { let &(i, _) = n; - dot::LabelStr(str::Slice(self.nodes[i].as_slice())) + dot::LabelStr(self.nodes[i].as_slice().into_cow()) } fn edge_label<'a>(&'a self, _: &Ed<'a>) -> dot::LabelText<'a> { - dot::LabelStr(str::Slice("⊆")) + dot::LabelStr("⊆".into_cow()) } } @@ -279,8 +276,8 @@ pub fn main() { pub use self::LabelText::*; use std::io; -use std::str; -use self::maybe_owned_vec::MaybeOwnedVector; +use std::str::CowString; +use std::vec::CowVec; pub mod maybe_owned_vec; @@ -290,7 +287,7 @@ pub enum LabelText<'a> { /// /// Occurrences of backslashes (`\`) are escaped, and thus appear /// as backslashes in the rendered label. - LabelStr(str::MaybeOwned<'a>), + LabelStr(CowString<'a>), /// This kind of label uses the graphviz label escString type: /// http://www.graphviz.org/content/attrs#kescString @@ -302,7 +299,7 @@ pub enum LabelText<'a> { /// to break a line (centering the line preceding the `\n`), there /// are also the escape sequences `\l` which left-justifies the /// preceding line and `\r` which right-justifies it. - EscStr(str::MaybeOwned<'a>), + EscStr(CowString<'a>), } // There is a tension in the design of the labelling API. @@ -339,7 +336,7 @@ pub enum LabelText<'a> { /// `Id` is a Graphviz `ID`. pub struct Id<'a> { - name: str::MaybeOwned<'a>, + name: CowString<'a>, } impl<'a> Id<'a> { @@ -357,10 +354,10 @@ impl<'a> Id<'a> { /// /// Passing an invalid string (containing spaces, brackets, /// quotes, ...) will return an empty `Err` value. - pub fn new>(name: Name) -> Result, ()> { - let name = name.into_maybe_owned(); + pub fn new>(name: Name) -> Result, ()> { + let name = name.into_cow(); { - let mut chars = name.as_slice().chars(); + let mut chars = name.chars(); match chars.next() { Some(c) if is_letter_or_underscore(c) => { ; }, _ => return Err(()) @@ -383,10 +380,10 @@ impl<'a> Id<'a> { } pub fn as_slice(&'a self) -> &'a str { - self.name.as_slice() + &*self.name } - pub fn name(self) -> str::MaybeOwned<'a> { + pub fn name(self) -> CowString<'a> { self.name } } @@ -421,7 +418,7 @@ pub trait Labeller<'a,N,E> { /// default is in fact the empty string. fn edge_label(&'a self, e: &E) -> LabelText<'a> { let _ignored = e; - LabelStr(str::Slice("")) + LabelStr("".into_cow()) } } @@ -454,11 +451,11 @@ impl<'a> LabelText<'a> { /// yields same content as self. The result obeys the law /// render(`lt`) == render(`EscStr(lt.pre_escaped_content())`) for /// all `lt: LabelText`. - fn pre_escaped_content(self) -> str::MaybeOwned<'a> { + fn pre_escaped_content(self) -> CowString<'a> { match self { EscStr(s) => s, - LabelStr(s) => if s.as_slice().contains_char('\\') { - str::Owned(s.as_slice().escape_default()) + LabelStr(s) => if s.contains_char('\\') { + s.escape_default().into_cow() } else { s }, @@ -476,12 +473,12 @@ impl<'a> LabelText<'a> { let suffix = suffix.pre_escaped_content(); prefix.push_str(r"\n\n"); prefix.push_str(suffix.as_slice()); - EscStr(str::Owned(prefix)) + EscStr(prefix.into_cow()) } } -pub type Nodes<'a,N> = MaybeOwnedVector<'a,N>; -pub type Edges<'a,E> = MaybeOwnedVector<'a,E>; +pub type Nodes<'a,N> = CowVec<'a,N>; +pub type Edges<'a,E> = CowVec<'a,E>; // (The type parameters in GraphWalk should be associated items, // when/if Rust supports such.) @@ -496,7 +493,7 @@ pub type Edges<'a,E> = MaybeOwnedVector<'a,E>; /// that is bound by the self lifetime `'a`. /// /// The `nodes` and `edges` method each return instantiations of -/// `MaybeOwnedVector` to leave implementers the freedom to create +/// `CowVec` to leave implementers the freedom to create /// entirely new vectors or to pass back slices into internally owned /// vectors. pub trait GraphWalk<'a, N, E> { @@ -512,7 +509,7 @@ pub trait GraphWalk<'a, N, E> { /// Renders directed graph `g` into the writer `w` in DOT syntax. /// (Main entry point for the library.) -pub fn render<'a, N:'a, E:'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>( +pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>( g: &'a G, w: &mut W) -> io::IoResult<()> { @@ -647,12 +644,12 @@ mod tests { } fn node_label(&'a self, n: &Node) -> LabelText<'a> { match self.node_labels[*n] { - Some(ref l) => LabelStr(str::Slice(l.as_slice())), + Some(ref l) => LabelStr(l.into_cow()), None => LabelStr(id_name(n).name()), } } fn edge_label(&'a self, e: & &'a Edge) -> LabelText<'a> { - LabelStr(str::Slice(e.label.as_slice())) + LabelStr(e.label.into_cow()) } } diff --git a/src/libgraphviz/maybe_owned_vec.rs b/src/libgraphviz/maybe_owned_vec.rs index 70b3971c6b8..6482a514115 100644 --- a/src/libgraphviz/maybe_owned_vec.rs +++ b/src/libgraphviz/maybe_owned_vec.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deprecated = "use std::vec::CowVec"] + pub use self::MaybeOwnedVector::*; use std::default::Default; @@ -46,12 +48,16 @@ pub trait IntoMaybeOwnedVector<'a,T> { fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>; } +#[allow(deprecated)] impl<'a,T:'a> IntoMaybeOwnedVector<'a,T> for Vec { + #[allow(deprecated)] #[inline] fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) } } +#[allow(deprecated)] impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] { + #[allow(deprecated)] #[inline] fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) } } @@ -66,6 +72,7 @@ impl<'a,T> MaybeOwnedVector<'a,T> { pub fn len(&self) -> uint { self.as_slice().len() } + #[allow(deprecated)] pub fn is_empty(&self) -> bool { self.len() == 0 } } @@ -114,6 +121,7 @@ impl<'b,T> AsSlice for MaybeOwnedVector<'b,T> { } impl<'a,T> FromIterator for MaybeOwnedVector<'a,T> { + #[allow(deprecated)] fn from_iter>(iterator: I) -> MaybeOwnedVector<'a,T> { // If we are building from scratch, might as well build the // most flexible variant. @@ -143,6 +151,7 @@ impl<'a,T:Clone> CloneSliceAllocPrelude for MaybeOwnedVector<'a,T> { } impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> { + #[allow(deprecated)] fn clone(&self) -> MaybeOwnedVector<'a, T> { match *self { Growable(ref v) => Growable(v.clone()), @@ -152,6 +161,7 @@ impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> { } impl<'a, T> Default for MaybeOwnedVector<'a, T> { + #[allow(deprecated)] fn default() -> MaybeOwnedVector<'a, T> { Growable(Vec::new()) } diff --git a/src/libregex/re.rs b/src/libregex/re.rs index e70491a785c..58ce72a3173 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -13,7 +13,7 @@ pub use self::Regex::*; use std::collections::HashMap; use std::fmt; -use std::str::{MaybeOwned, Owned, Slice}; +use std::str::CowString; use compile::Program; use parse; @@ -565,25 +565,25 @@ pub trait Replacer { /// /// The `'a` lifetime refers to the lifetime of a borrowed string when /// a new owned string isn't needed (e.g., for `NoExpand`). - fn reg_replace<'a>(&'a mut self, caps: &Captures) -> MaybeOwned<'a>; + fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a>; } impl<'t> Replacer for NoExpand<'t> { - fn reg_replace<'a>(&'a mut self, _: &Captures) -> MaybeOwned<'a> { + fn reg_replace<'a>(&'a mut self, _: &Captures) -> CowString<'a> { let NoExpand(s) = *self; - Slice(s) + s.into_cow() } } impl<'t> Replacer for &'t str { - fn reg_replace<'a>(&'a mut self, caps: &Captures) -> MaybeOwned<'a> { - Owned(caps.expand(*self)) + fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a> { + caps.expand(*self).into_cow() } } impl<'t> Replacer for |&Captures|: 't -> String { - fn reg_replace<'a>(&'a mut self, caps: &Captures) -> MaybeOwned<'a> { - Owned((*self)(caps)) + fn reg_replace<'a>(&'a mut self, caps: &Captures) -> CowString<'a> { + (*self)(caps).into_cow() } } diff --git a/src/librustc/middle/borrowck/graphviz.rs b/src/librustc/middle/borrowck/graphviz.rs index 4a2f57735e1..c12a81cc739 100644 --- a/src/librustc/middle/borrowck/graphviz.rs +++ b/src/librustc/middle/borrowck/graphviz.rs @@ -26,7 +26,6 @@ use middle::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit}; use middle::dataflow; use std::rc::Rc; -use std::str; #[deriving(Show)] pub enum Variant { @@ -137,8 +136,8 @@ impl<'a, 'tcx> dot::Labeller<'a, Node<'a>, Edge<'a>> for DataflowLabeller<'a, 't let suffix = self.dataflow_for(dataflow::Exit, n); let inner_label = self.inner.node_label(n); inner_label - .prefix_line(dot::LabelStr(str::Owned(prefix))) - .suffix_line(dot::LabelStr(str::Owned(suffix))) + .prefix_line(dot::LabelStr(prefix.into_cow())) + .suffix_line(dot::LabelStr(suffix.into_cow())) } fn edge_label(&'a self, e: &Edge<'a>) -> dot::LabelText<'a> { self.inner.edge_label(e) } } diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index ba6dd2a5107..8e0e8ee1c5e 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -58,16 +58,16 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> { if i == self.cfg.entry { - dot::LabelStr("entry".into_maybe_owned()) + dot::LabelStr("entry".into_cow()) } else if i == self.cfg.exit { - dot::LabelStr("exit".into_maybe_owned()) + dot::LabelStr("exit".into_cow()) } else if n.data.id == ast::DUMMY_NODE_ID { - dot::LabelStr("(dummy_node)".into_maybe_owned()) + dot::LabelStr("(dummy_node)".into_cow()) } else { let s = self.ast_map.node_to_string(n.data.id); // left-aligns the lines let s = replace_newline_with_backslash_l(s); - dot::EscStr(s.into_maybe_owned()) + dot::EscStr(s.into_cow()) } } @@ -86,7 +86,7 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { label.push_str(format!("exiting scope_{} {}", i, s.as_slice()).as_slice()); } - dot::EscStr(label.into_maybe_owned()) + dot::EscStr(label.into_cow()) } } @@ -94,7 +94,7 @@ impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG { fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { let mut v = Vec::new(); self.graph.each_node(|i, nd| { v.push((i, nd)); true }); - dot::maybe_owned_vec::Growable(v) + v.into_cow() } fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.graph.all_edges().iter().collect() diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index a185a29a700..ce3440ead40 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -74,7 +74,7 @@ use fmt; use iter::Iterator; use option::{Option, None, Some}; use str; -use str::{MaybeOwned, Str, StrPrelude}; +use str::{CowString, MaybeOwned, Str, StrPrelude}; use string::String; use slice::{AsSlice, CloneSliceAllocPrelude}; use slice::{PartialEqSlicePrelude, SlicePrelude}; @@ -830,7 +830,7 @@ pub struct Display<'a, P:'a> { impl<'a, P: GenericPath> fmt::Show for Display<'a, P> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.as_maybe_owned().as_slice().fmt(f) + self.as_cow().fmt(f) } } @@ -840,7 +840,7 @@ impl<'a, P: GenericPath> Display<'a, P> { /// If the path is not UTF-8, invalid sequences will be replaced with the /// Unicode replacement char. This involves allocation. #[inline] - pub fn as_maybe_owned(&self) -> MaybeOwned<'a> { + pub fn as_cow(&self) -> CowString<'a> { String::from_utf8_lossy(if self.filename { match self.path.filename() { None => { diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 2b444fdc32b..bdce759a1df 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -551,14 +551,14 @@ mod tests { ($path:expr, $exp:expr) => ( { let path = Path::new($path); - let mo = path.display().as_maybe_owned(); + let mo = path.display().as_cow(); assert!(mo.as_slice() == $exp); } ); ($path:expr, $exp:expr, filename) => ( { let path = Path::new($path); - let mo = path.filename_display().as_maybe_owned(); + let mo = path.filename_display().as_cow(); assert!(mo.as_slice() == $exp); } ) diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 9f81de72980..fc367710131 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1326,10 +1326,10 @@ mod tests { assert_eq!(path.filename_display().to_string(), "".to_string()); let path = Path::new("foo"); - let mo = path.display().as_maybe_owned(); + let mo = path.display().as_cow(); assert_eq!(mo.as_slice(), "foo"); let path = Path::new(b"\\"); - let mo = path.filename_display().as_maybe_owned(); + let mo = path.filename_display().as_cow(); assert_eq!(mo.as_slice(), ""); } diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 65f45c3f97e..756ff1c58f3 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -58,6 +58,7 @@ #[doc(no_inline)] pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr}; #[doc(no_inline)] pub use ascii::IntoBytes; +#[doc(no_inline)] pub use borrow::IntoCow; #[doc(no_inline)] pub use c_str::ToCStr; #[doc(no_inline)] pub use char::{Char, UnicodeChar}; #[doc(no_inline)] pub use clone::Clone; @@ -78,7 +79,7 @@ #[doc(no_inline)] pub use result::Result::{Ok, Err}; #[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude}; #[doc(no_inline)] pub use str::{Str, StrVector, StrPrelude}; -#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrPrelude}; +#[doc(no_inline)] pub use str::{StrAllocating, UnicodeStrPrelude}; #[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4}; #[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8}; #[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12}; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 21b4edb6375..872a5452241 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -56,6 +56,7 @@ Several modules in `core` are clients of `rt`: #![allow(dead_code)] +use borrow::IntoCow; use failure; use rustrt; use os; @@ -113,7 +114,6 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int { use prelude::*; use rt; use rustrt::task::Task; - use str; let something_around_the_top_of_the_stack = 1; let addr = &something_around_the_top_of_the_stack as *const int; @@ -147,7 +147,7 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int { let mut main = Some(main); let mut task = box Task::new(Some((my_stack_bottom, my_stack_top)), Some(rustrt::thread::main_guard_page())); - task.name = Some(str::Slice("
")); + task.name = Some("
".into_cow()); drop(task.run(|| { unsafe { rustrt::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top); diff --git a/src/libstd/task.rs b/src/libstd/task.rs index c852b4efbd8..a0ee08570d9 100644 --- a/src/libstd/task.rs +++ b/src/libstd/task.rs @@ -44,16 +44,17 @@ will likely be renamed from `task` to `thread`."] use any::Any; +use borrow::IntoCow; +use boxed::Box; use comm::channel; use io::{Writer, stdio}; use kinds::{Send, marker}; use option::{None, Some, Option}; -use boxed::Box; use result::Result; use rustrt::local::Local; -use rustrt::task; use rustrt::task::Task; -use str::{Str, SendStr, IntoMaybeOwned}; +use rustrt::task; +use str::{Str, SendStr}; use string::{String, ToString}; use sync::Future; @@ -101,8 +102,8 @@ impl TaskBuilder { /// Name the task-to-be. Currently the name is used for identification /// only in panic messages. #[unstable = "IntoMaybeOwned will probably change."] - pub fn named>(mut self, name: T) -> TaskBuilder { - self.name = Some(name.into_maybe_owned()); + pub fn named>(mut self, name: T) -> TaskBuilder { + self.name = Some(name.into_cow()); self } @@ -264,12 +265,13 @@ pub fn failing() -> bool { #[cfg(test)] mod test { use any::{Any, AnyRefExt}; + use borrow::IntoCow; use boxed::BoxAny; - use result; + use prelude::*; use result::{Ok, Err}; - use string::String; + use result; use std::io::{ChanReader, ChanWriter}; - use prelude::*; + use string::String; use super::*; // !!! These tests are dangerous. If something is buggy, they will hang, !!! @@ -298,7 +300,7 @@ mod test { #[test] fn test_send_named_task() { - TaskBuilder::new().named("ada lovelace".into_maybe_owned()).try(proc() { + TaskBuilder::new().named("ada lovelace".into_cow()).try(proc() { assert!(name().unwrap() == "ada lovelace".to_string()); }).map_err(|_| ()).unwrap(); } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index a88029e087b..b5358e7d485 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -272,13 +272,13 @@ impl<'a> StringReader<'a> { /// Converts CRLF to LF in the given string, raising an error on bare CR. fn translate_crlf<'a>(&self, start: BytePos, - s: &'a str, errmsg: &'a str) -> str::MaybeOwned<'a> { + s: &'a str, errmsg: &'a str) -> str::CowString<'a> { let mut i = 0u; while i < s.len() { let str::CharRange { ch, next } = s.char_range_at(i); if ch == '\r' { if next < s.len() && s.char_at(next) == '\n' { - return translate_crlf_(self, start, s, errmsg, i).into_maybe_owned(); + return translate_crlf_(self, start, s, errmsg, i).into_cow(); } let pos = start + BytePos(i as u32); let end_pos = start + BytePos(next as u32); @@ -286,7 +286,7 @@ impl<'a> StringReader<'a> { } i = next; } - return s.into_maybe_owned(); + return s.into_cow(); fn translate_crlf_(rdr: &StringReader, start: BytePos, s: &str, errmsg: &str, mut i: uint) -> String { @@ -550,7 +550,7 @@ impl<'a> StringReader<'a> { let string = if has_cr { self.translate_crlf(start_bpos, string, "bare CR not allowed in block doc-comment") - } else { string.into_maybe_owned() }; + } else { string.into_cow() }; token::DocComment(token::intern(string.as_slice())) } else { token::Comment diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a9306c71240..c731a0005f8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4966,10 +4966,10 @@ impl<'a> Parser<'a> { let mut err = String::from_str("circular modules: "); let len = included_mod_stack.len(); for p in included_mod_stack.slice(i, len).iter() { - err.push_str(p.display().as_maybe_owned().as_slice()); + err.push_str(p.display().as_cow().as_slice()); err.push_str(" -> "); } - err.push_str(path.display().as_maybe_owned().as_slice()); + err.push_str(path.display().as_cow().as_slice()); self.span_fatal(id_sp, err.as_slice()); } None => () diff --git a/src/test/run-fail/panic-task-name-send-str.rs b/src/test/run-fail/panic-task-name-send-str.rs index 73fca246590..fb4fb5c2f70 100644 --- a/src/test/run-fail/panic-task-name-send-str.rs +++ b/src/test/run-fail/panic-task-name-send-str.rs @@ -12,7 +12,7 @@ fn main() { let r: Result = - ::std::task::TaskBuilder::new().named("send name".into_maybe_owned()) + ::std::task::TaskBuilder::new().named("send name".into_cow()) .try(proc() { panic!("test"); 3i diff --git a/src/test/run-pass/send_str_hashmap.rs b/src/test/run-pass/send_str_hashmap.rs index 55003a07b5b..ef485723c7e 100644 --- a/src/test/run-pass/send_str_hashmap.rs +++ b/src/test/run-pass/send_str_hashmap.rs @@ -10,51 +10,51 @@ extern crate collections; -use std::str::{SendStr, Owned, Slice}; use std::collections::HashMap; use std::option::Some; +use std::str::SendStr; pub fn main() { let mut map: HashMap = HashMap::new(); - assert!(map.insert(Slice("foo"), 42).is_none()); - assert!(map.insert(Owned("foo".to_string()), 42).is_some()); - assert!(map.insert(Slice("foo"), 42).is_some()); - assert!(map.insert(Owned("foo".to_string()), 42).is_some()); + assert!(map.insert("foo".into_cow(), 42).is_none()); + assert!(map.insert("foo".to_string().into_cow(), 42).is_some()); + assert!(map.insert("foo".into_cow(), 42).is_some()); + assert!(map.insert("foo".to_string().into_cow(), 42).is_some()); - assert!(map.insert(Slice("foo"), 43).is_some()); - assert!(map.insert(Owned("foo".to_string()), 44).is_some()); - assert!(map.insert(Slice("foo"), 45).is_some()); - assert!(map.insert(Owned("foo".to_string()), 46).is_some()); + assert!(map.insert("foo".into_cow(), 43).is_some()); + assert!(map.insert("foo".to_string().into_cow(), 44).is_some()); + assert!(map.insert("foo".into_cow(), 45).is_some()); + assert!(map.insert("foo".to_string().into_cow(), 46).is_some()); let v = 46; - assert_eq!(map.get(&Owned("foo".to_string())), Some(&v)); - assert_eq!(map.get(&Slice("foo")), Some(&v)); + assert_eq!(map.get(&"foo".to_string().into_cow()), Some(&v)); + assert_eq!(map.get(&"foo".into_cow()), Some(&v)); let (a, b, c, d) = (50, 51, 52, 53); - assert!(map.insert(Slice("abc"), a).is_none()); - assert!(map.insert(Owned("bcd".to_string()), b).is_none()); - assert!(map.insert(Slice("cde"), c).is_none()); - assert!(map.insert(Owned("def".to_string()), d).is_none()); - - assert!(map.insert(Slice("abc"), a).is_some()); - assert!(map.insert(Owned("bcd".to_string()), b).is_some()); - assert!(map.insert(Slice("cde"), c).is_some()); - assert!(map.insert(Owned("def".to_string()), d).is_some()); - - assert!(map.insert(Owned("abc".to_string()), a).is_some()); - assert!(map.insert(Slice("bcd"), b).is_some()); - assert!(map.insert(Owned("cde".to_string()), c).is_some()); - assert!(map.insert(Slice("def"), d).is_some()); - - assert_eq!(map.find_equiv("abc"), Some(&a)); - assert_eq!(map.find_equiv("bcd"), Some(&b)); - assert_eq!(map.find_equiv("cde"), Some(&c)); - assert_eq!(map.find_equiv("def"), Some(&d)); - - assert_eq!(map.find_equiv(&Slice("abc")), Some(&a)); - assert_eq!(map.find_equiv(&Slice("bcd")), Some(&b)); - assert_eq!(map.find_equiv(&Slice("cde")), Some(&c)); - assert_eq!(map.find_equiv(&Slice("def")), Some(&d)); + assert!(map.insert("abc".into_cow(), a).is_none()); + assert!(map.insert("bcd".to_string().into_cow(), b).is_none()); + assert!(map.insert("cde".into_cow(), c).is_none()); + assert!(map.insert("def".to_string().into_cow(), d).is_none()); + + assert!(map.insert("abc".into_cow(), a).is_some()); + assert!(map.insert("bcd".to_string().into_cow(), b).is_some()); + assert!(map.insert("cde".into_cow(), c).is_some()); + assert!(map.insert("def".to_string().into_cow(), d).is_some()); + + assert!(map.insert("abc".to_string().into_cow(), a).is_some()); + assert!(map.insert("bcd".into_cow(), b).is_some()); + assert!(map.insert("cde".to_string().into_cow(), c).is_some()); + assert!(map.insert("def".into_cow(), d).is_some()); + + assert_eq!(map.get("abc"), Some(&a)); + assert_eq!(map.get("bcd"), Some(&b)); + assert_eq!(map.get("cde"), Some(&c)); + assert_eq!(map.get("def"), Some(&d)); + + assert_eq!(map.get(&"abc".into_cow()), Some(&a)); + assert_eq!(map.get(&"bcd".into_cow()), Some(&b)); + assert_eq!(map.get(&"cde".into_cow()), Some(&c)); + assert_eq!(map.get(&"def".into_cow()), Some(&d)); } diff --git a/src/test/run-pass/send_str_treemap.rs b/src/test/run-pass/send_str_treemap.rs index 0d881419847..f72ca109b6e 100644 --- a/src/test/run-pass/send_str_treemap.rs +++ b/src/test/run-pass/send_str_treemap.rs @@ -10,56 +10,56 @@ extern crate collections; -use std::str::{SendStr, Owned, Slice}; -use std::string::ToString; use self::collections::TreeMap; use std::option::Some; +use std::str::SendStr; +use std::string::ToString; pub fn main() { let mut map: TreeMap = TreeMap::new(); - assert!(map.insert(Slice("foo"), 42).is_none()); - assert!(map.insert(Owned("foo".to_string()), 42).is_some()); - assert!(map.insert(Slice("foo"), 42).is_some()); - assert!(map.insert(Owned("foo".to_string()), 42).is_some()); + assert!(map.insert("foo".into_cow(), 42).is_none()); + assert!(map.insert("foo".to_string().into_cow(), 42).is_some()); + assert!(map.insert("foo".into_cow(), 42).is_some()); + assert!(map.insert("foo".to_string().into_cow(), 42).is_some()); - assert!(map.insert(Slice("foo"), 43).is_some()); - assert!(map.insert(Owned("foo".to_string()), 44).is_some()); - assert!(map.insert(Slice("foo"), 45).is_some()); - assert!(map.insert(Owned("foo".to_string()), 46).is_some()); + assert!(map.insert("foo".into_cow(), 43).is_some()); + assert!(map.insert("foo".to_string().into_cow(), 44).is_some()); + assert!(map.insert("foo".into_cow(), 45).is_some()); + assert!(map.insert("foo".to_string().into_cow(), 46).is_some()); let v = 46; - assert_eq!(map.get(&Owned("foo".to_string())), Some(&v)); - assert_eq!(map.get(&Slice("foo")), Some(&v)); + assert_eq!(map.get(&"foo".to_string().into_cow()), Some(&v)); + assert_eq!(map.get(&"foo".into_cow()), Some(&v)); let (a, b, c, d) = (50, 51, 52, 53); - assert!(map.insert(Slice("abc"), a).is_none()); - assert!(map.insert(Owned("bcd".to_string()), b).is_none()); - assert!(map.insert(Slice("cde"), c).is_none()); - assert!(map.insert(Owned("def".to_string()), d).is_none()); + assert!(map.insert("abc".into_cow(), a).is_none()); + assert!(map.insert("bcd".to_string().into_cow(), b).is_none()); + assert!(map.insert("cde".into_cow(), c).is_none()); + assert!(map.insert("def".to_string().into_cow(), d).is_none()); - assert!(map.insert(Slice("abc"), a).is_some()); - assert!(map.insert(Owned("bcd".to_string()), b).is_some()); - assert!(map.insert(Slice("cde"), c).is_some()); - assert!(map.insert(Owned("def".to_string()), d).is_some()); + assert!(map.insert("abc".into_cow(), a).is_some()); + assert!(map.insert("bcd".to_string().into_cow(), b).is_some()); + assert!(map.insert("cde".into_cow(), c).is_some()); + assert!(map.insert("def".to_string().into_cow(), d).is_some()); - assert!(map.insert(Owned("abc".to_string()), a).is_some()); - assert!(map.insert(Slice("bcd"), b).is_some()); - assert!(map.insert(Owned("cde".to_string()), c).is_some()); - assert!(map.insert(Slice("def"), d).is_some()); + assert!(map.insert("abc".to_string().into_cow(), a).is_some()); + assert!(map.insert("bcd".into_cow(), b).is_some()); + assert!(map.insert("cde".to_string().into_cow(), c).is_some()); + assert!(map.insert("def".into_cow(), d).is_some()); - assert_eq!(map.get(&Slice("abc")), Some(&a)); - assert_eq!(map.get(&Slice("bcd")), Some(&b)); - assert_eq!(map.get(&Slice("cde")), Some(&c)); - assert_eq!(map.get(&Slice("def")), Some(&d)); + assert_eq!(map.get(&"abc".into_cow()), Some(&a)); + assert_eq!(map.get(&"bcd".into_cow()), Some(&b)); + assert_eq!(map.get(&"cde".into_cow()), Some(&c)); + assert_eq!(map.get(&"def".into_cow()), Some(&d)); - assert_eq!(map.get(&Owned("abc".to_string())), Some(&a)); - assert_eq!(map.get(&Owned("bcd".to_string())), Some(&b)); - assert_eq!(map.get(&Owned("cde".to_string())), Some(&c)); - assert_eq!(map.get(&Owned("def".to_string())), Some(&d)); + assert_eq!(map.get(&"abc".to_string().into_cow()), Some(&a)); + assert_eq!(map.get(&"bcd".to_string().into_cow()), Some(&b)); + assert_eq!(map.get(&"cde".to_string().into_cow()), Some(&c)); + assert_eq!(map.get(&"def".to_string().into_cow()), Some(&d)); - assert!(map.remove(&Slice("foo")).is_some()); + assert!(map.remove(&"foo".into_cow()).is_some()); assert_eq!(map.into_iter().map(|(k, v)| format!("{}{}", k, v)) .collect::>() .concat(), -- cgit 1.4.1-3-g733a5 From 74a1041a4d7ae08d223f5ec623f6a698962d5667 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 20 Nov 2014 15:05:29 -0500 Subject: Implement the new parsing rules for types in the parser, modifying the AST appropriately. --- src/librustc/diagnostics.rs | 4 +- src/librustc/middle/resolve.rs | 95 ++++++++++------- src/librustc/middle/typeck/astconv.rs | 175 +++++++++++++++++-------------- src/libsyntax/ast.rs | 4 +- src/libsyntax/parse/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 192 +++++++++++++++------------------- src/libsyntax/print/pprust.rs | 24 +++-- 7 files changed, 262 insertions(+), 234 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index afbb18faa0b..1873213fadf 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -145,5 +145,7 @@ register_diagnostics!( E0166, E0167, E0168, - E0169 + E0169, + E0170, + E0171 ) diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 68a31c83ea4..d334395e911 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1396,29 +1396,53 @@ impl<'a> Resolver<'a> { // methods within to a new module, if the type was defined // within this module. - // Create the module and add all methods. - match ty.node { - TyPath(ref path, _, _) if path.segments.len() == 1 => { + let mod_name = match ty.node { + TyPath(ref path, _) if path.segments.len() == 1 => { // FIXME(18446) we should distinguish between the name of // a trait and the name of an impl of that trait. - let mod_name = path.segments.last().unwrap().identifier.name; + Some(path.segments.last().unwrap().identifier.name) + } + TyObjectSum(ref lhs_ty, _) => { + match lhs_ty.node { + TyPath(ref path, _) if path.segments.len() == 1 => { + Some(path.segments.last().unwrap().identifier.name) + } + _ => { + None + } + } + } + _ => { + None + } + }; + match mod_name { + None => { + self.resolve_error(ty.span, + "inherent implementations may \ + only be implemented in the same \ + module as the type they are \ + implemented for") + } + Some(mod_name) => { + // Create the module and add all methods. let parent_opt = parent.module().children.borrow() - .get(&mod_name).cloned(); + .get(&mod_name).cloned(); let new_parent = match parent_opt { // It already exists Some(ref child) if child.get_module_if_available() - .is_some() && - (child.get_module().kind.get() == ImplModuleKind || - child.get_module().kind.get() == TraitModuleKind) => { - ModuleReducedGraphParent(child.get_module()) - } + .is_some() && + (child.get_module().kind.get() == ImplModuleKind || + child.get_module().kind.get() == TraitModuleKind) => { + ModuleReducedGraphParent(child.get_module()) + } Some(ref child) if child.get_module_if_available() - .is_some() && - child.get_module().kind.get() == - EnumModuleKind => { - ModuleReducedGraphParent(child.get_module()) - } + .is_some() && + child.get_module().kind.get() == + EnumModuleKind => { + ModuleReducedGraphParent(child.get_module()) + } // Create the module _ => { let name_bindings = @@ -1433,7 +1457,7 @@ impl<'a> Resolver<'a> { let ns = TypeNS; let is_public = !name_bindings.defined_in_namespace(ns) || - name_bindings.defined_in_public_namespace(ns); + name_bindings.defined_in_public_namespace(ns); name_bindings.define_module(parent_link, Some(def_id), @@ -1459,21 +1483,21 @@ impl<'a> Resolver<'a> { ForbidDuplicateValues, method.span); let def = match method.pe_explicit_self() - .node { - SelfStatic => { - // Static methods become - // `DefStaticMethod`s. - DefStaticMethod(local_def(method.id), - FromImpl(local_def(item.id))) - } - _ => { - // Non-static methods become - // `DefMethod`s. - DefMethod(local_def(method.id), - None, - FromImpl(local_def(item.id))) - } - }; + .node { + SelfStatic => { + // Static methods become + // `DefStaticMethod`s. + DefStaticMethod(local_def(method.id), + FromImpl(local_def(item.id))) + } + _ => { + // Non-static methods become + // `DefMethod`s. + DefMethod(local_def(method.id), + None, + FromImpl(local_def(item.id))) + } + }; // NB: not IMPORTABLE let modifiers = if method.pe_vis() == ast::Public { @@ -1496,7 +1520,7 @@ impl<'a> Resolver<'a> { ForbidDuplicateTypesAndModules, typedef.span); let def = DefAssociatedTy(local_def( - typedef.id)); + typedef.id)); // NB: not IMPORTABLE let modifiers = if typedef.vis == ast::Public { PUBLIC @@ -1511,13 +1535,6 @@ impl<'a> Resolver<'a> { } } } - _ => { - self.resolve_error(ty.span, - "inherent implementations may \ - only be implemented in the same \ - module as the type they are \ - implemented for") - } } parent diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index fd5b1bd4793..8f1e2d115d3 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -59,8 +59,9 @@ use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope, ShiftedRscope, BindingRscope}; use middle::typeck::rscope; use middle::typeck::TypeAndSubsts; +use util::common::ErrorReported; use util::nodemap::DefIdMap; -use util::ppaux::{Repr, UserString}; +use util::ppaux::{mod, Repr, UserString}; use std::rc::Rc; use std::iter::AdditiveIterator; @@ -585,7 +586,7 @@ fn check_path_args(tcx: &ty::ctxt, pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { match ast_ty.node { - ast::TyPath(ref path, _, id) => { + ast::TyPath(ref path, id) => { let a_def = match tcx.def_map.borrow().get(&id) { None => { tcx.sess.span_bug(ast_ty.span, @@ -642,7 +643,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } match ast_ty.node { - ast::TyPath(ref path, _, id) => { + ast::TyPath(ref path, id) => { let a_def = match this.tcx().def_map.borrow().get(&id) { None => { this.tcx() @@ -682,64 +683,92 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } } -// Handle `~`, `Box`, and `&` being able to mean strs and vecs. -// If a_seq_ty is a str or a vec, make it a str/vec. -// Also handle first-class trait types. -fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( - this: &AC, - rscope: &RS, - a_seq_mutbl: ast::Mutability, - a_seq_ty: &ast::Ty, - region: ty::Region, - constr: |Ty<'tcx>| -> Ty<'tcx>) - -> Ty<'tcx> +fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, + rscope: &RS, + ty: &ast::Ty, + bounds: &[ast::TyParamBound]) + -> Result, ErrorReported> + where AC : AstConv<'tcx>, RS : RegionScope { - let tcx = this.tcx(); - - debug!("mk_pointer(region={}, a_seq_ty={})", - region, - a_seq_ty.repr(tcx)); + /*! + * In a type like `Foo + Send`, we want to wait to collect the + * full set of bounds before we make the object type, because we + * need them to infer a region bound. (For example, if we tried + * made a type from just `Foo`, then it wouldn't be enough to + * infer a 'static bound, and hence the user would get an error.) + * So this function is used when we're dealing with a sum type to + * convert the LHS. It only accepts a type that refers to a trait + * name, and reports an error otherwise. + */ - match a_seq_ty.node { - ast::TyVec(ref ty) => { - let ty = ast_ty_to_ty(this, rscope, &**ty); - return constr(ty::mk_vec(tcx, ty, None)); + match ty.node { + ast::TyPath(ref path, id) => { + match this.tcx().def_map.borrow().get(&id) { + Some(&def::DefTrait(trait_def_id)) => { + return Ok(ast_path_to_trait_ref(this, + rscope, + trait_def_id, + None, + path)); + } + _ => { + span_err!(this.tcx().sess, ty.span, E0170, "expected a reference to a trait"); + Err(ErrorReported) + } + } } - ast::TyPath(ref path, ref opt_bounds, id) => { - // Note that the "bounds must be empty if path is not a trait" - // restriction is enforced in the below case for ty_path, which - // will run after this as long as the path isn't a trait. - match tcx.def_map.borrow().get(&id) { - Some(&def::DefPrimTy(ast::TyStr)) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - return ty::mk_str_slice(tcx, region, a_seq_mutbl); + _ => { + span_err!(this.tcx().sess, ty.span, E0171, + "expected a path on the left-hand side of `+`, not `{}`", + pprust::ty_to_string(ty)); + match ty.node { + ast::TyRptr(None, ref mut_ty) => { + span_note!(this.tcx().sess, ty.span, + "perhaps you meant `&{}({} +{})`? (per RFC 248)", + ppaux::mutability_to_string(mut_ty.mutbl), + pprust::ty_to_string(&*mut_ty.ty), + pprust::bounds_to_string(bounds)); } - Some(&def::DefTrait(trait_def_id)) => { - let result = ast_path_to_trait_ref(this, - rscope, - trait_def_id, - None, - path); - let empty_vec = []; - let bounds = match *opt_bounds { None => empty_vec.as_slice(), - Some(ref bounds) => bounds.as_slice() }; - let existential_bounds = conv_existential_bounds(this, - rscope, - path.span, - &[Rc::new(result.clone())], - bounds); - let tr = ty::mk_trait(tcx, - result, - existential_bounds); - return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr}); + + ast::TyRptr(Some(ref lt), ref mut_ty) => { + span_note!(this.tcx().sess, ty.span, + "perhaps you meant `&{} {}({} +{})`? (per RFC 248)", + pprust::lifetime_to_string(lt), + ppaux::mutability_to_string(mut_ty.mutbl), + pprust::ty_to_string(&*mut_ty.ty), + pprust::bounds_to_string(bounds)); + } + + _ => { + span_note!(this.tcx().sess, ty.span, + "perhaps you forget parentheses? (per RFC 248)"); } - _ => {} } + Err(ErrorReported) } - _ => {} } - constr(ast_ty_to_ty(this, rscope, a_seq_ty)) +} + +fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC, + rscope: &RS, + span: Span, + trait_ref: ty::TraitRef<'tcx>, + bounds: &[ast::TyParamBound]) + -> Ty<'tcx> + where AC : AstConv<'tcx>, RS : RegionScope +{ + let existential_bounds = conv_existential_bounds(this, + rscope, + span, + &[Rc::new(trait_ref.clone())], + bounds); + + let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds); + debug!("trait_ref_to_object_type: result={}", + result.repr(this.tcx())); + + result } fn qpath_to_ty<'tcx,AC,RS>(this: &AC, @@ -806,6 +835,17 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast::TyVec(ref ty) => { ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None) } + ast::TyObjectSum(ref ty, ref bounds) => { + match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) { + Ok(trait_ref) => { + trait_ref_to_object_type(this, rscope, ast_ty.span, + trait_ref, bounds.as_slice()) + } + Err(ErrorReported) => { + ty::mk_err() + } + } + } ast::TyPtr(ref mt) => { ty::mk_ptr(tcx, ty::mt { ty: ast_ty_to_ty(this, rscope, &*mt.ty), @@ -815,8 +855,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast::TyRptr(ref region, ref mt) => { let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region); debug!("ty_rptr r={}", r.repr(this.tcx())); - mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r, - |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl})) + let t = ast_ty_to_ty(this, rscope, &*mt.ty); + ty::mk_rptr(tcx, r, ty::mt {ty: t, mutbl: mt.mutbl}) } ast::TyTup(ref fields) => { let flds = fields.iter() @@ -874,7 +914,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice()) } - ast::TyPath(ref path, ref bounds, id) => { + ast::TyPath(ref path, id) => { let a_def = match tcx.def_map.borrow().get(&id) { None => { tcx.sess @@ -884,35 +924,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } Some(&d) => d }; - // Kind bounds on path types are only supported for traits. - match a_def { - // But don't emit the error if the user meant to do a trait anyway. - def::DefTrait(..) => { }, - _ if bounds.is_some() => - tcx.sess.span_err(ast_ty.span, - "kind bounds can only be used on trait types"), - _ => { }, - } match a_def { def::DefTrait(trait_def_id) => { + // N.B. this case overlaps somewhat with + // TyObjectSum, see that fn for details let result = ast_path_to_trait_ref(this, rscope, trait_def_id, None, path); - let empty_bounds: &[ast::TyParamBound] = &[]; - let ast_bounds = match *bounds { - Some(ref b) => b.as_slice(), - None => empty_bounds - }; - let bounds = conv_existential_bounds(this, - rscope, - ast_ty.span, - &[Rc::new(result.clone())], - ast_bounds); - let result_ty = ty::mk_trait(tcx, result, bounds); - debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx())); - result_ty + trait_ref_to_object_type(this, rscope, path.span, result, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { ast_path_to_ty(this, rscope, did, path).ty diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3d33774aa55..14f164ff23b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1151,7 +1151,9 @@ pub enum Ty_ { /// A path (`module::module::...::Type`) or primitive /// /// Type parameters are stored in the Path itself - TyPath(Path, Option, NodeId), // for #7264; see above + TyPath(Path, NodeId), + /// Something like `A+B`. Note that `B` must always be a path. + TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` TyPolyTraitRef(TyParamBounds), /// A "qualified path", e.g. ` as SomeTrait>::SomeType` diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 96659031e6a..b46f7cdfe22 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1029,7 +1029,7 @@ mod test { parameters: ast::PathParameters::none(), } ), - }, None, ast::DUMMY_NODE_ID), + }, ast::DUMMY_NODE_ID), span:sp(10,13) }), pat: P(ast::Pat { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c731a0005f8..35187ebb522 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -111,16 +111,6 @@ pub enum PathParsingMode { /// A path with a lifetime and type parameters with double colons before /// the type parameters; e.g. `foo::bar::<'a>::Baz::` LifetimeAndTypesWithColons, - /// A path with a lifetime and type parameters with bounds before the last - /// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y` This - /// form does not use extra double colons. - LifetimeAndTypesAndBounds, -} - -/// A path paired with optional type bounds. -pub struct PathAndBounds { - pub path: ast::Path, - pub bounds: Option, } enum ItemOrViewItem { @@ -1053,17 +1043,9 @@ impl<'a> Parser<'a> { } } - pub fn parse_ty_path(&mut self, plus_allowed: bool) -> Ty_ { - let mode = if plus_allowed { - LifetimeAndTypesAndBounds - } else { - LifetimeAndTypesWithoutColons - }; - let PathAndBounds { - path, - bounds - } = self.parse_path(mode); - TyPath(path, bounds, ast::DUMMY_NODE_ID) + pub fn parse_ty_path(&mut self) -> Ty_ { + let path = self.parse_path(LifetimeAndTypesWithoutColons); + TyPath(path, ast::DUMMY_NODE_ID) } /// parse a TyBareFn type: @@ -1286,7 +1268,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; let ident = self.parse_ident(); self.expect(&token::Eq); - let typ = self.parse_ty(true); + let typ = self.parse_ty_sum(); let hi = self.span.hi; self.expect(&token::Semi); Typedef { @@ -1385,7 +1367,7 @@ impl<'a> Parser<'a> { /// Parse a possibly mutable type pub fn parse_mt(&mut self) -> MutTy { let mutbl = self.parse_mutability(); - let t = self.parse_ty(true); + let t = self.parse_ty(); MutTy { ty: t, mutbl: mutbl } } @@ -1396,7 +1378,7 @@ impl<'a> Parser<'a> { let mutbl = self.parse_mutability(); let id = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); let hi = ty.span.hi; ast::TypeField { ident: id, @@ -1411,7 +1393,19 @@ impl<'a> Parser<'a> { if self.eat(&token::Not) { NoReturn(self.span) } else { - Return(self.parse_ty(true)) + let t = self.parse_ty(); + + // We used to allow `fn foo() -> &T + U`, but don't + // anymore. If we see it, report a useful error. This + // only makes sense because `parse_ret_ty` is only + // used in fn *declarations*, not fn types or where + // clauses (i.e., not when parsing something like + // `FnMut() -> T + Send`, where the `+` is legal). + if self.token == token::BinOp(token::Plus) { + self.warn("deprecated syntax: `()` are required, see RFC 248 for details"); + } + + Return(t) } } else { let pos = self.span.lo; @@ -1423,11 +1417,36 @@ impl<'a> Parser<'a> { } } + /// Parse a type in a context where `T1+T2` is allowed. + pub fn parse_ty_sum(&mut self) -> P { + let lo = self.span.lo; + let lhs = self.parse_ty(); + + if !self.eat(&token::BinOp(token::Plus)) { + return lhs; + } + + let bounds = self.parse_ty_param_bounds(); + + // In type grammar, `+` is treated like a binary operator, + // and hence both L and R side are required. + if bounds.len() == 0 { + let last_span = self.last_span; + self.span_err(last_span, + "at least one type parameter bound \ + must be specified"); + } + + let sp = mk_sp(lo, self.last_span.hi); + let sum = ast::TyObjectSum(lhs, bounds); + P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}) + } + /// Parse a type. /// /// The second parameter specifies whether the `+` binary operator is /// allowed in the type grammar. - pub fn parse_ty(&mut self, plus_allowed: bool) -> P { + pub fn parse_ty(&mut self) -> P { maybe_whole!(no_clone self, NtTy); let lo = self.span.lo; @@ -1441,7 +1460,7 @@ impl<'a> Parser<'a> { let mut ts = vec![]; let mut last_comma = false; while self.token != token::CloseDelim(token::Paren) { - ts.push(self.parse_ty(true)); + ts.push(self.parse_ty_sum()); if self.token == token::Comma { last_comma = true; self.bump(); @@ -1465,7 +1484,7 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector), _ => self.obsolete(last_span, ObsoleteOwnedType) } - TyTup(vec![self.parse_ty(false)]) + TyTup(vec![self.parse_ty()]) } else if self.token == token::BinOp(token::Star) { // STAR POINTER (bare pointer?) self.bump(); @@ -1473,7 +1492,7 @@ impl<'a> Parser<'a> { } else if self.token == token::OpenDelim(token::Bracket) { // VECTOR self.expect(&token::OpenDelim(token::Bracket)); - let t = self.parse_ty(true); + let t = self.parse_ty_sum(); // Parse the `, ..e` in `[ int, ..e ]` // where `e` is a const expression @@ -1514,7 +1533,7 @@ impl<'a> Parser<'a> { } else if self.token == token::Lt { // QUALIFIED PATH `::item` self.bump(); - let self_type = self.parse_ty(true); + let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); let trait_ref = self.parse_trait_ref(); self.expect(&token::Gt); @@ -1529,7 +1548,7 @@ impl<'a> Parser<'a> { self.token.is_ident() || self.token.is_path() { // NAMED TYPE - self.parse_ty_path(plus_allowed) + self.parse_ty_path() } else if self.eat(&token::Underscore) { // TYPE TO BE INFERRED TyInfer @@ -1563,7 +1582,7 @@ impl<'a> Parser<'a> { known as `*const T`"); MutImmutable }; - let t = self.parse_ty(true); + let t = self.parse_ty(); MutTy { ty: t, mutbl: mutbl } } @@ -1603,7 +1622,7 @@ impl<'a> Parser<'a> { special_idents::invalid) }; - let t = self.parse_ty(true); + let t = self.parse_ty_sum(); Arg { ty: t, @@ -1621,7 +1640,7 @@ impl<'a> Parser<'a> { pub fn parse_fn_block_arg(&mut self) -> Arg { let pat = self.parse_pat(); let t = if self.eat(&token::Colon) { - self.parse_ty(true) + self.parse_ty_sum() } else { P(Ty { id: ast::DUMMY_NODE_ID, @@ -1739,7 +1758,7 @@ impl<'a> Parser<'a> { /// mode. The `mode` parameter determines whether lifetimes, types, and/or /// bounds are permitted and whether `::` must precede type parameter /// groups. - pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds { + pub fn parse_path(&mut self, mode: PathParsingMode) -> ast::Path { // Check for a whole path... let found = match self.token { token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()), @@ -1747,10 +1766,7 @@ impl<'a> Parser<'a> { }; match found { Some(token::Interpolated(token::NtPath(box path))) => { - return PathAndBounds { - path: path, - bounds: None - } + return path; } _ => {} } @@ -1762,8 +1778,7 @@ impl<'a> Parser<'a> { // identifier followed by an optional lifetime and a set of types. // A bound set is a set of type parameter bounds. let segments = match mode { - LifetimeAndTypesWithoutColons | - LifetimeAndTypesAndBounds => { + LifetimeAndTypesWithoutColons => { self.parse_path_segments_without_colons() } LifetimeAndTypesWithColons => { @@ -1774,44 +1789,14 @@ impl<'a> Parser<'a> { } }; - // Next, parse a plus and bounded type parameters, if - // applicable. We need to remember whether the separate was - // present for later, because in some contexts it's a parse - // error. - let opt_bounds = { - if mode == LifetimeAndTypesAndBounds && - self.eat(&token::BinOp(token::Plus)) - { - let bounds = self.parse_ty_param_bounds(); - - // For some reason that I do not fully understand, we - // do not permit an empty list in the case where it is - // introduced by a `+`, but we do for `:` and other - // separators. -nmatsakis - if bounds.len() == 0 { - let last_span = self.last_span; - self.span_err(last_span, - "at least one type parameter bound \ - must be specified"); - } - - Some(bounds) - } else { - None - } - }; - // Assemble the span. let span = mk_sp(lo, self.last_span.hi); // Assemble the result. - PathAndBounds { - path: ast::Path { - span: span, - global: is_global, - segments: segments, - }, - bounds: opt_bounds, + ast::Path { + span: span, + global: is_global, + segments: segments, } } @@ -1837,10 +1822,10 @@ impl<'a> Parser<'a> { let inputs = self.parse_seq_to_end( &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| p.parse_ty(true)); + |p| p.parse_ty_sum()); let output_ty = if self.eat(&token::RArrow) { - Some(self.parse_ty(true)) + Some(self.parse_ty()) } else { None }; @@ -2327,7 +2312,7 @@ impl<'a> Parser<'a> { !self.token.is_keyword(keywords::True) && !self.token.is_keyword(keywords::False) { let pth = - self.parse_path(LifetimeAndTypesWithColons).path; + self.parse_path(LifetimeAndTypesWithColons); // `!`, as an operator, is prefix, so we know this isn't that if self.token == token::Not { @@ -2898,7 +2883,7 @@ impl<'a> Parser<'a> { } None => { if as_prec > min_prec && self.eat_keyword(keywords::As) { - let rhs = self.parse_ty(false); + let rhs = self.parse_ty(); let _as = self.mk_expr(lhs.span.lo, rhs.span.hi, ExprCast(lhs, rhs)); @@ -3362,8 +3347,7 @@ impl<'a> Parser<'a> { }) { self.bump(); let end = if self.token.is_ident() || self.token.is_path() { - let path = self.parse_path(LifetimeAndTypesWithColons) - .path; + let path = self.parse_path(LifetimeAndTypesWithColons); let hi = self.span.hi; self.mk_expr(lo, hi, ExprPath(path)) } else { @@ -3433,8 +3417,7 @@ impl<'a> Parser<'a> { } } else { // parse an enum pat - let enum_path = self.parse_path(LifetimeAndTypesWithColons) - .path; + let enum_path = self.parse_path(LifetimeAndTypesWithColons); match self.token { token::OpenDelim(token::Brace) => { self.bump(); @@ -3548,7 +3531,7 @@ impl<'a> Parser<'a> { span: mk_sp(lo, lo), }); if self.eat(&token::Colon) { - ty = self.parse_ty(true); + ty = self.parse_ty_sum(); } let init = self.parse_initializer(); P(ast::Local { @@ -3577,7 +3560,7 @@ impl<'a> Parser<'a> { } let name = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); spanned(lo, self.last_span.hi, ast::StructField_ { kind: NamedField(name, pr), id: ast::DUMMY_NODE_ID, @@ -3624,7 +3607,7 @@ impl<'a> Parser<'a> { // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.bump(); let id = match self.token { @@ -3976,7 +3959,7 @@ impl<'a> Parser<'a> { let default = if self.token == token::Eq { self.bump(); - Some(self.parse_ty(true)) + Some(self.parse_ty_sum()) } else { None }; @@ -4032,7 +4015,7 @@ impl<'a> Parser<'a> { Some(token::Comma), |p| { p.forbid_lifetime(); - p.parse_ty(true) + p.parse_ty_sum() } ); (lifetimes, result.into_vec()) @@ -4265,7 +4248,7 @@ impl<'a> Parser<'a> { // Determine whether this is the fully explicit form, `self: // TYPE`. if self.eat(&token::Colon) { - SelfExplicit(self.parse_ty(false), self_ident) + SelfExplicit(self.parse_ty_sum(), self_ident) } else { SelfValue(self_ident) } @@ -4277,7 +4260,7 @@ impl<'a> Parser<'a> { // Determine whether this is the fully explicit form, // `self: TYPE`. if self.eat(&token::Colon) { - SelfExplicit(self.parse_ty(false), self_ident) + SelfExplicit(self.parse_ty_sum(), self_ident) } else { SelfValue(self_ident) } @@ -4466,7 +4449,7 @@ impl<'a> Parser<'a> { && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { // method macro. - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.expect(&token::Not); // eat a matched-delimiter token tree: @@ -4564,30 +4547,25 @@ impl<'a> Parser<'a> { let could_be_trait = self.token != token::OpenDelim(token::Paren); // Parse the trait. - let mut ty = self.parse_ty(true); + let mut ty = self.parse_ty_sum(); // Parse traits, if necessary. let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. let opt_trait_ref = match ty.node { - TyPath(ref path, None, node_id) => { + TyPath(ref path, node_id) => { Some(TraitRef { path: (*path).clone(), ref_id: node_id, }) } - TyPath(_, Some(_), _) => { - self.span_err(ty.span, - "bounded traits are only valid in type position"); - None - } _ => { self.span_err(ty.span, "not a trait"); None } }; - ty = self.parse_ty(true); + ty = self.parse_ty_sum(); opt_trait_ref } else { None @@ -4606,7 +4584,7 @@ impl<'a> Parser<'a> { /// Parse a::B fn parse_trait_ref(&mut self) -> TraitRef { ast::TraitRef { - path: self.parse_path(LifetimeAndTypesWithoutColons).path, + path: self.parse_path(LifetimeAndTypesWithoutColons), ref_id: ast::DUMMY_NODE_ID, } } @@ -4638,7 +4616,7 @@ impl<'a> Parser<'a> { let mut generics = self.parse_generics(); if self.eat(&token::Colon) { - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.span_err(ty.span, "`virtual` structs have been removed from the language"); } @@ -4673,7 +4651,7 @@ impl<'a> Parser<'a> { let struct_field_ = ast::StructField_ { kind: UnnamedField(p.parse_visibility()), id: ast::DUMMY_NODE_ID, - ty: p.parse_ty(true), + ty: p.parse_ty_sum(), attrs: attrs, }; spanned(lo, p.span.hi, struct_field_) @@ -4830,7 +4808,7 @@ impl<'a> Parser<'a> { fn parse_item_const(&mut self, m: Option) -> ItemInfo { let id = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.expect(&token::Eq); let e = self.parse_expr(); self.commit_expr_expecting(&*e, token::Semi); @@ -5023,7 +5001,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); let hi = self.span.hi; self.expect(&token::Semi); P(ForeignItem { @@ -5181,7 +5159,7 @@ impl<'a> Parser<'a> { let mut tps = self.parse_generics(); self.parse_where_clause(&mut tps); self.expect(&token::Eq); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.expect(&token::Semi); (ident, ItemTy(ty, tps), None) } @@ -5235,7 +5213,7 @@ impl<'a> Parser<'a> { &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| p.parse_ty(true) + |p| p.parse_ty_sum() ); for ty in arg_tys.into_iter() { args.push(ast::VariantArg { @@ -5593,7 +5571,7 @@ impl<'a> Parser<'a> { // MACRO INVOCATION ITEM // item macro. - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.expect(&token::Not); // a 'special' identifier (like what `macro_rules!` uses) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6960337c3e2..78412a76bfe 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -293,6 +293,10 @@ pub fn ty_to_string(ty: &ast::Ty) -> String { $to_string(|s| s.print_type(ty)) } +pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String { + $to_string(|s| s.print_bounds("", bounds)) +} + pub fn pat_to_string(pat: &ast::Pat) -> String { $to_string(|s| s.print_pat(pat)) } @@ -739,11 +743,15 @@ impl<'a> State<'a> { Some(&generics), None)); } - ast::TyPath(ref path, ref bounds, _) => { - try!(self.print_bounded_path(path, bounds)); + ast::TyPath(ref path, _) => { + try!(self.print_path(path, false)); + } + ast::TyObjectSum(ref ty, ref bounds) => { + try!(self.print_type(&**ty)); + try!(self.print_bounds("+", bounds.as_slice())); } ast::TyPolyTraitRef(ref bounds) => { - try!(self.print_bounds("", bounds)); + try!(self.print_bounds("", bounds.as_slice())); } ast::TyQPath(ref qpath) => { try!(word(&mut self.s, "<")); @@ -970,7 +978,7 @@ impl<'a> State<'a> { } _ => {} } - try!(self.print_bounds(":", bounds)); + try!(self.print_bounds(":", bounds.as_slice())); try!(self.print_where_clause(generics)); try!(word(&mut self.s, " ")); try!(self.bopen()); @@ -2329,7 +2337,7 @@ impl<'a> State<'a> { pub fn print_bounds(&mut self, prefix: &str, - bounds: &OwnedSlice) + bounds: &[ast::TyParamBound]) -> IoResult<()> { if !bounds.is_empty() { try!(word(&mut self.s, prefix)); @@ -2418,7 +2426,7 @@ impl<'a> State<'a> { _ => {} } try!(self.print_ident(param.ident)); - try!(self.print_bounds(":", ¶m.bounds)); + try!(self.print_bounds(":", param.bounds.as_slice())); match param.default { Some(ref default) => { try!(space(&mut self.s)); @@ -2447,7 +2455,7 @@ impl<'a> State<'a> { } try!(self.print_ident(predicate.ident)); - try!(self.print_bounds(":", &predicate.bounds)); + try!(self.print_bounds(":", predicate.bounds.as_slice())); } Ok(()) @@ -2664,7 +2672,7 @@ impl<'a> State<'a> { try!(self.pclose()); } - try!(self.print_bounds(":", bounds)); + try!(self.print_bounds(":", bounds.as_slice())); try!(self.print_fn_output(decl)); -- cgit 1.4.1-3-g733a5 From cd5c8235c5448a7234548c772468c8d2e8f150d9 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 25 Nov 2014 21:17:11 -0500 Subject: /*! -> //! Sister pull request of https://github.com/rust-lang/rust/pull/19288, but for the other style of block doc comment. --- src/libcollections/hash/mod.rs | 102 +- src/libcore/clone.rs | 22 +- src/libcore/finally.rs | 40 +- src/libcore/intrinsics.rs | 62 +- src/libcore/iter.rs | 94 +- src/libcore/kinds.rs | 19 +- src/libcore/ops.rs | 88 +- src/libflate/lib.rs | 14 +- src/libgraphviz/lib.rs | 506 ++-- src/liblibc/lib.rs | 104 +- src/librand/distributions/mod.rs | 19 +- src/librustc/lib.rs | 14 +- src/librustc/middle/astencode.rs | 120 +- src/librustc/middle/borrowck/check_loans.rs | 42 +- src/librustc/middle/borrowck/doc.rs | 2428 ++++++++++---------- src/librustc/middle/borrowck/fragments.rs | 47 +- .../middle/borrowck/gather_loans/gather_moves.rs | 4 +- .../middle/borrowck/gather_loans/lifetime.rs | 6 +- src/librustc/middle/borrowck/gather_loans/mod.rs | 9 +- .../middle/borrowck/gather_loans/restrictions.rs | 4 +- src/librustc/middle/borrowck/mod.rs | 2 +- src/librustc/middle/borrowck/move_data.rs | 77 +- src/librustc/middle/cfg/mod.rs | 8 +- src/librustc/middle/dataflow.rs | 10 +- src/librustc/middle/expr_use_visitor.rs | 25 +- src/librustc/middle/fast_reject.rs | 24 +- src/librustc/middle/graph.rs | 46 +- src/librustc/middle/liveness.rs | 196 +- src/librustc/middle/mem_categorization.rs | 133 +- src/librustc/middle/region.rs | 151 +- src/librustc/middle/resolve_lifetime.rs | 63 +- src/librustc/middle/subst.rs | 110 +- src/librustc/middle/traits/coherence.rs | 2 +- src/librustc/middle/traits/doc.rs | 796 ++++--- src/librustc/middle/traits/fulfill.rs | 19 +- src/librustc/middle/traits/mod.rs | 53 +- src/librustc/middle/traits/select.rs | 280 +-- src/librustc/middle/traits/util.rs | 49 +- src/librustc/middle/ty.rs | 197 +- src/librustc/middle/ty_fold.rs | 52 +- src/librustc/middle/typeck/astconv.rs | 141 +- src/librustc/middle/typeck/check/closure.rs | 4 +- src/librustc/middle/typeck/check/method/confirm.rs | 26 +- src/librustc/middle/typeck/check/method/doc.rs | 227 +- src/librustc/middle/typeck/check/method/mod.rs | 69 +- src/librustc/middle/typeck/check/method/probe.rs | 93 +- src/librustc/middle/typeck/check/mod.rs | 268 +-- src/librustc/middle/typeck/check/regionck.rs | 537 ++--- src/librustc/middle/typeck/check/regionmanip.rs | 23 +- src/librustc/middle/typeck/check/vtable.rs | 25 +- src/librustc/middle/typeck/check/wf.rs | 58 +- src/librustc/middle/typeck/coherence/mod.rs | 8 +- src/librustc/middle/typeck/coherence/orphan.rs | 6 +- src/librustc/middle/typeck/coherence/overlap.rs | 6 +- src/librustc/middle/typeck/collect.rs | 17 +- src/librustc/middle/typeck/infer/coercion.rs | 114 +- src/librustc/middle/typeck/infer/combine.rs | 13 +- src/librustc/middle/typeck/infer/doc.rs | 478 ++-- .../middle/typeck/infer/error_reporting.rs | 103 +- .../middle/typeck/infer/higher_ranked/doc.rs | 806 ++++--- .../middle/typeck/infer/higher_ranked/mod.rs | 6 +- src/librustc/middle/typeck/infer/lattice.rs | 42 +- src/librustc/middle/typeck/infer/mod.rs | 26 +- .../middle/typeck/infer/region_inference/doc.rs | 732 +++--- .../middle/typeck/infer/region_inference/mod.rs | 30 +- src/librustc/middle/typeck/infer/skolemize.rs | 52 +- src/librustc/middle/typeck/infer/type_variable.rs | 18 +- src/librustc/middle/typeck/infer/unify.rs | 44 +- src/librustc/middle/typeck/variance.rs | 368 ++- src/librustc/plugin/mod.rs | 94 +- src/librustc/util/common.rs | 20 +- src/librustc/util/ppaux.rs | 7 +- src/librustc/util/snapshot_vec.rs | 42 +- src/librustc_trans/lib.rs | 14 +- src/librustc_trans/test.rs | 30 +- src/librustc_trans/trans/_match.rs | 419 ++-- src/librustc_trans/trans/adt.rs | 66 +- src/librustc_trans/trans/asm.rs | 4 +- src/librustc_trans/trans/base.rs | 15 +- src/librustc_trans/trans/callee.rs | 71 +- src/librustc_trans/trans/cleanup.rs | 214 +- src/librustc_trans/trans/closure.rs | 22 +- src/librustc_trans/trans/common.rs | 28 +- src/librustc_trans/trans/datum.rs | 161 +- src/librustc_trans/trans/debuginfo.rs | 349 ++- src/librustc_trans/trans/doc.rs | 450 ++-- src/librustc_trans/trans/expr.rs | 127 +- src/librustc_trans/trans/foreign.rs | 49 +- src/librustc_trans/trans/meth.rs | 57 +- src/librustc_trans/trans/tvec.rs | 36 +- src/librustrt/c_str.rs | 120 +- src/libserialize/json.rs | 355 ++- src/libstd/dynamic_lib.rs | 10 +- src/libstd/fmt.rs | 768 +++---- src/libstd/hash.rs | 102 +- src/libstd/io/fs.rs | 80 +- src/libstd/io/mod.rs | 400 ++-- src/libstd/io/net/addrinfo.rs | 12 +- src/libstd/io/net/pipe.rs | 22 +- src/libstd/io/stdio.rs | 34 +- src/libstd/io/test.rs | 15 +- src/libstd/io/timer.rs | 12 +- src/libstd/io/util.rs | 2 +- src/libstd/os.rs | 30 +- src/libstd/path/mod.rs | 106 +- src/libstd/rt/mod.rs | 72 +- src/libstd/sync/future.rs | 28 +- src/libsyntax/ast.rs | 6 +- src/libsyntax/ast_util.rs | 6 +- src/libsyntax/codemap.rs | 18 +- src/libsyntax/ext/deriving/decodable.rs | 5 +- src/libsyntax/ext/deriving/generic/ty.rs | 6 +- src/libsyntax/ext/deriving/mod.rs | 13 +- src/libsyntax/parse/obsolete.rs | 12 +- src/libsyntax/parse/parser.rs | 21 +- src/libsyntax/visit.rs | 8 +- src/libunicode/normalize.rs | 5 +- src/libunicode/u_char.rs | 10 +- src/libunicode/u_str.rs | 10 +- 119 files changed, 6860 insertions(+), 8080 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index 4173ffc5d2f..1dc2539c592 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -8,58 +8,56 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Generic hashing support. - * - * This module provides a generic way to compute the hash of a value. The - * simplest way to make a type hashable is to use `#[deriving(Hash)]`: - * - * # Example - * - * ```rust - * use std::hash; - * use std::hash::Hash; - * - * #[deriving(Hash)] - * struct Person { - * id: uint, - * name: String, - * phone: u64, - * } - * - * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; - * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; - * - * assert!(hash::hash(&person1) != hash::hash(&person2)); - * ``` - * - * If you need more control over how a value is hashed, you need to implement - * the trait `Hash`: - * - * ```rust - * use std::hash; - * use std::hash::Hash; - * use std::hash::sip::SipState; - * - * struct Person { - * id: uint, - * name: String, - * phone: u64, - * } - * - * impl Hash for Person { - * fn hash(&self, state: &mut SipState) { - * self.id.hash(state); - * self.phone.hash(state); - * } - * } - * - * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; - * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; - * - * assert!(hash::hash(&person1) == hash::hash(&person2)); - * ``` - */ +//! Generic hashing support. +//! +//! This module provides a generic way to compute the hash of a value. The +//! simplest way to make a type hashable is to use `#[deriving(Hash)]`: +//! +//! # Example +//! +//! ```rust +//! use std::hash; +//! use std::hash::Hash; +//! +//! #[deriving(Hash)] +//! struct Person { +//! id: uint, +//! name: String, +//! phone: u64, +//! } +//! +//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; +//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; +//! +//! assert!(hash::hash(&person1) != hash::hash(&person2)); +//! ``` +//! +//! If you need more control over how a value is hashed, you need to implement +//! the trait `Hash`: +//! +//! ```rust +//! use std::hash; +//! use std::hash::Hash; +//! use std::hash::sip::SipState; +//! +//! struct Person { +//! id: uint, +//! name: String, +//! phone: u64, +//! } +//! +//! impl Hash for Person { +//! fn hash(&self, state: &mut SipState) { +//! self.id.hash(state); +//! self.phone.hash(state); +//! } +//! } +//! +//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; +//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; +//! +//! assert!(hash::hash(&person1) == hash::hash(&person2)); +//! ``` #![allow(unused_must_use)] diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index d13daf0964a..9f928f57e9e 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -8,18 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! The `Clone` trait for types that cannot be 'implicitly copied' - -In Rust, some simple types are "implicitly copyable" and when you -assign them or pass them as arguments, the receiver will get a copy, -leaving the original value in place. These types do not require -allocation to copy and do not have finalizers (i.e. they do not -contain owned boxes or implement `Drop`), so the compiler considers -them cheap and safe to copy. For other types copies must be made -explicitly, by convention implementing the `Clone` trait and calling -the `clone` method. - -*/ +//! The `Clone` trait for types that cannot be 'implicitly copied' +//! +//! In Rust, some simple types are "implicitly copyable" and when you +//! assign them or pass them as arguments, the receiver will get a copy, +//! leaving the original value in place. These types do not require +//! allocation to copy and do not have finalizers (i.e. they do not +//! contain owned boxes or implement `Drop`), so the compiler considers +//! them cheap and safe to copy. For other types copies must be made +//! explicitly, by convention implementing the `Clone` trait and calling +//! the `clone` method. #![unstable] diff --git a/src/libcore/finally.rs b/src/libcore/finally.rs index 2e358e7a74b..8bfdd934477 100644 --- a/src/libcore/finally.rs +++ b/src/libcore/finally.rs @@ -8,27 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -The Finally trait provides a method, `finally` on -stack closures that emulates Java-style try/finally blocks. - -Using the `finally` method is sometimes convenient, but the type rules -prohibit any shared, mutable state between the "try" case and the -"finally" case. For advanced cases, the `try_finally` function can -also be used. See that function for more details. - -# Example - -``` -use std::finally::Finally; - -(|| { - // ... -}).finally(|| { - // this code is always run -}) -``` -*/ +//! The Finally trait provides a method, `finally` on +//! stack closures that emulates Java-style try/finally blocks. +//! +//! Using the `finally` method is sometimes convenient, but the type rules +//! prohibit any shared, mutable state between the "try" case and the +//! "finally" case. For advanced cases, the `try_finally` function can +//! also be used. See that function for more details. +//! +//! # Example +//! +//! ``` +//! use std::finally::Finally; +//! +//! (|| { +//! // ... +//! }).finally(|| { +//! // this code is always run +//! }) +//! ``` #![experimental] diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 067ef47a86b..78c74075d48 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -8,38 +8,36 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! rustc compiler intrinsics. - -The corresponding definitions are in librustc/middle/trans/foreign.rs. - -# Volatiles - -The volatile intrinsics provide operations intended to act on I/O -memory, which are guaranteed to not be reordered by the compiler -across other volatile intrinsics. See the LLVM documentation on -[[volatile]]. - -[volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses - -# Atomics - -The atomic intrinsics provide common atomic operations on machine -words, with multiple possible memory orderings. They obey the same -semantics as C++11. See the LLVM documentation on [[atomics]]. - -[atomics]: http://llvm.org/docs/Atomics.html - -A quick refresher on memory ordering: - -* Acquire - a barrier for acquiring a lock. Subsequent reads and writes - take place after the barrier. -* Release - a barrier for releasing a lock. Preceding reads and writes - take place before the barrier. -* Sequentially consistent - sequentially consistent operations are - guaranteed to happen in order. This is the standard mode for working - with atomic types and is equivalent to Java's `volatile`. - -*/ +//! rustc compiler intrinsics. +//! +//! The corresponding definitions are in librustc/middle/trans/foreign.rs. +//! +//! # Volatiles +//! +//! The volatile intrinsics provide operations intended to act on I/O +//! memory, which are guaranteed to not be reordered by the compiler +//! across other volatile intrinsics. See the LLVM documentation on +//! [[volatile]]. +//! +//! [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses +//! +//! # Atomics +//! +//! The atomic intrinsics provide common atomic operations on machine +//! words, with multiple possible memory orderings. They obey the same +//! semantics as C++11. See the LLVM documentation on [[atomics]]. +//! +//! [atomics]: http://llvm.org/docs/Atomics.html +//! +//! A quick refresher on memory ordering: +//! +//! * Acquire - a barrier for acquiring a lock. Subsequent reads and writes +//! take place after the barrier. +//! * Release - a barrier for releasing a lock. Preceding reads and writes +//! take place before the barrier. +//! * Sequentially consistent - sequentially consistent operations are +//! guaranteed to happen in order. This is the standard mode for working +//! with atomic types and is equivalent to Java's `volatile`. #![experimental] #![allow(missing_docs)] diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 496e7979b72..2d488a4b155 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -8,55 +8,51 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Composable external iterators - -# The `Iterator` trait - -This module defines Rust's core iteration trait. The `Iterator` trait has one -unimplemented method, `next`. All other methods are derived through default -methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`. - -The goal of this module is to unify iteration across all containers in Rust. -An iterator can be considered as a state machine which is used to track which -element will be yielded next. - -There are various extensions also defined in this module to assist with various -types of iteration, such as the `DoubleEndedIterator` for iterating in reverse, -the `FromIterator` trait for creating a container from an iterator, and much -more. - -## Rust's `for` loop - -The special syntax used by rust's `for` loop is based around the `Iterator` -trait defined in this module. For loops can be viewed as a syntactical expansion -into a `loop`, for example, the `for` loop in this example is essentially -translated to the `loop` below. - -```rust -let values = vec![1i, 2, 3]; - -// "Syntactical sugar" taking advantage of an iterator -for &x in values.iter() { - println!("{}", x); -} - -// Rough translation of the iteration without a `for` iterator. -let mut it = values.iter(); -loop { - match it.next() { - Some(&x) => { - println!("{}", x); - } - None => { break } - } -} -``` - -This `for` loop syntax can be applied to any iterator over any type. - -*/ +//! Composable external iterators +//! +//! # The `Iterator` trait +//! +//! This module defines Rust's core iteration trait. The `Iterator` trait has one +//! unimplemented method, `next`. All other methods are derived through default +//! methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`. +//! +//! The goal of this module is to unify iteration across all containers in Rust. +//! An iterator can be considered as a state machine which is used to track which +//! element will be yielded next. +//! +//! There are various extensions also defined in this module to assist with various +//! types of iteration, such as the `DoubleEndedIterator` for iterating in reverse, +//! the `FromIterator` trait for creating a container from an iterator, and much +//! more. +//! +//! ## Rust's `for` loop +//! +//! The special syntax used by rust's `for` loop is based around the `Iterator` +//! trait defined in this module. For loops can be viewed as a syntactical expansion +//! into a `loop`, for example, the `for` loop in this example is essentially +//! translated to the `loop` below. +//! +//! ```rust +//! let values = vec![1i, 2, 3]; +//! +//! // "Syntactical sugar" taking advantage of an iterator +//! for &x in values.iter() { +//! println!("{}", x); +//! } +//! +//! // Rough translation of the iteration without a `for` iterator. +//! let mut it = values.iter(); +//! loop { +//! match it.next() { +//! Some(&x) => { +//! println!("{}", x); +//! } +//! None => { break } +//! } +//! } +//! ``` +//! +//! This `for` loop syntax can be applied to any iterator over any type. pub use self::MinMaxResult::*; diff --git a/src/libcore/kinds.rs b/src/libcore/kinds.rs index 6489101f7b9..0c2cb9d5910 100644 --- a/src/libcore/kinds.rs +++ b/src/libcore/kinds.rs @@ -8,17 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -Primitive traits representing basic 'kinds' of types - -Rust types can be classified in various useful ways according to -intrinsic properties of the type. These classifications, often called -'kinds', are represented as traits. - -They cannot be implemented by user code, but are instead implemented -by the compiler automatically for the types to which they apply. - -*/ +//! Primitive traits representing basic 'kinds' of types +//! +//! Rust types can be classified in various useful ways according to +//! intrinsic properties of the type. These classifications, often called +//! 'kinds', are represented as traits. +//! +//! They cannot be implemented by user code, but are instead implemented +//! by the compiler automatically for the types to which they apply. /// Types able to be transferred across task boundaries. #[lang="send"] diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 185c937eb6b..519dfd47fd8 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -8,52 +8,48 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * - * Overloadable operators - * - * Implementing these traits allows you to get an effect similar to - * overloading operators. - * - * The values for the right hand side of an operator are automatically - * borrowed, so `a + b` is sugar for `a.add(&b)`. - * - * All of these traits are imported by the prelude, so they are available in - * every Rust program. - * - * # Example - * - * This example creates a `Point` struct that implements `Add` and `Sub`, and then - * demonstrates adding and subtracting two `Point`s. - * - * ```rust - * #[deriving(Show)] - * struct Point { - * x: int, - * y: int - * } - * - * impl Add for Point { - * fn add(&self, other: &Point) -> Point { - * Point {x: self.x + other.x, y: self.y + other.y} - * } - * } - * - * impl Sub for Point { - * fn sub(&self, other: &Point) -> Point { - * Point {x: self.x - other.x, y: self.y - other.y} - * } - * } - * fn main() { - * println!("{}", Point {x: 1, y: 0} + Point {x: 2, y: 3}); - * println!("{}", Point {x: 1, y: 0} - Point {x: 2, y: 3}); - * } - * ``` - * - * See the documentation for each trait for a minimum implementation that prints - * something to the screen. - * - */ +//! Overloadable operators +//! +//! Implementing these traits allows you to get an effect similar to +//! overloading operators. +//! +//! The values for the right hand side of an operator are automatically +//! borrowed, so `a + b` is sugar for `a.add(&b)`. +//! +//! All of these traits are imported by the prelude, so they are available in +//! every Rust program. +//! +//! # Example +//! +//! This example creates a `Point` struct that implements `Add` and `Sub`, and then +//! demonstrates adding and subtracting two `Point`s. +//! +//! ```rust +//! #[deriving(Show)] +//! struct Point { +//! x: int, +//! y: int +//! } +//! +//! impl Add for Point { +//! fn add(&self, other: &Point) -> Point { +//! Point {x: self.x + other.x, y: self.y + other.y} +//! } +//! } +//! +//! impl Sub for Point { +//! fn sub(&self, other: &Point) -> Point { +//! Point {x: self.x - other.x, y: self.y - other.y} +//! } +//! } +//! fn main() { +//! println!("{}", Point {x: 1, y: 0} + Point {x: 2, y: 3}); +//! println!("{}", Point {x: 1, y: 0} - Point {x: 2, y: 3}); +//! } +//! ``` +//! +//! See the documentation for each trait for a minimum implementation that prints +//! something to the screen. use kinds::Sized; diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 568210118a8..36a04392c36 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -8,15 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Simple [DEFLATE][def]-based compression. This is a wrapper around the -[`miniz`][mz] library, which is a one-file pure-C implementation of zlib. - -[def]: https://en.wikipedia.org/wiki/DEFLATE -[mz]: https://code.google.com/p/miniz/ - -*/ +//! Simple [DEFLATE][def]-based compression. This is a wrapper around the +//! [`miniz`][mz] library, which is a one-file pure-C implementation of zlib. +//! +//! [def]: https://en.wikipedia.org/wiki/DEFLATE +//! [mz]: https://code.google.com/p/miniz/ #![crate_name = "flate"] #![experimental] diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index f149ec509af..04eeeb62e1d 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -8,260 +8,258 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Generate files suitable for use with [Graphviz](http://www.graphviz.org/) - -The `render` function generates output (e.g. an `output.dot` file) for -use with [Graphviz](http://www.graphviz.org/) by walking a labelled -graph. (Graphviz can then automatically lay out the nodes and edges -of the graph, and also optionally render the graph as an image or -other [output formats]( -http://www.graphviz.org/content/output-formats), such as SVG.) - -Rather than impose some particular graph data structure on clients, -this library exposes two traits that clients can implement on their -own structs before handing them over to the rendering function. - -Note: This library does not yet provide access to the full -expressiveness of the [DOT language]( -http://www.graphviz.org/doc/info/lang.html). For example, there are -many [attributes](http://www.graphviz.org/content/attrs) related to -providing layout hints (e.g. left-to-right versus top-down, which -algorithm to use, etc). The current intention of this library is to -emit a human-readable .dot file with very regular structure suitable -for easy post-processing. - -# Examples - -The first example uses a very simple graph representation: a list of -pairs of ints, representing the edges (the node set is implicit). -Each node label is derived directly from the int representing the node, -while the edge labels are all empty strings. - -This example also illustrates how to use `CowVec` to return -an owned vector or a borrowed slice as appropriate: we construct the -node vector from scratch, but borrow the edge list (rather than -constructing a copy of all the edges from scratch). - -The output from this example renders five nodes, with the first four -forming a diamond-shaped acyclic graph and then pointing to the fifth -which is cyclic. - -```rust -use graphviz as dot; - -type Nd = int; -type Ed = (int,int); -struct Edges(Vec); - -pub fn render_to(output: &mut W) { - let edges = Edges(vec!((0,1), (0,2), (1,3), (2,3), (3,4), (4,4))); - dot::render(&edges, output).unwrap() -} - -impl<'a> dot::Labeller<'a, Nd, Ed> for Edges { - fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example1").unwrap() } - - fn node_id(&'a self, n: &Nd) -> dot::Id<'a> { - dot::Id::new(format!("N{}", *n)).unwrap() - } -} - -impl<'a> dot::GraphWalk<'a, Nd, Ed> for Edges { - fn nodes(&self) -> dot::Nodes<'a,Nd> { - // (assumes that |N| \approxeq |E|) - let &Edges(ref v) = self; - let mut nodes = Vec::with_capacity(v.len()); - for &(s,t) in v.iter() { - nodes.push(s); nodes.push(t); - } - nodes.sort(); - nodes.dedup(); - nodes.into_cow() - } - - fn edges(&'a self) -> dot::Edges<'a,Ed> { - let &Edges(ref edges) = self; - edges.as_slice().into_cow() - } - - fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s } - - fn target(&self, e: &Ed) -> Nd { let &(_,t) = e; t } -} - -# pub fn main() { render_to(&mut Vec::new()) } -``` - -```no_run -# pub fn render_to(output: &mut W) { unimplemented!() } -pub fn main() { - use std::io::File; - let mut f = File::create(&Path::new("example1.dot")); - render_to(&mut f) -} -``` - -Output from first example (in `example1.dot`): - -```ignore -digraph example1 { - N0[label="N0"]; - N1[label="N1"]; - N2[label="N2"]; - N3[label="N3"]; - N4[label="N4"]; - N0 -> N1[label=""]; - N0 -> N2[label=""]; - N1 -> N3[label=""]; - N2 -> N3[label=""]; - N3 -> N4[label=""]; - N4 -> N4[label=""]; -} -``` - -The second example illustrates using `node_label` and `edge_label` to -add labels to the nodes and edges in the rendered graph. The graph -here carries both `nodes` (the label text to use for rendering a -particular node), and `edges` (again a list of `(source,target)` -indices). - -This example also illustrates how to use a type (in this case the edge -type) that shares substructure with the graph: the edge type here is a -direct reference to the `(source,target)` pair stored in the graph's -internal vector (rather than passing around a copy of the pair -itself). Note that this implies that `fn edges(&'a self)` must -construct a fresh `Vec<&'a (uint,uint)>` from the `Vec<(uint,uint)>` -edges stored in `self`. - -Since both the set of nodes and the set of edges are always -constructed from scratch via iterators, we use the `collect()` method -from the `Iterator` trait to collect the nodes and edges into freshly -constructed growable `Vec` values (rather use the `into_cow` -from the `IntoCow` trait as was used in the first example -above). - -The output from this example renders four nodes that make up the -Hasse-diagram for the subsets of the set `{x, y}`. Each edge is -labelled with the ⊆ character (specified using the HTML character -entity `&sube`). - -```rust -use graphviz as dot; - -type Nd = uint; -type Ed<'a> = &'a (uint, uint); -struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> } - -pub fn render_to(output: &mut W) { - let nodes = vec!("{x,y}","{x}","{y}","{}"); - let edges = vec!((0,1), (0,2), (1,3), (2,3)); - let graph = Graph { nodes: nodes, edges: edges }; - - dot::render(&graph, output).unwrap() -} - -impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph { - fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example2").unwrap() } - fn node_id(&'a self, n: &Nd) -> dot::Id<'a> { - dot::Id::new(format!("N{}", n)).unwrap() - } - fn node_label<'a>(&'a self, n: &Nd) -> dot::LabelText<'a> { - dot::LabelStr(self.nodes[*n].as_slice().into_cow()) - } - fn edge_label<'a>(&'a self, _: &Ed) -> dot::LabelText<'a> { - dot::LabelStr("⊆".into_cow()) - } -} - -impl<'a> dot::GraphWalk<'a, Nd, Ed<'a>> for Graph { - fn nodes(&self) -> dot::Nodes<'a,Nd> { range(0,self.nodes.len()).collect() } - fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> { self.edges.iter().collect() } - fn source(&self, e: &Ed) -> Nd { let & &(s,_) = e; s } - fn target(&self, e: &Ed) -> Nd { let & &(_,t) = e; t } -} - -# pub fn main() { render_to(&mut Vec::new()) } -``` - -```no_run -# pub fn render_to(output: &mut W) { unimplemented!() } -pub fn main() { - use std::io::File; - let mut f = File::create(&Path::new("example2.dot")); - render_to(&mut f) -} -``` - -The third example is similar to the second, except now each node and -edge now carries a reference to the string label for each node as well -as that node's index. (This is another illustration of how to share -structure with the graph itself, and why one might want to do so.) - -The output from this example is the same as the second example: the -Hasse-diagram for the subsets of the set `{x, y}`. - -```rust -use graphviz as dot; - -type Nd<'a> = (uint, &'a str); -type Ed<'a> = (Nd<'a>, Nd<'a>); -struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> } - -pub fn render_to(output: &mut W) { - let nodes = vec!("{x,y}","{x}","{y}","{}"); - let edges = vec!((0,1), (0,2), (1,3), (2,3)); - let graph = Graph { nodes: nodes, edges: edges }; - - dot::render(&graph, output).unwrap() -} - -impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph { - fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3").unwrap() } - fn node_id(&'a self, n: &Nd<'a>) -> dot::Id<'a> { - dot::Id::new(format!("N{}", n.val0())).unwrap() - } - fn node_label<'a>(&'a self, n: &Nd<'a>) -> dot::LabelText<'a> { - let &(i, _) = n; - dot::LabelStr(self.nodes[i].as_slice().into_cow()) - } - fn edge_label<'a>(&'a self, _: &Ed<'a>) -> dot::LabelText<'a> { - dot::LabelStr("⊆".into_cow()) - } -} - -impl<'a> dot::GraphWalk<'a, Nd<'a>, Ed<'a>> for Graph { - fn nodes(&'a self) -> dot::Nodes<'a,Nd<'a>> { - self.nodes.iter().map(|s|s.as_slice()).enumerate().collect() - } - fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> { - self.edges.iter() - .map(|&(i,j)|((i, self.nodes[i].as_slice()), - (j, self.nodes[j].as_slice()))) - .collect() - } - fn source(&self, e: &Ed<'a>) -> Nd<'a> { let &(s,_) = e; s } - fn target(&self, e: &Ed<'a>) -> Nd<'a> { let &(_,t) = e; t } -} - -# pub fn main() { render_to(&mut Vec::new()) } -``` - -```no_run -# pub fn render_to(output: &mut W) { unimplemented!() } -pub fn main() { - use std::io::File; - let mut f = File::create(&Path::new("example3.dot")); - render_to(&mut f) -} -``` - -# References - -* [Graphviz](http://www.graphviz.org/) - -* [DOT language](http://www.graphviz.org/doc/info/lang.html) - -*/ +//! Generate files suitable for use with [Graphviz](http://www.graphviz.org/) +//! +//! The `render` function generates output (e.g. an `output.dot` file) for +//! use with [Graphviz](http://www.graphviz.org/) by walking a labelled +//! graph. (Graphviz can then automatically lay out the nodes and edges +//! of the graph, and also optionally render the graph as an image or +//! other [output formats]( +//! http://www.graphviz.org/content/output-formats), such as SVG.) +//! +//! Rather than impose some particular graph data structure on clients, +//! this library exposes two traits that clients can implement on their +//! own structs before handing them over to the rendering function. +//! +//! Note: This library does not yet provide access to the full +//! expressiveness of the [DOT language]( +//! http://www.graphviz.org/doc/info/lang.html). For example, there are +//! many [attributes](http://www.graphviz.org/content/attrs) related to +//! providing layout hints (e.g. left-to-right versus top-down, which +//! algorithm to use, etc). The current intention of this library is to +//! emit a human-readable .dot file with very regular structure suitable +//! for easy post-processing. +//! +//! # Examples +//! +//! The first example uses a very simple graph representation: a list of +//! pairs of ints, representing the edges (the node set is implicit). +//! Each node label is derived directly from the int representing the node, +//! while the edge labels are all empty strings. +//! +//! This example also illustrates how to use `CowVec` to return +//! an owned vector or a borrowed slice as appropriate: we construct the +//! node vector from scratch, but borrow the edge list (rather than +//! constructing a copy of all the edges from scratch). +//! +//! The output from this example renders five nodes, with the first four +//! forming a diamond-shaped acyclic graph and then pointing to the fifth +//! which is cyclic. +//! +//! ```rust +//! use graphviz as dot; +//! +//! type Nd = int; +//! type Ed = (int,int); +//! struct Edges(Vec); +//! +//! pub fn render_to(output: &mut W) { +//! let edges = Edges(vec!((0,1), (0,2), (1,3), (2,3), (3,4), (4,4))); +//! dot::render(&edges, output).unwrap() +//! } +//! +//! impl<'a> dot::Labeller<'a, Nd, Ed> for Edges { +//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example1").unwrap() } +//! +//! fn node_id(&'a self, n: &Nd) -> dot::Id<'a> { +//! dot::Id::new(format!("N{}", *n)).unwrap() +//! } +//! } +//! +//! impl<'a> dot::GraphWalk<'a, Nd, Ed> for Edges { +//! fn nodes(&self) -> dot::Nodes<'a,Nd> { +//! // (assumes that |N| \approxeq |E|) +//! let &Edges(ref v) = self; +//! let mut nodes = Vec::with_capacity(v.len()); +//! for &(s,t) in v.iter() { +//! nodes.push(s); nodes.push(t); +//! } +//! nodes.sort(); +//! nodes.dedup(); +//! nodes.into_cow() +//! } +//! +//! fn edges(&'a self) -> dot::Edges<'a,Ed> { +//! let &Edges(ref edges) = self; +//! edges.as_slice().into_cow() +//! } +//! +//! fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s } +//! +//! fn target(&self, e: &Ed) -> Nd { let &(_,t) = e; t } +//! } +//! +//! # pub fn main() { render_to(&mut Vec::new()) } +//! ``` +//! +//! ```no_run +//! # pub fn render_to(output: &mut W) { unimplemented!() } +//! pub fn main() { +//! use std::io::File; +//! let mut f = File::create(&Path::new("example1.dot")); +//! render_to(&mut f) +//! } +//! ``` +//! +//! Output from first example (in `example1.dot`): +//! +//! ```ignore +//! digraph example1 { +//! N0[label="N0"]; +//! N1[label="N1"]; +//! N2[label="N2"]; +//! N3[label="N3"]; +//! N4[label="N4"]; +//! N0 -> N1[label=""]; +//! N0 -> N2[label=""]; +//! N1 -> N3[label=""]; +//! N2 -> N3[label=""]; +//! N3 -> N4[label=""]; +//! N4 -> N4[label=""]; +//! } +//! ``` +//! +//! The second example illustrates using `node_label` and `edge_label` to +//! add labels to the nodes and edges in the rendered graph. The graph +//! here carries both `nodes` (the label text to use for rendering a +//! particular node), and `edges` (again a list of `(source,target)` +//! indices). +//! +//! This example also illustrates how to use a type (in this case the edge +//! type) that shares substructure with the graph: the edge type here is a +//! direct reference to the `(source,target)` pair stored in the graph's +//! internal vector (rather than passing around a copy of the pair +//! itself). Note that this implies that `fn edges(&'a self)` must +//! construct a fresh `Vec<&'a (uint,uint)>` from the `Vec<(uint,uint)>` +//! edges stored in `self`. +//! +//! Since both the set of nodes and the set of edges are always +//! constructed from scratch via iterators, we use the `collect()` method +//! from the `Iterator` trait to collect the nodes and edges into freshly +//! constructed growable `Vec` values (rather use the `into_cow` +//! from the `IntoCow` trait as was used in the first example +//! above). +//! +//! The output from this example renders four nodes that make up the +//! Hasse-diagram for the subsets of the set `{x, y}`. Each edge is +//! labelled with the ⊆ character (specified using the HTML character +//! entity `&sube`). +//! +//! ```rust +//! use graphviz as dot; +//! +//! type Nd = uint; +//! type Ed<'a> = &'a (uint, uint); +//! struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> } +//! +//! pub fn render_to(output: &mut W) { +//! let nodes = vec!("{x,y}","{x}","{y}","{}"); +//! let edges = vec!((0,1), (0,2), (1,3), (2,3)); +//! let graph = Graph { nodes: nodes, edges: edges }; +//! +//! dot::render(&graph, output).unwrap() +//! } +//! +//! impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph { +//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example2").unwrap() } +//! fn node_id(&'a self, n: &Nd) -> dot::Id<'a> { +//! dot::Id::new(format!("N{}", n)).unwrap() +//! } +//! fn node_label<'a>(&'a self, n: &Nd) -> dot::LabelText<'a> { +//! dot::LabelStr(self.nodes[*n].as_slice().into_cow()) +//! } +//! fn edge_label<'a>(&'a self, _: &Ed) -> dot::LabelText<'a> { +//! dot::LabelStr("⊆".into_cow()) +//! } +//! } +//! +//! impl<'a> dot::GraphWalk<'a, Nd, Ed<'a>> for Graph { +//! fn nodes(&self) -> dot::Nodes<'a,Nd> { range(0,self.nodes.len()).collect() } +//! fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> { self.edges.iter().collect() } +//! fn source(&self, e: &Ed) -> Nd { let & &(s,_) = e; s } +//! fn target(&self, e: &Ed) -> Nd { let & &(_,t) = e; t } +//! } +//! +//! # pub fn main() { render_to(&mut Vec::new()) } +//! ``` +//! +//! ```no_run +//! # pub fn render_to(output: &mut W) { unimplemented!() } +//! pub fn main() { +//! use std::io::File; +//! let mut f = File::create(&Path::new("example2.dot")); +//! render_to(&mut f) +//! } +//! ``` +//! +//! The third example is similar to the second, except now each node and +//! edge now carries a reference to the string label for each node as well +//! as that node's index. (This is another illustration of how to share +//! structure with the graph itself, and why one might want to do so.) +//! +//! The output from this example is the same as the second example: the +//! Hasse-diagram for the subsets of the set `{x, y}`. +//! +//! ```rust +//! use graphviz as dot; +//! +//! type Nd<'a> = (uint, &'a str); +//! type Ed<'a> = (Nd<'a>, Nd<'a>); +//! struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> } +//! +//! pub fn render_to(output: &mut W) { +//! let nodes = vec!("{x,y}","{x}","{y}","{}"); +//! let edges = vec!((0,1), (0,2), (1,3), (2,3)); +//! let graph = Graph { nodes: nodes, edges: edges }; +//! +//! dot::render(&graph, output).unwrap() +//! } +//! +//! impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph { +//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3").unwrap() } +//! fn node_id(&'a self, n: &Nd<'a>) -> dot::Id<'a> { +//! dot::Id::new(format!("N{}", n.val0())).unwrap() +//! } +//! fn node_label<'a>(&'a self, n: &Nd<'a>) -> dot::LabelText<'a> { +//! let &(i, _) = n; +//! dot::LabelStr(self.nodes[i].as_slice().into_cow()) +//! } +//! fn edge_label<'a>(&'a self, _: &Ed<'a>) -> dot::LabelText<'a> { +//! dot::LabelStr("⊆".into_cow()) +//! } +//! } +//! +//! impl<'a> dot::GraphWalk<'a, Nd<'a>, Ed<'a>> for Graph { +//! fn nodes(&'a self) -> dot::Nodes<'a,Nd<'a>> { +//! self.nodes.iter().map(|s|s.as_slice()).enumerate().collect() +//! } +//! fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> { +//! self.edges.iter() +//! .map(|&(i,j)|((i, self.nodes[i].as_slice()), +//! (j, self.nodes[j].as_slice()))) +//! .collect() +//! } +//! fn source(&self, e: &Ed<'a>) -> Nd<'a> { let &(s,_) = e; s } +//! fn target(&self, e: &Ed<'a>) -> Nd<'a> { let &(_,t) = e; t } +//! } +//! +//! # pub fn main() { render_to(&mut Vec::new()) } +//! ``` +//! +//! ```no_run +//! # pub fn render_to(output: &mut W) { unimplemented!() } +//! pub fn main() { +//! use std::io::File; +//! let mut f = File::create(&Path::new("example3.dot")); +//! render_to(&mut f) +//! } +//! ``` +//! +//! # References +//! +//! * [Graphviz](http://www.graphviz.org/) +//! +//! * [DOT language](http://www.graphviz.org/doc/info/lang.html) #![crate_name = "graphviz"] #![experimental] diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 10610b70584..0014a3e3941 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -19,59 +19,57 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -/*! -* Bindings for the C standard library and other platform libraries -* -* **NOTE:** These are *architecture and libc* specific. On Linux, these -* bindings are only correct for glibc. -* -* This module contains bindings to the C standard library, organized into -* modules by their defining standard. Additionally, it contains some assorted -* platform-specific definitions. For convenience, most functions and types -* are reexported, so `use libc::*` will import the available C bindings as -* appropriate for the target platform. The exact set of functions available -* are platform specific. -* -* *Note:* Because these definitions are platform-specific, some may not appear -* in the generated documentation. -* -* We consider the following specs reasonably normative with respect to -* interoperating with the C standard library (libc/msvcrt): -* -* * ISO 9899:1990 ('C95', 'ANSI C', 'Standard C'), NA1, 1995. -* * ISO 9899:1999 ('C99' or 'C9x'). -* * ISO 9945:1988 / IEEE 1003.1-1988 ('POSIX.1'). -* * ISO 9945:2001 / IEEE 1003.1-2001 ('POSIX:2001', 'SUSv3'). -* * ISO 9945:2008 / IEEE 1003.1-2008 ('POSIX:2008', 'SUSv4'). -* -* Note that any reference to the 1996 revision of POSIX, or any revs between -* 1990 (when '88 was approved at ISO) and 2001 (when the next actual -* revision-revision happened), are merely additions of other chapters (1b and -* 1c) outside the core interfaces. -* -* Despite having several names each, these are *reasonably* coherent -* point-in-time, list-of-definition sorts of specs. You can get each under a -* variety of names but will wind up with the same definition in each case. -* -* See standards(7) in linux-manpages for more details. -* -* Our interface to these libraries is complicated by the non-universality of -* conformance to any of them. About the only thing universally supported is -* the first (C95), beyond that definitions quickly become absent on various -* platforms. -* -* We therefore wind up dividing our module-space up (mostly for the sake of -* sanity while editing, filling-in-details and eliminating duplication) into -* definitions common-to-all (held in modules named c95, c99, posix88, posix01 -* and posix08) and definitions that appear only on *some* platforms (named -* 'extra'). This would be things like significant OSX foundation kit, or Windows -* library kernel32.dll, or various fancy glibc, Linux or BSD extensions. -* -* In addition to the per-platform 'extra' modules, we define a module of -* 'common BSD' libc routines that never quite made it into POSIX but show up -* in multiple derived systems. This is the 4.4BSD r2 / 1995 release, the final -* one from Berkeley after the lawsuits died down and the CSRG dissolved. -*/ +//! Bindings for the C standard library and other platform libraries +//! +//! **NOTE:** These are *architecture and libc* specific. On Linux, these +//! bindings are only correct for glibc. +//! +//! This module contains bindings to the C standard library, organized into +//! modules by their defining standard. Additionally, it contains some assorted +//! platform-specific definitions. For convenience, most functions and types +//! are reexported, so `use libc::*` will import the available C bindings as +//! appropriate for the target platform. The exact set of functions available +//! are platform specific. +//! +//! *Note:* Because these definitions are platform-specific, some may not appear +//! in the generated documentation. +//! +//! We consider the following specs reasonably normative with respect to +//! interoperating with the C standard library (libc/msvcrt): +//! +//! * ISO 9899:1990 ('C95', 'ANSI C', 'Standard C'), NA1, 1995. +//! * ISO 9899:1999 ('C99' or 'C9x'). +//! * ISO 9945:1988 / IEEE 1003.1-1988 ('POSIX.1'). +//! * ISO 9945:2001 / IEEE 1003.1-2001 ('POSIX:2001', 'SUSv3'). +//! * ISO 9945:2008 / IEEE 1003.1-2008 ('POSIX:2008', 'SUSv4'). +//! +//! Note that any reference to the 1996 revision of POSIX, or any revs between +//! 1990 (when '88 was approved at ISO) and 2001 (when the next actual +//! revision-revision happened), are merely additions of other chapters (1b and +//! 1c) outside the core interfaces. +//! +//! Despite having several names each, these are *reasonably* coherent +//! point-in-time, list-of-definition sorts of specs. You can get each under a +//! variety of names but will wind up with the same definition in each case. +//! +//! See standards(7) in linux-manpages for more details. +//! +//! Our interface to these libraries is complicated by the non-universality of +//! conformance to any of them. About the only thing universally supported is +//! the first (C95), beyond that definitions quickly become absent on various +//! platforms. +//! +//! We therefore wind up dividing our module-space up (mostly for the sake of +//! sanity while editing, filling-in-details and eliminating duplication) into +//! definitions common-to-all (held in modules named c95, c99, posix88, posix01 +//! and posix08) and definitions that appear only on *some* platforms (named +//! 'extra'). This would be things like significant OSX foundation kit, or Windows +//! library kernel32.dll, or various fancy glibc, Linux or BSD extensions. +//! +//! In addition to the per-platform 'extra' modules, we define a module of +//! 'common BSD' libc routines that never quite made it into POSIX but show up +//! in multiple derived systems. This is the 4.4BSD r2 / 1995 release, the final +//! one from Berkeley after the lawsuits died down and the CSRG dissolved. #![allow(non_camel_case_types)] #![allow(non_snake_case)] diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 5bbddcb7c16..0fa989bf0b2 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -8,17 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -Sampling from random distributions. - -This is a generalization of `Rand` to allow parameters to control the -exact properties of the generated values, e.g. the mean and standard -deviation of a normal distribution. The `Sample` trait is the most -general, and allows for generating values that change some state -internally. The `IndependentSample` trait is for generating values -that do not need to record state. - -*/ +//! Sampling from random distributions. +//! +//! This is a generalization of `Rand` to allow parameters to control the +//! exact properties of the generated values, e.g. the mean and standard +//! deviation of a normal distribution. The `Sample` trait is the most +//! general, and allows for generating values that change some state +//! internally. The `IndependentSample` trait is for generating values +//! that do not need to record state. #![experimental] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f272bb52a14..c599a0f2daf 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -8,15 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -The Rust compiler. - -# Note - -This API is completely unstable and subject to change. - -*/ +//! The Rust compiler. +//! +//! # Note +//! +//! This API is completely unstable and subject to change. #![crate_name = "rustc"] #![experimental] diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 7986a526b23..523e997a8de 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -196,53 +196,38 @@ fn reserve_id_range(sess: &Session, } impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> { + /// Translates an internal id, meaning a node id that is known to refer to some part of the + /// item currently being inlined, such as a local variable or argument. All naked node-ids + /// that appear in types have this property, since if something might refer to an external item + /// we would use a def-id to allow for the possibility that the item resides in another crate. pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId { - /*! - * Translates an internal id, meaning a node id that is known - * to refer to some part of the item currently being inlined, - * such as a local variable or argument. All naked node-ids - * that appear in types have this property, since if something - * might refer to an external item we would use a def-id to - * allow for the possibility that the item resides in another - * crate. - */ - // from_id_range should be non-empty assert!(!self.from_id_range.empty()); (id - self.from_id_range.min + self.to_id_range.min) } + + /// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded + /// data to the current crate numbers.. By external, I mean that it be translated to a + /// reference to the item in its original crate, as opposed to being translated to a reference + /// to the inlined version of the item. This is typically, but not always, what you want, + /// because most def-ids refer to external things like types or other fns that may or may not + /// be inlined. Note that even when the inlined function is referencing itself recursively, we + /// would want `tr_def_id` for that reference--- conceptually the function calls the original, + /// non-inlined version, and trans deals with linking that recursive call to the inlined copy. + /// + /// However, there are a *few* cases where def-ids are used but we know that the thing being + /// referenced is in fact *internal* to the item being inlined. In those cases, you should use + /// `tr_intern_def_id()` below. pub fn tr_def_id(&self, did: ast::DefId) -> ast::DefId { - /*! - * Translates an EXTERNAL def-id, converting the crate number - * from the one used in the encoded data to the current crate - * numbers.. By external, I mean that it be translated to a - * reference to the item in its original crate, as opposed to - * being translated to a reference to the inlined version of - * the item. This is typically, but not always, what you - * want, because most def-ids refer to external things like - * types or other fns that may or may not be inlined. Note - * that even when the inlined function is referencing itself - * recursively, we would want `tr_def_id` for that - * reference--- conceptually the function calls the original, - * non-inlined version, and trans deals with linking that - * recursive call to the inlined copy. - * - * However, there are a *few* cases where def-ids are used but - * we know that the thing being referenced is in fact *internal* - * to the item being inlined. In those cases, you should use - * `tr_intern_def_id()` below. - */ decoder::translate_def_id(self.cdata, did) } - pub fn tr_intern_def_id(&self, did: ast::DefId) -> ast::DefId { - /*! - * Translates an INTERNAL def-id, meaning a def-id that is - * known to refer to some part of the item currently being - * inlined. In that case, we want to convert the def-id to - * refer to the current crate and to the new, inlined node-id. - */ + /// Translates an INTERNAL def-id, meaning a def-id that is + /// known to refer to some part of the item currently being + /// inlined. In that case, we want to convert the def-id to + /// refer to the current crate and to the new, inlined node-id. + pub fn tr_intern_def_id(&self, did: ast::DefId) -> ast::DefId { assert_eq!(did.krate, ast::LOCAL_CRATE); ast::DefId { krate: ast::LOCAL_CRATE, node: self.tr_id(did.node) } } @@ -1780,43 +1765,40 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { } } + /// Converts a def-id that appears in a type. The correct + /// translation will depend on what kind of def-id this is. + /// This is a subtle point: type definitions are not + /// inlined into the current crate, so if the def-id names + /// a nominal type or type alias, then it should be + /// translated to refer to the source crate. + /// + /// However, *type parameters* are cloned along with the function + /// they are attached to. So we should translate those def-ids + /// to refer to the new, cloned copy of the type parameter. + /// We only see references to free type parameters in the body of + /// an inlined function. In such cases, we need the def-id to + /// be a local id so that the TypeContents code is able to lookup + /// the relevant info in the ty_param_defs table. + /// + /// *Region parameters*, unfortunately, are another kettle of fish. + /// In such cases, def_id's can appear in types to distinguish + /// shadowed bound regions and so forth. It doesn't actually + /// matter so much what we do to these, since regions are erased + /// at trans time, but it's good to keep them consistent just in + /// case. We translate them with `tr_def_id()` which will map + /// the crate numbers back to the original source crate. + /// + /// Unboxed closures are cloned along with the function being + /// inlined, and all side tables use interned node IDs, so we + /// translate their def IDs accordingly. + /// + /// It'd be really nice to refactor the type repr to not include + /// def-ids so that all these distinctions were unnecessary. fn convert_def_id(&mut self, dcx: &DecodeContext, source: tydecode::DefIdSource, did: ast::DefId) -> ast::DefId { - /*! - * Converts a def-id that appears in a type. The correct - * translation will depend on what kind of def-id this is. - * This is a subtle point: type definitions are not - * inlined into the current crate, so if the def-id names - * a nominal type or type alias, then it should be - * translated to refer to the source crate. - * - * However, *type parameters* are cloned along with the function - * they are attached to. So we should translate those def-ids - * to refer to the new, cloned copy of the type parameter. - * We only see references to free type parameters in the body of - * an inlined function. In such cases, we need the def-id to - * be a local id so that the TypeContents code is able to lookup - * the relevant info in the ty_param_defs table. - * - * *Region parameters*, unfortunately, are another kettle of fish. - * In such cases, def_id's can appear in types to distinguish - * shadowed bound regions and so forth. It doesn't actually - * matter so much what we do to these, since regions are erased - * at trans time, but it's good to keep them consistent just in - * case. We translate them with `tr_def_id()` which will map - * the crate numbers back to the original source crate. - * - * Unboxed closures are cloned along with the function being - * inlined, and all side tables use interned node IDs, so we - * translate their def IDs accordingly. - * - * It'd be really nice to refactor the type repr to not include - * def-ids so that all these distinctions were unnecessary. - */ - let r = match source { NominalType | TypeWithId | RegionParameter => dcx.tr_def_id(did), TypeParameter | UnboxedClosureSource => dcx.tr_intern_def_id(did) diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index afcc533ffb8..9a27abbe832 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -684,16 +684,13 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { return ret; } + /// Reports an error if `expr` (which should be a path) + /// is using a moved/uninitialized value fn check_if_path_is_moved(&self, id: ast::NodeId, span: Span, use_kind: MovedValueUseKind, lp: &Rc>) { - /*! - * Reports an error if `expr` (which should be a path) - * is using a moved/uninitialized value - */ - debug!("check_if_path_is_moved(id={}, use_kind={}, lp={})", id, use_kind, lp.repr(self.bccx.tcx)); let base_lp = owned_ptr_base_path_rc(lp); @@ -708,30 +705,29 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { }); } + /// Reports an error if assigning to `lp` will use a + /// moved/uninitialized value. Mainly this is concerned with + /// detecting derefs of uninitialized pointers. + /// + /// For example: + /// + /// ``` + /// let a: int; + /// a = 10; // ok, even though a is uninitialized + /// + /// struct Point { x: uint, y: uint } + /// let p: Point; + /// p.x = 22; // ok, even though `p` is uninitialized + /// + /// let p: ~Point; + /// (*p).x = 22; // not ok, p is uninitialized, can't deref + /// ``` fn check_if_assigned_path_is_moved(&self, id: ast::NodeId, span: Span, use_kind: MovedValueUseKind, lp: &Rc>) { - /*! - * Reports an error if assigning to `lp` will use a - * moved/uninitialized value. Mainly this is concerned with - * detecting derefs of uninitialized pointers. - * - * For example: - * - * let a: int; - * a = 10; // ok, even though a is uninitialized - * - * struct Point { x: uint, y: uint } - * let p: Point; - * p.x = 22; // ok, even though `p` is uninitialized - * - * let p: ~Point; - * (*p).x = 22; // not ok, p is uninitialized, can't deref - */ - match lp.kind { LpVar(_) | LpUpvar(_) => { // assigning to `x` does not require that `x` is initialized diff --git a/src/librustc/middle/borrowck/doc.rs b/src/librustc/middle/borrowck/doc.rs index 5b70d97b402..c6db5340f0f 100644 --- a/src/librustc/middle/borrowck/doc.rs +++ b/src/librustc/middle/borrowck/doc.rs @@ -8,1219 +8,1215 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -# The Borrow Checker - -This pass has the job of enforcing memory safety. This is a subtle -topic. This docs aim to explain both the practice and the theory -behind the borrow checker. They start with a high-level overview of -how it works, and then proceed to dive into the theoretical -background. Finally, they go into detail on some of the more subtle -aspects. - -# Table of contents - -These docs are long. Search for the section you are interested in. - -- Overview -- Formal model -- Borrowing and loans -- Moves and initialization -- Drop flags and structural fragments -- Future work - -# Overview - -The borrow checker checks one function at a time. It operates in two -passes. The first pass, called `gather_loans`, walks over the function -and identifies all of the places where borrows (e.g., `&` expressions -and `ref` bindings) and moves (copies or captures of a linear value) -occur. It also tracks initialization sites. For each borrow and move, -it checks various basic safety conditions at this time (for example, -that the lifetime of the borrow doesn't exceed the lifetime of the -value being borrowed, or that there is no move out of an `&T` -referent). - -It then uses the dataflow module to propagate which of those borrows -may be in scope at each point in the procedure. A loan is considered -to come into scope at the expression that caused it and to go out of -scope when the lifetime of the resulting reference expires. - -Once the in-scope loans are known for each point in the program, the -borrow checker walks the IR again in a second pass called -`check_loans`. This pass examines each statement and makes sure that -it is safe with respect to the in-scope loans. - -# Formal model - -Throughout the docs we'll consider a simple subset of Rust in which -you can only borrow from lvalues, defined like so: - -```text -LV = x | LV.f | *LV -``` - -Here `x` represents some variable, `LV.f` is a field reference, -and `*LV` is a pointer dereference. There is no auto-deref or other -niceties. This means that if you have a type like: - -```text -struct S { f: uint } -``` - -and a variable `a: Box`, then the rust expression `a.f` would correspond -to an `LV` of `(*a).f`. - -Here is the formal grammar for the types we'll consider: - -```text -TY = () | S<'LT...> | Box | & 'LT MQ TY -MQ = mut | imm | const -``` - -Most of these types should be pretty self explanatory. Here `S` is a -struct name and we assume structs are declared like so: - -```text -SD = struct S<'LT...> { (f: TY)... } -``` - -# Borrowing and loans - -## An intuitive explanation - -### Issuing loans - -Now, imagine we had a program like this: - -```text -struct Foo { f: uint, g: uint } -... -'a: { - let mut x: Box = ...; - let y = &mut (*x).f; - x = ...; -} -``` - -This is of course dangerous because mutating `x` will free the old -value and hence invalidate `y`. The borrow checker aims to prevent -this sort of thing. - -#### Loans and restrictions - -The way the borrow checker works is that it analyzes each borrow -expression (in our simple model, that's stuff like `&LV`, though in -real life there are a few other cases to consider). For each borrow -expression, it computes a `Loan`, which is a data structure that -records (1) the value being borrowed, (2) the mutability and scope of -the borrow, and (3) a set of restrictions. In the code, `Loan` is a -struct defined in `middle::borrowck`. Formally, we define `LOAN` as -follows: - -```text -LOAN = (LV, LT, MQ, RESTRICTION*) -RESTRICTION = (LV, ACTION*) -ACTION = MUTATE | CLAIM | FREEZE -``` - -Here the `LOAN` tuple defines the lvalue `LV` being borrowed; the -lifetime `LT` of that borrow; the mutability `MQ` of the borrow; and a -list of restrictions. The restrictions indicate actions which, if -taken, could invalidate the loan and lead to type safety violations. - -Each `RESTRICTION` is a pair of a restrictive lvalue `LV` (which will -either be the path that was borrowed or some prefix of the path that -was borrowed) and a set of restricted actions. There are three kinds -of actions that may be restricted for the path `LV`: - -- `MUTATE` means that `LV` cannot be assigned to; -- `CLAIM` means that the `LV` cannot be borrowed mutably; -- `FREEZE` means that the `LV` cannot be borrowed immutably; - -Finally, it is never possible to move from an lvalue that appears in a -restriction. This implies that the "empty restriction" `(LV, [])`, -which contains an empty set of actions, still has a purpose---it -prevents moves from `LV`. I chose not to make `MOVE` a fourth kind of -action because that would imply that sometimes moves are permitted -from restrictived values, which is not the case. - -#### Example - -To give you a better feeling for what kind of restrictions derived -from a loan, let's look at the loan `L` that would be issued as a -result of the borrow `&mut (*x).f` in the example above: - -```text -L = ((*x).f, 'a, mut, RS) where - RS = [((*x).f, [MUTATE, CLAIM, FREEZE]), - (*x, [MUTATE, CLAIM, FREEZE]), - (x, [MUTATE, CLAIM, FREEZE])] -``` - -The loan states that the expression `(*x).f` has been loaned as -mutable for the lifetime `'a`. Because the loan is mutable, that means -that the value `(*x).f` may be mutated via the newly created reference -(and *only* via that pointer). This is reflected in the -restrictions `RS` that accompany the loan. - -The first restriction `((*x).f, [MUTATE, CLAIM, FREEZE])` states that -the lender may not mutate, freeze, nor alias `(*x).f`. Mutation is -illegal because `(*x).f` is only supposed to be mutated via the new -reference, not by mutating the original path `(*x).f`. Freezing is -illegal because the path now has an `&mut` alias; so even if we the -lender were to consider `(*x).f` to be immutable, it might be mutated -via this alias. They will be enforced for the lifetime `'a` of the -loan. After the loan expires, the restrictions no longer apply. - -The second restriction on `*x` is interesting because it does not -apply to the path that was lent (`(*x).f`) but rather to a prefix of -the borrowed path. This is due to the rules of inherited mutability: -if the user were to assign to (or freeze) `*x`, they would indirectly -overwrite (or freeze) `(*x).f`, and thus invalidate the reference -that was created. In general it holds that when a path is -lent, restrictions are issued for all the owning prefixes of that -path. In this case, the path `*x` owns the path `(*x).f` and, -because `x` is an owned pointer, the path `x` owns the path `*x`. -Therefore, borrowing `(*x).f` yields restrictions on both -`*x` and `x`. - -### Checking for illegal assignments, moves, and reborrows - -Once we have computed the loans introduced by each borrow, the borrow -checker uses a data flow propagation to compute the full set of loans -in scope at each expression and then uses that set to decide whether -that expression is legal. Remember that the scope of loan is defined -by its lifetime LT. We sometimes say that a loan which is in-scope at -a particular point is an "outstanding loan", and the set of -restrictions included in those loans as the "outstanding -restrictions". - -The kinds of expressions which in-scope loans can render illegal are: -- *assignments* (`lv = v`): illegal if there is an in-scope restriction - against mutating `lv`; -- *moves*: illegal if there is any in-scope restriction on `lv` at all; -- *mutable borrows* (`&mut lv`): illegal there is an in-scope restriction - against claiming `lv`; -- *immutable borrows* (`&lv`): illegal there is an in-scope restriction - against freezing `lv`. - -## Formal rules - -Now that we hopefully have some kind of intuitive feeling for how the -borrow checker works, let's look a bit more closely now at the precise -conditions that it uses. For simplicity I will ignore const loans. - -I will present the rules in a modified form of standard inference -rules, which looks as follows: - -```text -PREDICATE(X, Y, Z) // Rule-Name - Condition 1 - Condition 2 - Condition 3 -``` - -The initial line states the predicate that is to be satisfied. The -indented lines indicate the conditions that must be met for the -predicate to be satisfied. The right-justified comment states the name -of this rule: there are comments in the borrowck source referencing -these names, so that you can cross reference to find the actual code -that corresponds to the formal rule. - -### Invariants - -I want to collect, at a high-level, the invariants the borrow checker -maintains. I will give them names and refer to them throughout the -text. Together these invariants are crucial for the overall soundness -of the system. - -**Mutability requires uniqueness.** To mutate a path - -**Unique mutability.** There is only one *usable* mutable path to any -given memory at any given time. This implies that when claiming memory -with an expression like `p = &mut x`, the compiler must guarantee that -the borrowed value `x` can no longer be mutated so long as `p` is -live. (This is done via restrictions, read on.) - -**.** - - -### The `gather_loans` pass - -We start with the `gather_loans` pass, which walks the AST looking for -borrows. For each borrow, there are three bits of information: the -lvalue `LV` being borrowed and the mutability `MQ` and lifetime `LT` -of the resulting pointer. Given those, `gather_loans` applies four -validity tests: - -1. `MUTABILITY(LV, MQ)`: The mutability of the reference is -compatible with the mutability of `LV` (i.e., not borrowing immutable -data as mutable). - -2. `ALIASABLE(LV, MQ)`: The aliasability of the reference is -compatible with the aliasability of `LV`. The goal is to prevent -`&mut` borrows of aliasability data. - -3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed -the lifetime of the value being borrowed. - -4. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the -restrictions to maintain memory safety. These are the restrictions -that will go into the final loan. We'll discuss in more detail below. - -## Checking mutability - -Checking mutability is fairly straightforward. We just want to prevent -immutable data from being borrowed as mutable. Note that it is ok to -borrow mutable data as immutable, since that is simply a -freeze. Formally we define a predicate `MUTABLE(LV, MQ)` which, if -defined, means that "borrowing `LV` with mutability `MQ` is ok. The -Rust code corresponding to this predicate is the function -`check_mutability` in `middle::borrowck::gather_loans`. - -### Checking mutability of variables - -*Code pointer:* Function `check_mutability()` in `gather_loans/mod.rs`, -but also the code in `mem_categorization`. - -Let's begin with the rules for variables, which state that if a -variable is declared as mutable, it may be borrowed any which way, but -otherwise the variable must be borrowed as immutable or const: - -```text -MUTABILITY(X, MQ) // M-Var-Mut - DECL(X) = mut - -MUTABILITY(X, MQ) // M-Var-Imm - DECL(X) = imm - MQ = imm | const -``` - -### Checking mutability of owned content - -Fields and owned pointers inherit their mutability from -their base expressions, so both of their rules basically -delegate the check to the base expression `LV`: - -```text -MUTABILITY(LV.f, MQ) // M-Field - MUTABILITY(LV, MQ) - -MUTABILITY(*LV, MQ) // M-Deref-Unique - TYPE(LV) = Box - MUTABILITY(LV, MQ) -``` - -### Checking mutability of immutable pointer types - -Immutable pointer types like `&T` can only -be borrowed if MQ is immutable or const: - -```text -MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Imm - TYPE(LV) = &Ty - MQ == imm | const -``` - -### Checking mutability of mutable pointer types - -`&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: - -```text -MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut - TYPE(LV) = &mut Ty -``` - -## Checking aliasability - -The goal of the aliasability check is to ensure that we never permit -`&mut` borrows of aliasable data. Formally we define a predicate -`ALIASABLE(LV, MQ)` which if defined means that -"borrowing `LV` with mutability `MQ` is ok". The -Rust code corresponding to this predicate is the function -`check_aliasability()` in `middle::borrowck::gather_loans`. - -### Checking aliasability of variables - -Local variables are never aliasable as they are accessible only within -the stack frame. - -```text - ALIASABLE(X, MQ) // M-Var-Mut -``` - -### Checking aliasable of owned content - -Owned content is aliasable if it is found in an aliasable location: - -```text -ALIASABLE(LV.f, MQ) // M-Field - ALIASABLE(LV, MQ) - -ALIASABLE(*LV, MQ) // M-Deref-Unique - ALIASABLE(LV, MQ) -``` - -### Checking mutability of immutable pointer types - -Immutable pointer types like `&T` are aliasable, and hence can only be -borrowed immutably: - -```text -ALIASABLE(*LV, imm) // M-Deref-Borrowed-Imm - TYPE(LV) = &Ty -``` - -### Checking mutability of mutable pointer types - -`&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: - -```text -ALIASABLE(*LV, MQ) // M-Deref-Borrowed-Mut - TYPE(LV) = &mut Ty -``` - -## Checking lifetime - -These rules aim to ensure that no data is borrowed for a scope that exceeds -its lifetime. These two computations wind up being intimately related. -Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that -"the lvalue `LV` can be safely borrowed for the lifetime `LT` with mutability -`MQ`". The Rust code corresponding to this predicate is the module -`middle::borrowck::gather_loans::lifetime`. - -### The Scope function - -Several of the rules refer to a helper function `SCOPE(LV)=LT`. The -`SCOPE(LV)` yields the lifetime `LT` for which the lvalue `LV` is -guaranteed to exist, presuming that no mutations occur. - -The scope of a local variable is the block where it is declared: - -```text - SCOPE(X) = block where X is declared -``` - -The scope of a field is the scope of the struct: - -```text - SCOPE(LV.f) = SCOPE(LV) -``` - -The scope of a unique referent is the scope of the pointer, since -(barring mutation or moves) the pointer will not be freed until -the pointer itself `LV` goes out of scope: - -```text - SCOPE(*LV) = SCOPE(LV) if LV has type Box -``` - -The scope of a borrowed referent is the scope associated with the -pointer. This is a conservative approximation, since the data that -the pointer points at may actually live longer: - -```text - SCOPE(*LV) = LT if LV has type &'LT T or &'LT mut T -``` - -### Checking lifetime of variables - -The rule for variables states that a variable can only be borrowed a -lifetime `LT` that is a subregion of the variable's scope: - -```text -LIFETIME(X, LT, MQ) // L-Local - LT <= SCOPE(X) -``` - -### Checking lifetime for owned content - -The lifetime of a field or owned pointer is the same as the lifetime -of its owner: - -```text -LIFETIME(LV.f, LT, MQ) // L-Field - LIFETIME(LV, LT, MQ) - -LIFETIME(*LV, LT, MQ) // L-Deref-Send - TYPE(LV) = Box - LIFETIME(LV, LT, MQ) -``` - -### Checking lifetime for derefs of references - -References have a lifetime `LT'` associated with them. The -data they point at has been guaranteed to be valid for at least this -lifetime. Therefore, the borrow is valid so long as the lifetime `LT` -of the borrow is shorter than the lifetime `LT'` of the pointer -itself: - -```text -LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed - TYPE(LV) = <' Ty OR <' mut Ty - LT <= LT' -``` - -## Computing the restrictions - -The final rules govern the computation of *restrictions*, meaning that -we compute the set of actions that will be illegal for the life of the -loan. The predicate is written `RESTRICTIONS(LV, LT, ACTIONS) = -RESTRICTION*`, which can be read "in order to prevent `ACTIONS` from -occurring on `LV`, the restrictions `RESTRICTION*` must be respected -for the lifetime of the loan". - -Note that there is an initial set of restrictions: these restrictions -are computed based on the kind of borrow: - -```text -&mut LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM|FREEZE) -&LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM) -&const LV => RESTRICTIONS(LV, LT, []) -``` - -The reasoning here is that a mutable borrow must be the only writer, -therefore it prevents other writes (`MUTATE`), mutable borrows -(`CLAIM`), and immutable borrows (`FREEZE`). An immutable borrow -permits other immutable borrows but forbids writes and mutable borrows. -Finally, a const borrow just wants to be sure that the value is not -moved out from under it, so no actions are forbidden. - -### Restrictions for loans of a local variable - -The simplest case is a borrow of a local variable `X`: - -```text -RESTRICTIONS(X, LT, ACTIONS) = (X, ACTIONS) // R-Variable -``` - -In such cases we just record the actions that are not permitted. - -### Restrictions for loans of fields - -Restricting a field is the same as restricting the owner of that -field: - -```text -RESTRICTIONS(LV.f, LT, ACTIONS) = RS, (LV.f, ACTIONS) // R-Field - RESTRICTIONS(LV, LT, ACTIONS) = RS -``` - -The reasoning here is as follows. If the field must not be mutated, -then you must not mutate the owner of the field either, since that -would indirectly modify the field. Similarly, if the field cannot be -frozen or aliased, we cannot allow the owner to be frozen or aliased, -since doing so indirectly freezes/aliases the field. This is the -origin of inherited mutability. - -### Restrictions for loans of owned referents - -Because the mutability of owned referents is inherited, restricting an -owned referent is similar to restricting a field, in that it implies -restrictions on the pointer. However, owned pointers have an important -twist: if the owner `LV` is mutated, that causes the owned referent -`*LV` to be freed! So whenever an owned referent `*LV` is borrowed, we -must prevent the owned pointer `LV` from being mutated, which means -that we always add `MUTATE` and `CLAIM` to the restriction set imposed -on `LV`: - -```text -RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer - TYPE(LV) = Box - RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS -``` - -### Restrictions for loans of immutable borrowed referents - -Immutable borrowed referents are freely aliasable, meaning that -the compiler does not prevent you from copying the pointer. This -implies that issuing restrictions is useless. We might prevent the -user from acting on `*LV` itself, but there could be another path -`*LV1` that refers to the exact same memory, and we would not be -restricting that path. Therefore, the rule for `&Ty` pointers -always returns an empty set of restrictions, and it only permits -restricting `MUTATE` and `CLAIM` actions: - -```text -RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed - TYPE(LV) = <' Ty - LT <= LT' // (1) - ACTIONS subset of [MUTATE, CLAIM] -``` - -The reason that we can restrict `MUTATE` and `CLAIM` actions even -without a restrictions list is that it is never legal to mutate nor to -borrow mutably the contents of a `&Ty` pointer. In other words, -those restrictions are already inherent in the type. - -Clause (1) in the rule for `&Ty` deserves mention. Here I -specify that the lifetime of the loan must be less than the lifetime -of the `&Ty` pointer. In simple cases, this clause is redundant, since -the `LIFETIME()` function will already enforce the required rule: - -``` -fn foo(point: &'a Point) -> &'static f32 { - &point.x // Error -} -``` - -The above example fails to compile both because of clause (1) above -but also by the basic `LIFETIME()` check. However, in more advanced -examples involving multiple nested pointers, clause (1) is needed: - -``` -fn foo(point: &'a &'b mut Point) -> &'b f32 { - &point.x // Error -} -``` - -The `LIFETIME` rule here would accept `'b` because, in fact, the -*memory is* guaranteed to remain valid (i.e., not be freed) for the -lifetime `'b`, since the `&mut` pointer is valid for `'b`. However, we -are returning an immutable reference, so we need the memory to be both -valid and immutable. Even though `point.x` is referenced by an `&mut` -pointer, it can still be considered immutable so long as that `&mut` -pointer is found in an aliased location. That means the memory is -guaranteed to be *immutable* for the lifetime of the `&` pointer, -which is only `'a`, not `'b`. Hence this example yields an error. - -As a final twist, consider the case of two nested *immutable* -pointers, rather than a mutable pointer within an immutable one: - -``` -fn foo(point: &'a &'b Point) -> &'b f32 { - &point.x // OK -} -``` - -This function is legal. The reason for this is that the inner pointer -(`*point : &'b Point`) is enough to guarantee the memory is immutable -and valid for the lifetime `'b`. This is reflected in -`RESTRICTIONS()` by the fact that we do not recurse (i.e., we impose -no restrictions on `LV`, which in this particular case is the pointer -`point : &'a &'b Point`). - -#### Why both `LIFETIME()` and `RESTRICTIONS()`? - -Given the previous text, it might seem that `LIFETIME` and -`RESTRICTIONS` should be folded together into one check, but there is -a reason that they are separated. They answer separate concerns. -The rules pertaining to `LIFETIME` exist to ensure that we don't -create a borrowed pointer that outlives the memory it points at. So -`LIFETIME` prevents a function like this: - -``` -fn get_1<'a>() -> &'a int { - let x = 1; - &x -} -``` - -Here we would be returning a pointer into the stack. Clearly bad. - -However, the `RESTRICTIONS` rules are more concerned with how memory -is used. The example above doesn't generate an error according to -`RESTRICTIONS` because, for local variables, we don't require that the -loan lifetime be a subset of the local variable lifetime. The idea -here is that we *can* guarantee that `x` is not (e.g.) mutated for the -lifetime `'a`, even though `'a` exceeds the function body and thus -involves unknown code in the caller -- after all, `x` ceases to exist -after we return and hence the remaining code in `'a` cannot possibly -mutate it. This distinction is important for type checking functions -like this one: - -``` -fn inc_and_get<'a>(p: &'a mut Point) -> &'a int { - p.x += 1; - &p.x -} -``` - -In this case, we take in a `&mut` and return a frozen borrowed pointer -with the same lifetime. So long as the lifetime of the returned value -doesn't exceed the lifetime of the `&mut` we receive as input, this is -fine, though it may seem surprising at first (it surprised me when I -first worked it through). After all, we're guaranteeing that `*p` -won't be mutated for the lifetime `'a`, even though we can't "see" the -entirety of the code during that lifetime, since some of it occurs in -our caller. But we *do* know that nobody can mutate `*p` except -through `p`. So if we don't mutate `*p` and we don't return `p`, then -we know that the right to mutate `*p` has been lost to our caller -- -in terms of capability, the caller passed in the ability to mutate -`*p`, and we never gave it back. (Note that we can't return `p` while -`*p` is borrowed since that would be a move of `p`, as `&mut` pointers -are affine.) - -### Restrictions for loans of const aliasable referents - -Freeze pointers are read-only. There may be `&mut` or `&` aliases, and -we can not prevent *anything* but moves in that case. So the -`RESTRICTIONS` function is only defined if `ACTIONS` is the empty set. -Because moves from a `&const` lvalue are never legal, it is not -necessary to add any restrictions at all to the final result. - -```text - RESTRICTIONS(*LV, LT, []) = [] // R-Deref-Freeze-Borrowed - TYPE(LV) = &const Ty -``` - -### Restrictions for loans of mutable borrowed referents - -Mutable borrowed pointers are guaranteed to be the only way to mutate -their referent. This permits us to take greater license with them; for -example, the referent can be frozen simply be ensuring that we do not -use the original pointer to perform mutate. Similarly, we can allow -the referent to be claimed, so long as the original pointer is unused -while the new claimant is live. - -The rule for mutable borrowed pointers is as follows: - -```text -RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Mut-Borrowed - TYPE(LV) = <' mut Ty - LT <= LT' // (1) - RESTRICTIONS(LV, LT, ACTIONS) = RS // (2) -``` - -Let's examine the two numbered clauses: - -Clause (1) specifies that the lifetime of the loan (`LT`) cannot -exceed the lifetime of the `&mut` pointer (`LT'`). The reason for this -is that the `&mut` pointer is guaranteed to be the only legal way to -mutate its referent -- but only for the lifetime `LT'`. After that -lifetime, the loan on the referent expires and hence the data may be -modified by its owner again. This implies that we are only able to -guarantee that the referent will not be modified or aliased for a -maximum of `LT'`. - -Here is a concrete example of a bug this rule prevents: - -``` -// Test region-reborrow-from-shorter-mut-ref.rs: -fn copy_pointer<'a,'b,T>(x: &'a mut &'b mut T) -> &'b mut T { - &mut **p // ERROR due to clause (1) -} -fn main() { - let mut x = 1; - let mut y = &mut x; // <-'b-----------------------------+ - // +-'a--------------------+ | - // v v | - let z = copy_borrowed_ptr(&mut y); // y is lent | - *y += 1; // Here y==z, so both should not be usable... | - *z += 1; // ...and yet they would be, but for clause 1. | -} // <------------------------------------------------------+ -``` - -Clause (2) propagates the restrictions on the referent to the pointer -itself. This is the same as with an owned pointer, though the -reasoning is mildly different. The basic goal in all cases is to -prevent the user from establishing another route to the same data. To -see what I mean, let's examine various cases of what can go wrong and -show how it is prevented. - -**Example danger 1: Moving the base pointer.** One of the simplest -ways to violate the rules is to move the base pointer to a new name -and access it via that new name, thus bypassing the restrictions on -the old name. Here is an example: - -``` -// src/test/compile-fail/borrowck-move-mut-base-ptr.rs -fn foo(t0: &mut int) { - let p: &int = &*t0; // Freezes `*t0` - let t1 = t0; //~ ERROR cannot move out of `t0` - *t1 = 22; // OK, not a write through `*t0` -} -``` - -Remember that `&mut` pointers are linear, and hence `let t1 = t0` is a -move of `t0` -- or would be, if it were legal. Instead, we get an -error, because clause (2) imposes restrictions on `LV` (`t0`, here), -and any restrictions on a path make it impossible to move from that -path. - -**Example danger 2: Claiming the base pointer.** Another possible -danger is to mutably borrow the base path. This can lead to two bad -scenarios. The most obvious is that the mutable borrow itself becomes -another path to access the same data, as shown here: - -``` -// src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` - let mut t2 = &mut t0; //~ ERROR cannot borrow `t0` - **t2 += 1; // Mutates `*t0` -} -``` - -In this example, `**t2` is the same memory as `*t0`. Because `t2` is -an `&mut` pointer, `**t2` is a unique path and hence it would be -possible to mutate `**t2` even though that memory was supposed to be -frozen by the creation of `p`. However, an error is reported -- the -reason is that the freeze `&*t0` will restrict claims and mutation -against `*t0` which, by clause 2, in turn prevents claims and mutation -of `t0`. Hence the claim `&mut t0` is illegal. - -Another danger with an `&mut` pointer is that we could swap the `t0` -value away to create a new path: - -``` -// src/test/compile-fail/borrowck-swap-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` - swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0` - *t1 = 22; -} -``` - -This is illegal for the same reason as above. Note that if we added -back a swap operator -- as we used to have -- we would want to be very -careful to ensure this example is still illegal. - -**Example danger 3: Freeze the base pointer.** In the case where the -referent is claimed, even freezing the base pointer can be dangerous, -as shown in the following example: - -``` -// src/test/compile-fail/borrowck-borrow-of-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &mut int = &mut *t0; // Claims `*t0` - let mut t2 = &t0; //~ ERROR cannot borrow `t0` - let q: &int = &*t2; // Freezes `*t0` but not through `*p` - *p += 1; // violates type of `*q` -} -``` - -Here the problem is that `*t0` is claimed by `p`, and hence `p` wants -to be the controlling pointer through which mutation or freezes occur. -But `t2` would -- if it were legal -- have the type `& &mut int`, and -hence would be a mutable pointer in an aliasable location, which is -considered frozen (since no one can write to `**t2` as it is not a -unique path). Therefore, we could reasonably create a frozen `&int` -pointer pointing at `*t0` that coexists with the mutable pointer `p`, -which is clearly unsound. - -However, it is not always unsafe to freeze the base pointer. In -particular, if the referent is frozen, there is no harm in it: - -``` -// src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` - let mut t2 = &t0; - let q: &int = &*t2; // Freezes `*t0`, but that's ok... - let r: &int = &*t0; // ...after all, could do same thing directly. -} -``` - -In this case, creating the alias `t2` of `t0` is safe because the only -thing `t2` can be used for is to further freeze `*t0`, which is -already frozen. In particular, we cannot assign to `*t0` through the -new alias `t2`, as demonstrated in this test case: - -``` -// src/test/run-pass/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs -fn foo(t0: & &mut int) { - let t1 = t0; - let p: &int = &**t0; - **t1 = 22; //~ ERROR cannot assign -} -``` - -This distinction is reflected in the rules. When doing an `&mut` -borrow -- as in the first example -- the set `ACTIONS` will be -`CLAIM|MUTATE|FREEZE`, because claiming the referent implies that it -cannot be claimed, mutated, or frozen by anyone else. These -restrictions are propagated back to the base path and hence the base -path is considered unfreezable. - -In contrast, when the referent is merely frozen -- as in the second -example -- the set `ACTIONS` will be `CLAIM|MUTATE`, because freezing -the referent implies that it cannot be claimed or mutated but permits -others to freeze. Hence when these restrictions are propagated back to -the base path, it will still be considered freezable. - - - -**FIXME #10520: Restrictions against mutating the base pointer.** When -an `&mut` pointer is frozen or claimed, we currently pass along the -restriction against MUTATE to the base pointer. I do not believe this -restriction is needed. It dates from the days when we had a way to -mutate that preserved the value being mutated (i.e., swap). Nowadays -the only form of mutation is assignment, which destroys the pointer -being mutated -- therefore, a mutation cannot create a new path to the -same data. Rather, it removes an existing path. This implies that not -only can we permit mutation, we can have mutation kill restrictions in -the dataflow sense. - -**WARNING:** We do not currently have `const` borrows in the -language. If they are added back in, we must ensure that they are -consistent with all of these examples. The crucial question will be -what sorts of actions are permitted with a `&const &mut` pointer. I -would suggest that an `&mut` referent found in an `&const` location be -prohibited from both freezes and claims. This would avoid the need to -prevent `const` borrows of the base pointer when the referent is -borrowed. - -# Moves and initialization - -The borrow checker is also in charge of ensuring that: - -- all memory which is accessed is initialized -- immutable local variables are assigned at most once. - -These are two separate dataflow analyses built on the same -framework. Let's look at checking that memory is initialized first; -the checking of immutable local variable assignments works in a very -similar way. - -To track the initialization of memory, we actually track all the -points in the program that *create uninitialized memory*, meaning -moves and the declaration of uninitialized variables. For each of -these points, we create a bit in the dataflow set. Assignments to a -variable `x` or path `a.b.c` kill the move/uninitialization bits for -those paths and any subpaths (e.g., `x`, `x.y`, `a.b.c`, `*a.b.c`). -Bits are unioned when two control-flow paths join. Thus, the -presence of a bit indicates that the move may have occurred without an -intervening assignment to the same memory. At each use of a variable, -we examine the bits in scope, and check that none of them are -moves/uninitializations of the variable that is being used. - -Let's look at a simple example: - -``` -fn foo(a: Box) { - let b: Box; // Gen bit 0. - - if cond { // Bits: 0 - use(&*a); - b = a; // Gen bit 1, kill bit 0. - use(&*b); - } else { - // Bits: 0 - } - // Bits: 0,1 - use(&*a); // Error. - use(&*b); // Error. -} - -fn use(a: &int) { } -``` - -In this example, the variable `b` is created uninitialized. In one -branch of an `if`, we then move the variable `a` into `b`. Once we -exit the `if`, therefore, it is an error to use `a` or `b` since both -are only conditionally initialized. I have annotated the dataflow -state using comments. There are two dataflow bits, with bit 0 -corresponding to the creation of `b` without an initializer, and bit 1 -corresponding to the move of `a`. The assignment `b = a` both -generates bit 1, because it is a move of `a`, and kills bit 0, because -`b` is now initialized. On the else branch, though, `b` is never -initialized, and so bit 0 remains untouched. When the two flows of -control join, we union the bits from both sides, resulting in both -bits 0 and 1 being set. Thus any attempt to use `a` uncovers the bit 1 -from the "then" branch, showing that `a` may be moved, and any attempt -to use `b` uncovers bit 0, from the "else" branch, showing that `b` -may not be initialized. - -## Initialization of immutable variables - -Initialization of immutable variables works in a very similar way, -except that: - -1. we generate bits for each assignment to a variable; -2. the bits are never killed except when the variable goes out of scope. - -Thus the presence of an assignment bit indicates that the assignment -may have occurred. Note that assignments are only killed when the -variable goes out of scope, as it is not relevant whether or not there -has been a move in the meantime. Using these bits, we can declare that -an assignment to an immutable variable is legal iff there is no other -assignment bit to that same variable in scope. - -## Why is the design made this way? - -It may seem surprising that we assign dataflow bits to *each move* -rather than *each path being moved*. This is somewhat less efficient, -since on each use, we must iterate through all moves and check whether -any of them correspond to the path in question. Similar concerns apply -to the analysis for double assignments to immutable variables. The -main reason to do it this way is that it allows us to print better -error messages, because when a use occurs, we can print out the -precise move that may be in scope, rather than simply having to say -"the variable may not be initialized". - -## Data structures used in the move analysis - -The move analysis maintains several data structures that enable it to -cross-reference moves and assignments to determine when they may be -moving/assigning the same memory. These are all collected into the -`MoveData` and `FlowedMoveData` structs. The former represents the set -of move paths, moves, and assignments, and the latter adds in the -results of a dataflow computation. - -### Move paths - -The `MovePath` tree tracks every path that is moved or assigned to. -These paths have the same form as the `LoanPath` data structure, which -in turn is the "real world version of the lvalues `LV` that we -introduced earlier. The difference between a `MovePath` and a `LoanPath` -is that move paths are: - -1. Canonicalized, so that we have exactly one copy of each, and - we can refer to move paths by index; -2. Cross-referenced with other paths into a tree, so that given a move - path we can efficiently find all parent move paths and all - extensions (e.g., given the `a.b` move path, we can easily find the - move path `a` and also the move paths `a.b.c`) -3. Cross-referenced with moves and assignments, so that we can - easily find all moves and assignments to a given path. - -The mechanism that we use is to create a `MovePath` record for each -move path. These are arranged in an array and are referenced using -`MovePathIndex` values, which are newtype'd indices. The `MovePath` -structs are arranged into a tree, representing using the standard -Knuth representation where each node has a child 'pointer' and a "next -sibling" 'pointer'. In addition, each `MovePath` has a parent -'pointer'. In this case, the 'pointers' are just `MovePathIndex` -values. - -In this way, if we want to find all base paths of a given move path, -we can just iterate up the parent pointers (see `each_base_path()` in -the `move_data` module). If we want to find all extensions, we can -iterate through the subtree (see `each_extending_path()`). - -### Moves and assignments - -There are structs to represent moves (`Move`) and assignments -(`Assignment`), and these are also placed into arrays and referenced -by index. All moves of a particular path are arranged into a linked -lists, beginning with `MovePath.first_move` and continuing through -`Move.next_move`. - -We distinguish between "var" assignments, which are assignments to a -variable like `x = foo`, and "path" assignments (`x.f = foo`). This -is because we need to assign dataflows to the former, but not the -latter, so as to check for double initialization of immutable -variables. - -### Gathering and checking moves - -Like loans, we distinguish two phases. The first, gathering, is where -we uncover all the moves and assignments. As with loans, we do some -basic sanity checking in this phase, so we'll report errors if you -attempt to move out of a borrowed pointer etc. Then we do the dataflow -(see `FlowedMoveData::new`). Finally, in the `check_loans.rs` code, we -walk back over, identify all uses, assignments, and captures, and -check that they are legal given the set of dataflow bits we have -computed for that program point. - -# Drop flags and structural fragments - -In addition to the job of enforcing memory safety, the borrow checker -code is also responsible for identifying the *structural fragments* of -data in the function, to support out-of-band dynamic drop flags -allocated on the stack. (For background, see [RFC PR #320].) - -[RFC PR #320]: https://github.com/rust-lang/rfcs/pull/320 - -Semantically, each piece of data that has a destructor may need a -boolean flag to indicate whether or not its destructor has been run -yet. However, in many cases there is no need to actually maintain such -a flag: It can be apparent from the code itself that a given path is -always initialized (or always deinitialized) when control reaches the -end of its owner's scope, and thus we can unconditionally emit (or -not) the destructor invocation for that path. - -A simple example of this is the following: - -```rust -struct D { p: int } -impl D { fn new(x: int) -> D { ... } -impl Drop for D { ... } - -fn foo(a: D, b: D, t: || -> bool) { - let c: D; - let d: D; - if t() { c = b; } -} -``` - -At the end of the body of `foo`, the compiler knows that `a` is -initialized, introducing a drop obligation (deallocating the boxed -integer) for the end of `a`'s scope that is run unconditionally. -Likewise the compiler knows that `d` is not initialized, and thus it -leave out the drop code for `d`. - -The compiler cannot statically know the drop-state of `b` nor `c` at -the end of their scope, since that depends on the value of -`t`. Therefore, we need to insert boolean flags to track whether we -need to drop `b` and `c`. - -However, the matter is not as simple as just mapping local variables -to their corresponding drop flags when necessary. In particular, in -addition to being able to move data out of local variables, Rust -allows one to move values in and out of structured data. - -Consider the following: - -```rust -struct S { x: D, y: D, z: D } - -fn foo(a: S, mut b: S, t: || -> bool) { - let mut c: S; - let d: S; - let e: S = a.clone(); - if t() { - c = b; - b.x = e.y; - } - if t() { c.y = D::new(4); } -} -``` - -As before, the drop obligations of `a` and `d` can be statically -determined, and again the state of `b` and `c` depend on dynamic -state. But additionally, the dynamic drop obligations introduced by -`b` and `c` are not just per-local boolean flags. For example, if the -first call to `t` returns `false` and the second call `true`, then at -the end of their scope, `b` will be completely initialized, but only -`c.y` in `c` will be initialized. If both calls to `t` return `true`, -then at the end of their scope, `c` will be completely initialized, -but only `b.x` will be initialized in `b`, and only `e.x` and `e.z` -will be initialized in `e`. - -Note that we need to cover the `z` field in each case in some way, -since it may (or may not) need to be dropped, even though `z` is never -directly mentioned in the body of the `foo` function. We call a path -like `b.z` a *fragment sibling* of `b.x`, since the field `z` comes -from the same structure `S` that declared the field `x` in `b.x`. - -In general we need to maintain boolean flags that match the -`S`-structure of both `b` and `c`. In addition, we need to consult -such a flag when doing an assignment (such as `c.y = D::new(4);` -above), in order to know whether or not there is a previous value that -needs to be dropped before we do the assignment. - -So for any given function, we need to determine what flags are needed -to track its drop obligations. Our strategy for determining the set of -flags is to represent the fragmentation of the structure explicitly: -by starting initially from the paths that are explicitly mentioned in -moves and assignments (such as `b.x` and `c.y` above), and then -traversing the structure of the path's type to identify leftover -*unmoved fragments*: assigning into `c.y` means that `c.x` and `c.z` -are leftover unmoved fragments. Each fragment represents a drop -obligation that may need to be tracked. Paths that are only moved or -assigned in their entirety (like `a` and `d`) are treated as a single -drop obligation. - -The fragment construction process works by piggy-backing on the -existing `move_data` module. We already have callbacks that visit each -direct move and assignment; these form the basis for the sets of -moved_leaf_paths and assigned_leaf_paths. From these leaves, we can -walk up their parent chain to identify all of their parent paths. -We need to identify the parents because of cases like the following: - -```rust -struct Pair{ x: X, y: Y } -fn foo(dd_d_d: Pair, D>, D>) { - other_function(dd_d_d.x.y); -} -``` - -In this code, the move of the path `dd_d.x.y` leaves behind not only -the fragment drop-obligation `dd_d.x.x` but also `dd_d.y` as well. - -Once we have identified the directly-referenced leaves and their -parents, we compute the left-over fragments, in the function -`fragments::add_fragment_siblings`. As of this writing this works by -looking at each directly-moved or assigned path P, and blindly -gathering all sibling fields of P (as well as siblings for the parents -of P, etc). After accumulating all such siblings, we filter out the -entries added as siblings of P that turned out to be -directly-referenced paths (or parents of directly referenced paths) -themselves, thus leaving the never-referenced "left-overs" as the only -thing left from the gathering step. - -## Array structural fragments - -A special case of the structural fragments discussed above are -the elements of an array that has been passed by value, such as -the following: - -```rust -fn foo(a: [D, ..10], i: uint) -> D { - a[i] -} -``` - -The above code moves a single element out of the input array `a`. -The remainder of the array still needs to be dropped; i.e., it -is a structural fragment. Note that after performing such a move, -it is not legal to read from the array `a`. There are a number of -ways to deal with this, but the important thing to note is that -the semantics needs to distinguish in some manner between a -fragment that is the *entire* array versus a fragment that represents -all-but-one element of the array. A place where that distinction -would arise is the following: - -```rust -fn foo(a: [D, ..10], b: [D, ..10], i: uint, t: bool) -> D { - if t { - a[i] - } else { - b[i] - } - - // When control exits, we will need either to drop all of `a` - // and all-but-one of `b`, or to drop all of `b` and all-but-one - // of `a`. -} -``` - -There are a number of ways that the trans backend could choose to -compile this (e.g. a `[bool, ..10]` array for each such moved array; -or an `Option` for each moved array). From the viewpoint of the -borrow-checker, the important thing is to record what kind of fragment -is implied by the relevant moves. - -# Future work - -While writing up these docs, I encountered some rules I believe to be -stricter than necessary: - -- I think restricting the `&mut` LV against moves and `ALIAS` is sufficient, - `MUTATE` and `CLAIM` are overkill. `MUTATE` was necessary when swap was - a built-in operator, but as it is not, it is implied by `CLAIM`, - and `CLAIM` is implied by `ALIAS`. The only net effect of this is an - extra error message in some cases, though. -- I have not described how closures interact. Current code is unsound. - I am working on describing and implementing the fix. -- If we wish, we can easily extend the move checking to allow finer-grained - tracking of what is initialized and what is not, enabling code like - this: - - a = x.f.g; // x.f.g is now uninitialized - // here, x and x.f are not usable, but x.f.h *is* - x.f.g = b; // x.f.g is not initialized - // now x, x.f, x.f.g, x.f.h are all usable - - What needs to change here, most likely, is that the `moves` module - should record not only what paths are moved, but what expressions - are actual *uses*. For example, the reference to `x` in `x.f.g = b` - is not a true *use* in the sense that it requires `x` to be fully - initialized. This is in fact why the above code produces an error - today: the reference to `x` in `x.f.g = b` is considered illegal - because `x` is not fully initialized. - -There are also some possible refactorings: - -- It might be nice to replace all loan paths with the MovePath mechanism, - since they allow lightweight comparison using an integer. - -*/ +//! # The Borrow Checker +//! +//! This pass has the job of enforcing memory safety. This is a subtle +//! topic. This docs aim to explain both the practice and the theory +//! behind the borrow checker. They start with a high-level overview of +//! how it works, and then proceed to dive into the theoretical +//! background. Finally, they go into detail on some of the more subtle +//! aspects. +//! +//! # Table of contents +//! +//! These docs are long. Search for the section you are interested in. +//! +//! - Overview +//! - Formal model +//! - Borrowing and loans +//! - Moves and initialization +//! - Drop flags and structural fragments +//! - Future work +//! +//! # Overview +//! +//! The borrow checker checks one function at a time. It operates in two +//! passes. The first pass, called `gather_loans`, walks over the function +//! and identifies all of the places where borrows (e.g., `&` expressions +//! and `ref` bindings) and moves (copies or captures of a linear value) +//! occur. It also tracks initialization sites. For each borrow and move, +//! it checks various basic safety conditions at this time (for example, +//! that the lifetime of the borrow doesn't exceed the lifetime of the +//! value being borrowed, or that there is no move out of an `&T` +//! referent). +//! +//! It then uses the dataflow module to propagate which of those borrows +//! may be in scope at each point in the procedure. A loan is considered +//! to come into scope at the expression that caused it and to go out of +//! scope when the lifetime of the resulting reference expires. +//! +//! Once the in-scope loans are known for each point in the program, the +//! borrow checker walks the IR again in a second pass called +//! `check_loans`. This pass examines each statement and makes sure that +//! it is safe with respect to the in-scope loans. +//! +//! # Formal model +//! +//! Throughout the docs we'll consider a simple subset of Rust in which +//! you can only borrow from lvalues, defined like so: +//! +//! ```text +//! LV = x | LV.f | *LV +//! ``` +//! +//! Here `x` represents some variable, `LV.f` is a field reference, +//! and `*LV` is a pointer dereference. There is no auto-deref or other +//! niceties. This means that if you have a type like: +//! +//! ```text +//! struct S { f: uint } +//! ``` +//! +//! and a variable `a: Box`, then the rust expression `a.f` would correspond +//! to an `LV` of `(*a).f`. +//! +//! Here is the formal grammar for the types we'll consider: +//! +//! ```text +//! TY = () | S<'LT...> | Box | & 'LT MQ TY +//! MQ = mut | imm | const +//! ``` +//! +//! Most of these types should be pretty self explanatory. Here `S` is a +//! struct name and we assume structs are declared like so: +//! +//! ```text +//! SD = struct S<'LT...> { (f: TY)... } +//! ``` +//! +//! # Borrowing and loans +//! +//! ## An intuitive explanation +//! +//! ### Issuing loans +//! +//! Now, imagine we had a program like this: +//! +//! ```text +//! struct Foo { f: uint, g: uint } +//! ... +//! 'a: { +//! let mut x: Box = ...; +//! let y = &mut (*x).f; +//! x = ...; +//! } +//! ``` +//! +//! This is of course dangerous because mutating `x` will free the old +//! value and hence invalidate `y`. The borrow checker aims to prevent +//! this sort of thing. +//! +//! #### Loans and restrictions +//! +//! The way the borrow checker works is that it analyzes each borrow +//! expression (in our simple model, that's stuff like `&LV`, though in +//! real life there are a few other cases to consider). For each borrow +//! expression, it computes a `Loan`, which is a data structure that +//! records (1) the value being borrowed, (2) the mutability and scope of +//! the borrow, and (3) a set of restrictions. In the code, `Loan` is a +//! struct defined in `middle::borrowck`. Formally, we define `LOAN` as +//! follows: +//! +//! ```text +//! LOAN = (LV, LT, MQ, RESTRICTION*) +//! RESTRICTION = (LV, ACTION*) +//! ACTION = MUTATE | CLAIM | FREEZE +//! ``` +//! +//! Here the `LOAN` tuple defines the lvalue `LV` being borrowed; the +//! lifetime `LT` of that borrow; the mutability `MQ` of the borrow; and a +//! list of restrictions. The restrictions indicate actions which, if +//! taken, could invalidate the loan and lead to type safety violations. +//! +//! Each `RESTRICTION` is a pair of a restrictive lvalue `LV` (which will +//! either be the path that was borrowed or some prefix of the path that +//! was borrowed) and a set of restricted actions. There are three kinds +//! of actions that may be restricted for the path `LV`: +//! +//! - `MUTATE` means that `LV` cannot be assigned to; +//! - `CLAIM` means that the `LV` cannot be borrowed mutably; +//! - `FREEZE` means that the `LV` cannot be borrowed immutably; +//! +//! Finally, it is never possible to move from an lvalue that appears in a +//! restriction. This implies that the "empty restriction" `(LV, [])`, +//! which contains an empty set of actions, still has a purpose---it +//! prevents moves from `LV`. I chose not to make `MOVE` a fourth kind of +//! action because that would imply that sometimes moves are permitted +//! from restrictived values, which is not the case. +//! +//! #### Example +//! +//! To give you a better feeling for what kind of restrictions derived +//! from a loan, let's look at the loan `L` that would be issued as a +//! result of the borrow `&mut (*x).f` in the example above: +//! +//! ```text +//! L = ((*x).f, 'a, mut, RS) where +//! RS = [((*x).f, [MUTATE, CLAIM, FREEZE]), +//! (*x, [MUTATE, CLAIM, FREEZE]), +//! (x, [MUTATE, CLAIM, FREEZE])] +//! ``` +//! +//! The loan states that the expression `(*x).f` has been loaned as +//! mutable for the lifetime `'a`. Because the loan is mutable, that means +//! that the value `(*x).f` may be mutated via the newly created reference +//! (and *only* via that pointer). This is reflected in the +//! restrictions `RS` that accompany the loan. +//! +//! The first restriction `((*x).f, [MUTATE, CLAIM, FREEZE])` states that +//! the lender may not mutate, freeze, nor alias `(*x).f`. Mutation is +//! illegal because `(*x).f` is only supposed to be mutated via the new +//! reference, not by mutating the original path `(*x).f`. Freezing is +//! illegal because the path now has an `&mut` alias; so even if we the +//! lender were to consider `(*x).f` to be immutable, it might be mutated +//! via this alias. They will be enforced for the lifetime `'a` of the +//! loan. After the loan expires, the restrictions no longer apply. +//! +//! The second restriction on `*x` is interesting because it does not +//! apply to the path that was lent (`(*x).f`) but rather to a prefix of +//! the borrowed path. This is due to the rules of inherited mutability: +//! if the user were to assign to (or freeze) `*x`, they would indirectly +//! overwrite (or freeze) `(*x).f`, and thus invalidate the reference +//! that was created. In general it holds that when a path is +//! lent, restrictions are issued for all the owning prefixes of that +//! path. In this case, the path `*x` owns the path `(*x).f` and, +//! because `x` is an owned pointer, the path `x` owns the path `*x`. +//! Therefore, borrowing `(*x).f` yields restrictions on both +//! `*x` and `x`. +//! +//! ### Checking for illegal assignments, moves, and reborrows +//! +//! Once we have computed the loans introduced by each borrow, the borrow +//! checker uses a data flow propagation to compute the full set of loans +//! in scope at each expression and then uses that set to decide whether +//! that expression is legal. Remember that the scope of loan is defined +//! by its lifetime LT. We sometimes say that a loan which is in-scope at +//! a particular point is an "outstanding loan", and the set of +//! restrictions included in those loans as the "outstanding +//! restrictions". +//! +//! The kinds of expressions which in-scope loans can render illegal are: +//! - *assignments* (`lv = v`): illegal if there is an in-scope restriction +//! against mutating `lv`; +//! - *moves*: illegal if there is any in-scope restriction on `lv` at all; +//! - *mutable borrows* (`&mut lv`): illegal there is an in-scope restriction +//! against claiming `lv`; +//! - *immutable borrows* (`&lv`): illegal there is an in-scope restriction +//! against freezing `lv`. +//! +//! ## Formal rules +//! +//! Now that we hopefully have some kind of intuitive feeling for how the +//! borrow checker works, let's look a bit more closely now at the precise +//! conditions that it uses. For simplicity I will ignore const loans. +//! +//! I will present the rules in a modified form of standard inference +//! rules, which looks as follows: +//! +//! ```text +//! PREDICATE(X, Y, Z) // Rule-Name +//! Condition 1 +//! Condition 2 +//! Condition 3 +//! ``` +//! +//! The initial line states the predicate that is to be satisfied. The +//! indented lines indicate the conditions that must be met for the +//! predicate to be satisfied. The right-justified comment states the name +//! of this rule: there are comments in the borrowck source referencing +//! these names, so that you can cross reference to find the actual code +//! that corresponds to the formal rule. +//! +//! ### Invariants +//! +//! I want to collect, at a high-level, the invariants the borrow checker +//! maintains. I will give them names and refer to them throughout the +//! text. Together these invariants are crucial for the overall soundness +//! of the system. +//! +//! **Mutability requires uniqueness.** To mutate a path +//! +//! **Unique mutability.** There is only one *usable* mutable path to any +//! given memory at any given time. This implies that when claiming memory +//! with an expression like `p = &mut x`, the compiler must guarantee that +//! the borrowed value `x` can no longer be mutated so long as `p` is +//! live. (This is done via restrictions, read on.) +//! +//! **.** +//! +//! +//! ### The `gather_loans` pass +//! +//! We start with the `gather_loans` pass, which walks the AST looking for +//! borrows. For each borrow, there are three bits of information: the +//! lvalue `LV` being borrowed and the mutability `MQ` and lifetime `LT` +//! of the resulting pointer. Given those, `gather_loans` applies four +//! validity tests: +//! +//! 1. `MUTABILITY(LV, MQ)`: The mutability of the reference is +//! compatible with the mutability of `LV` (i.e., not borrowing immutable +//! data as mutable). +//! +//! 2. `ALIASABLE(LV, MQ)`: The aliasability of the reference is +//! compatible with the aliasability of `LV`. The goal is to prevent +//! `&mut` borrows of aliasability data. +//! +//! 3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed +//! the lifetime of the value being borrowed. +//! +//! 4. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the +//! restrictions to maintain memory safety. These are the restrictions +//! that will go into the final loan. We'll discuss in more detail below. +//! +//! ## Checking mutability +//! +//! Checking mutability is fairly straightforward. We just want to prevent +//! immutable data from being borrowed as mutable. Note that it is ok to +//! borrow mutable data as immutable, since that is simply a +//! freeze. Formally we define a predicate `MUTABLE(LV, MQ)` which, if +//! defined, means that "borrowing `LV` with mutability `MQ` is ok. The +//! Rust code corresponding to this predicate is the function +//! `check_mutability` in `middle::borrowck::gather_loans`. +//! +//! ### Checking mutability of variables +//! +//! *Code pointer:* Function `check_mutability()` in `gather_loans/mod.rs`, +//! but also the code in `mem_categorization`. +//! +//! Let's begin with the rules for variables, which state that if a +//! variable is declared as mutable, it may be borrowed any which way, but +//! otherwise the variable must be borrowed as immutable or const: +//! +//! ```text +//! MUTABILITY(X, MQ) // M-Var-Mut +//! DECL(X) = mut +//! +//! MUTABILITY(X, MQ) // M-Var-Imm +//! DECL(X) = imm +//! MQ = imm | const +//! ``` +//! +//! ### Checking mutability of owned content +//! +//! Fields and owned pointers inherit their mutability from +//! their base expressions, so both of their rules basically +//! delegate the check to the base expression `LV`: +//! +//! ```text +//! MUTABILITY(LV.f, MQ) // M-Field +//! MUTABILITY(LV, MQ) +//! +//! MUTABILITY(*LV, MQ) // M-Deref-Unique +//! TYPE(LV) = Box +//! MUTABILITY(LV, MQ) +//! ``` +//! +//! ### Checking mutability of immutable pointer types +//! +//! Immutable pointer types like `&T` can only +//! be borrowed if MQ is immutable or const: +//! +//! ```text +//! MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Imm +//! TYPE(LV) = &Ty +//! MQ == imm | const +//! ``` +//! +//! ### Checking mutability of mutable pointer types +//! +//! `&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: +//! +//! ```text +//! MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut +//! TYPE(LV) = &mut Ty +//! ``` +//! +//! ## Checking aliasability +//! +//! The goal of the aliasability check is to ensure that we never permit +//! `&mut` borrows of aliasable data. Formally we define a predicate +//! `ALIASABLE(LV, MQ)` which if defined means that +//! "borrowing `LV` with mutability `MQ` is ok". The +//! Rust code corresponding to this predicate is the function +//! `check_aliasability()` in `middle::borrowck::gather_loans`. +//! +//! ### Checking aliasability of variables +//! +//! Local variables are never aliasable as they are accessible only within +//! the stack frame. +//! +//! ```text +//! ALIASABLE(X, MQ) // M-Var-Mut +//! ``` +//! +//! ### Checking aliasable of owned content +//! +//! Owned content is aliasable if it is found in an aliasable location: +//! +//! ```text +//! ALIASABLE(LV.f, MQ) // M-Field +//! ALIASABLE(LV, MQ) +//! +//! ALIASABLE(*LV, MQ) // M-Deref-Unique +//! ALIASABLE(LV, MQ) +//! ``` +//! +//! ### Checking mutability of immutable pointer types +//! +//! Immutable pointer types like `&T` are aliasable, and hence can only be +//! borrowed immutably: +//! +//! ```text +//! ALIASABLE(*LV, imm) // M-Deref-Borrowed-Imm +//! TYPE(LV) = &Ty +//! ``` +//! +//! ### Checking mutability of mutable pointer types +//! +//! `&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut: +//! +//! ```text +//! ALIASABLE(*LV, MQ) // M-Deref-Borrowed-Mut +//! TYPE(LV) = &mut Ty +//! ``` +//! +//! ## Checking lifetime +//! +//! These rules aim to ensure that no data is borrowed for a scope that exceeds +//! its lifetime. These two computations wind up being intimately related. +//! Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that +//! "the lvalue `LV` can be safely borrowed for the lifetime `LT` with mutability +//! `MQ`". The Rust code corresponding to this predicate is the module +//! `middle::borrowck::gather_loans::lifetime`. +//! +//! ### The Scope function +//! +//! Several of the rules refer to a helper function `SCOPE(LV)=LT`. The +//! `SCOPE(LV)` yields the lifetime `LT` for which the lvalue `LV` is +//! guaranteed to exist, presuming that no mutations occur. +//! +//! The scope of a local variable is the block where it is declared: +//! +//! ```text +//! SCOPE(X) = block where X is declared +//! ``` +//! +//! The scope of a field is the scope of the struct: +//! +//! ```text +//! SCOPE(LV.f) = SCOPE(LV) +//! ``` +//! +//! The scope of a unique referent is the scope of the pointer, since +//! (barring mutation or moves) the pointer will not be freed until +//! the pointer itself `LV` goes out of scope: +//! +//! ```text +//! SCOPE(*LV) = SCOPE(LV) if LV has type Box +//! ``` +//! +//! The scope of a borrowed referent is the scope associated with the +//! pointer. This is a conservative approximation, since the data that +//! the pointer points at may actually live longer: +//! +//! ```text +//! SCOPE(*LV) = LT if LV has type &'LT T or &'LT mut T +//! ``` +//! +//! ### Checking lifetime of variables +//! +//! The rule for variables states that a variable can only be borrowed a +//! lifetime `LT` that is a subregion of the variable's scope: +//! +//! ```text +//! LIFETIME(X, LT, MQ) // L-Local +//! LT <= SCOPE(X) +//! ``` +//! +//! ### Checking lifetime for owned content +//! +//! The lifetime of a field or owned pointer is the same as the lifetime +//! of its owner: +//! +//! ```text +//! LIFETIME(LV.f, LT, MQ) // L-Field +//! LIFETIME(LV, LT, MQ) +//! +//! LIFETIME(*LV, LT, MQ) // L-Deref-Send +//! TYPE(LV) = Box +//! LIFETIME(LV, LT, MQ) +//! ``` +//! +//! ### Checking lifetime for derefs of references +//! +//! References have a lifetime `LT'` associated with them. The +//! data they point at has been guaranteed to be valid for at least this +//! lifetime. Therefore, the borrow is valid so long as the lifetime `LT` +//! of the borrow is shorter than the lifetime `LT'` of the pointer +//! itself: +//! +//! ```text +//! LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed +//! TYPE(LV) = <' Ty OR <' mut Ty +//! LT <= LT' +//! ``` +//! +//! ## Computing the restrictions +//! +//! The final rules govern the computation of *restrictions*, meaning that +//! we compute the set of actions that will be illegal for the life of the +//! loan. The predicate is written `RESTRICTIONS(LV, LT, ACTIONS) = +//! RESTRICTION*`, which can be read "in order to prevent `ACTIONS` from +//! occurring on `LV`, the restrictions `RESTRICTION*` must be respected +//! for the lifetime of the loan". +//! +//! Note that there is an initial set of restrictions: these restrictions +//! are computed based on the kind of borrow: +//! +//! ```text +//! &mut LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM|FREEZE) +//! &LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM) +//! &const LV => RESTRICTIONS(LV, LT, []) +//! ``` +//! +//! The reasoning here is that a mutable borrow must be the only writer, +//! therefore it prevents other writes (`MUTATE`), mutable borrows +//! (`CLAIM`), and immutable borrows (`FREEZE`). An immutable borrow +//! permits other immutable borrows but forbids writes and mutable borrows. +//! Finally, a const borrow just wants to be sure that the value is not +//! moved out from under it, so no actions are forbidden. +//! +//! ### Restrictions for loans of a local variable +//! +//! The simplest case is a borrow of a local variable `X`: +//! +//! ```text +//! RESTRICTIONS(X, LT, ACTIONS) = (X, ACTIONS) // R-Variable +//! ``` +//! +//! In such cases we just record the actions that are not permitted. +//! +//! ### Restrictions for loans of fields +//! +//! Restricting a field is the same as restricting the owner of that +//! field: +//! +//! ```text +//! RESTRICTIONS(LV.f, LT, ACTIONS) = RS, (LV.f, ACTIONS) // R-Field +//! RESTRICTIONS(LV, LT, ACTIONS) = RS +//! ``` +//! +//! The reasoning here is as follows. If the field must not be mutated, +//! then you must not mutate the owner of the field either, since that +//! would indirectly modify the field. Similarly, if the field cannot be +//! frozen or aliased, we cannot allow the owner to be frozen or aliased, +//! since doing so indirectly freezes/aliases the field. This is the +//! origin of inherited mutability. +//! +//! ### Restrictions for loans of owned referents +//! +//! Because the mutability of owned referents is inherited, restricting an +//! owned referent is similar to restricting a field, in that it implies +//! restrictions on the pointer. However, owned pointers have an important +//! twist: if the owner `LV` is mutated, that causes the owned referent +//! `*LV` to be freed! So whenever an owned referent `*LV` is borrowed, we +//! must prevent the owned pointer `LV` from being mutated, which means +//! that we always add `MUTATE` and `CLAIM` to the restriction set imposed +//! on `LV`: +//! +//! ```text +//! RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer +//! TYPE(LV) = Box +//! RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS +//! ``` +//! +//! ### Restrictions for loans of immutable borrowed referents +//! +//! Immutable borrowed referents are freely aliasable, meaning that +//! the compiler does not prevent you from copying the pointer. This +//! implies that issuing restrictions is useless. We might prevent the +//! user from acting on `*LV` itself, but there could be another path +//! `*LV1` that refers to the exact same memory, and we would not be +//! restricting that path. Therefore, the rule for `&Ty` pointers +//! always returns an empty set of restrictions, and it only permits +//! restricting `MUTATE` and `CLAIM` actions: +//! +//! ```text +//! RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed +//! TYPE(LV) = <' Ty +//! LT <= LT' // (1) +//! ACTIONS subset of [MUTATE, CLAIM] +//! ``` +//! +//! The reason that we can restrict `MUTATE` and `CLAIM` actions even +//! without a restrictions list is that it is never legal to mutate nor to +//! borrow mutably the contents of a `&Ty` pointer. In other words, +//! those restrictions are already inherent in the type. +//! +//! Clause (1) in the rule for `&Ty` deserves mention. Here I +//! specify that the lifetime of the loan must be less than the lifetime +//! of the `&Ty` pointer. In simple cases, this clause is redundant, since +//! the `LIFETIME()` function will already enforce the required rule: +//! +//! ``` +//! fn foo(point: &'a Point) -> &'static f32 { +//! &point.x // Error +//! } +//! ``` +//! +//! The above example fails to compile both because of clause (1) above +//! but also by the basic `LIFETIME()` check. However, in more advanced +//! examples involving multiple nested pointers, clause (1) is needed: +//! +//! ``` +//! fn foo(point: &'a &'b mut Point) -> &'b f32 { +//! &point.x // Error +//! } +//! ``` +//! +//! The `LIFETIME` rule here would accept `'b` because, in fact, the +//! *memory is* guaranteed to remain valid (i.e., not be freed) for the +//! lifetime `'b`, since the `&mut` pointer is valid for `'b`. However, we +//! are returning an immutable reference, so we need the memory to be both +//! valid and immutable. Even though `point.x` is referenced by an `&mut` +//! pointer, it can still be considered immutable so long as that `&mut` +//! pointer is found in an aliased location. That means the memory is +//! guaranteed to be *immutable* for the lifetime of the `&` pointer, +//! which is only `'a`, not `'b`. Hence this example yields an error. +//! +//! As a final twist, consider the case of two nested *immutable* +//! pointers, rather than a mutable pointer within an immutable one: +//! +//! ``` +//! fn foo(point: &'a &'b Point) -> &'b f32 { +//! &point.x // OK +//! } +//! ``` +//! +//! This function is legal. The reason for this is that the inner pointer +//! (`*point : &'b Point`) is enough to guarantee the memory is immutable +//! and valid for the lifetime `'b`. This is reflected in +//! `RESTRICTIONS()` by the fact that we do not recurse (i.e., we impose +//! no restrictions on `LV`, which in this particular case is the pointer +//! `point : &'a &'b Point`). +//! +//! #### Why both `LIFETIME()` and `RESTRICTIONS()`? +//! +//! Given the previous text, it might seem that `LIFETIME` and +//! `RESTRICTIONS` should be folded together into one check, but there is +//! a reason that they are separated. They answer separate concerns. +//! The rules pertaining to `LIFETIME` exist to ensure that we don't +//! create a borrowed pointer that outlives the memory it points at. So +//! `LIFETIME` prevents a function like this: +//! +//! ``` +//! fn get_1<'a>() -> &'a int { +//! let x = 1; +//! &x +//! } +//! ``` +//! +//! Here we would be returning a pointer into the stack. Clearly bad. +//! +//! However, the `RESTRICTIONS` rules are more concerned with how memory +//! is used. The example above doesn't generate an error according to +//! `RESTRICTIONS` because, for local variables, we don't require that the +//! loan lifetime be a subset of the local variable lifetime. The idea +//! here is that we *can* guarantee that `x` is not (e.g.) mutated for the +//! lifetime `'a`, even though `'a` exceeds the function body and thus +//! involves unknown code in the caller -- after all, `x` ceases to exist +//! after we return and hence the remaining code in `'a` cannot possibly +//! mutate it. This distinction is important for type checking functions +//! like this one: +//! +//! ``` +//! fn inc_and_get<'a>(p: &'a mut Point) -> &'a int { +//! p.x += 1; +//! &p.x +//! } +//! ``` +//! +//! In this case, we take in a `&mut` and return a frozen borrowed pointer +//! with the same lifetime. So long as the lifetime of the returned value +//! doesn't exceed the lifetime of the `&mut` we receive as input, this is +//! fine, though it may seem surprising at first (it surprised me when I +//! first worked it through). After all, we're guaranteeing that `*p` +//! won't be mutated for the lifetime `'a`, even though we can't "see" the +//! entirety of the code during that lifetime, since some of it occurs in +//! our caller. But we *do* know that nobody can mutate `*p` except +//! through `p`. So if we don't mutate `*p` and we don't return `p`, then +//! we know that the right to mutate `*p` has been lost to our caller -- +//! in terms of capability, the caller passed in the ability to mutate +//! `*p`, and we never gave it back. (Note that we can't return `p` while +//! `*p` is borrowed since that would be a move of `p`, as `&mut` pointers +//! are affine.) +//! +//! ### Restrictions for loans of const aliasable referents +//! +//! Freeze pointers are read-only. There may be `&mut` or `&` aliases, and +//! we can not prevent *anything* but moves in that case. So the +//! `RESTRICTIONS` function is only defined if `ACTIONS` is the empty set. +//! Because moves from a `&const` lvalue are never legal, it is not +//! necessary to add any restrictions at all to the final result. +//! +//! ```text +//! RESTRICTIONS(*LV, LT, []) = [] // R-Deref-Freeze-Borrowed +//! TYPE(LV) = &const Ty +//! ``` +//! +//! ### Restrictions for loans of mutable borrowed referents +//! +//! Mutable borrowed pointers are guaranteed to be the only way to mutate +//! their referent. This permits us to take greater license with them; for +//! example, the referent can be frozen simply be ensuring that we do not +//! use the original pointer to perform mutate. Similarly, we can allow +//! the referent to be claimed, so long as the original pointer is unused +//! while the new claimant is live. +//! +//! The rule for mutable borrowed pointers is as follows: +//! +//! ```text +//! RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Mut-Borrowed +//! TYPE(LV) = <' mut Ty +//! LT <= LT' // (1) +//! RESTRICTIONS(LV, LT, ACTIONS) = RS // (2) +//! ``` +//! +//! Let's examine the two numbered clauses: +//! +//! Clause (1) specifies that the lifetime of the loan (`LT`) cannot +//! exceed the lifetime of the `&mut` pointer (`LT'`). The reason for this +//! is that the `&mut` pointer is guaranteed to be the only legal way to +//! mutate its referent -- but only for the lifetime `LT'`. After that +//! lifetime, the loan on the referent expires and hence the data may be +//! modified by its owner again. This implies that we are only able to +//! guarantee that the referent will not be modified or aliased for a +//! maximum of `LT'`. +//! +//! Here is a concrete example of a bug this rule prevents: +//! +//! ``` +//! // Test region-reborrow-from-shorter-mut-ref.rs: +//! fn copy_pointer<'a,'b,T>(x: &'a mut &'b mut T) -> &'b mut T { +//! &mut **p // ERROR due to clause (1) +//! } +//! fn main() { +//! let mut x = 1; +//! let mut y = &mut x; // <-'b-----------------------------+ +//! // +-'a--------------------+ | +//! // v v | +//! let z = copy_borrowed_ptr(&mut y); // y is lent | +//! *y += 1; // Here y==z, so both should not be usable... | +//! *z += 1; // ...and yet they would be, but for clause 1. | +//! } // <------------------------------------------------------+ +//! ``` +//! +//! Clause (2) propagates the restrictions on the referent to the pointer +//! itself. This is the same as with an owned pointer, though the +//! reasoning is mildly different. The basic goal in all cases is to +//! prevent the user from establishing another route to the same data. To +//! see what I mean, let's examine various cases of what can go wrong and +//! show how it is prevented. +//! +//! **Example danger 1: Moving the base pointer.** One of the simplest +//! ways to violate the rules is to move the base pointer to a new name +//! and access it via that new name, thus bypassing the restrictions on +//! the old name. Here is an example: +//! +//! ``` +//! // src/test/compile-fail/borrowck-move-mut-base-ptr.rs +//! fn foo(t0: &mut int) { +//! let p: &int = &*t0; // Freezes `*t0` +//! let t1 = t0; //~ ERROR cannot move out of `t0` +//! *t1 = 22; // OK, not a write through `*t0` +//! } +//! ``` +//! +//! Remember that `&mut` pointers are linear, and hence `let t1 = t0` is a +//! move of `t0` -- or would be, if it were legal. Instead, we get an +//! error, because clause (2) imposes restrictions on `LV` (`t0`, here), +//! and any restrictions on a path make it impossible to move from that +//! path. +//! +//! **Example danger 2: Claiming the base pointer.** Another possible +//! danger is to mutably borrow the base path. This can lead to two bad +//! scenarios. The most obvious is that the mutable borrow itself becomes +//! another path to access the same data, as shown here: +//! +//! ``` +//! // src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs +//! fn foo<'a>(mut t0: &'a mut int, +//! mut t1: &'a mut int) { +//! let p: &int = &*t0; // Freezes `*t0` +//! let mut t2 = &mut t0; //~ ERROR cannot borrow `t0` +//! **t2 += 1; // Mutates `*t0` +//! } +//! ``` +//! +//! In this example, `**t2` is the same memory as `*t0`. Because `t2` is +//! an `&mut` pointer, `**t2` is a unique path and hence it would be +//! possible to mutate `**t2` even though that memory was supposed to be +//! frozen by the creation of `p`. However, an error is reported -- the +//! reason is that the freeze `&*t0` will restrict claims and mutation +//! against `*t0` which, by clause 2, in turn prevents claims and mutation +//! of `t0`. Hence the claim `&mut t0` is illegal. +//! +//! Another danger with an `&mut` pointer is that we could swap the `t0` +//! value away to create a new path: +//! +//! ``` +//! // src/test/compile-fail/borrowck-swap-mut-base-ptr.rs +//! fn foo<'a>(mut t0: &'a mut int, +//! mut t1: &'a mut int) { +//! let p: &int = &*t0; // Freezes `*t0` +//! swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0` +//! *t1 = 22; +//! } +//! ``` +//! +//! This is illegal for the same reason as above. Note that if we added +//! back a swap operator -- as we used to have -- we would want to be very +//! careful to ensure this example is still illegal. +//! +//! **Example danger 3: Freeze the base pointer.** In the case where the +//! referent is claimed, even freezing the base pointer can be dangerous, +//! as shown in the following example: +//! +//! ``` +//! // src/test/compile-fail/borrowck-borrow-of-mut-base-ptr.rs +//! fn foo<'a>(mut t0: &'a mut int, +//! mut t1: &'a mut int) { +//! let p: &mut int = &mut *t0; // Claims `*t0` +//! let mut t2 = &t0; //~ ERROR cannot borrow `t0` +//! let q: &int = &*t2; // Freezes `*t0` but not through `*p` +//! *p += 1; // violates type of `*q` +//! } +//! ``` +//! +//! Here the problem is that `*t0` is claimed by `p`, and hence `p` wants +//! to be the controlling pointer through which mutation or freezes occur. +//! But `t2` would -- if it were legal -- have the type `& &mut int`, and +//! hence would be a mutable pointer in an aliasable location, which is +//! considered frozen (since no one can write to `**t2` as it is not a +//! unique path). Therefore, we could reasonably create a frozen `&int` +//! pointer pointing at `*t0` that coexists with the mutable pointer `p`, +//! which is clearly unsound. +//! +//! However, it is not always unsafe to freeze the base pointer. In +//! particular, if the referent is frozen, there is no harm in it: +//! +//! ``` +//! // src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs +//! fn foo<'a>(mut t0: &'a mut int, +//! mut t1: &'a mut int) { +//! let p: &int = &*t0; // Freezes `*t0` +//! let mut t2 = &t0; +//! let q: &int = &*t2; // Freezes `*t0`, but that's ok... +//! let r: &int = &*t0; // ...after all, could do same thing directly. +//! } +//! ``` +//! +//! In this case, creating the alias `t2` of `t0` is safe because the only +//! thing `t2` can be used for is to further freeze `*t0`, which is +//! already frozen. In particular, we cannot assign to `*t0` through the +//! new alias `t2`, as demonstrated in this test case: +//! +//! ``` +//! // src/test/run-pass/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs +//! fn foo(t0: & &mut int) { +//! let t1 = t0; +//! let p: &int = &**t0; +//! **t1 = 22; //~ ERROR cannot assign +//! } +//! ``` +//! +//! This distinction is reflected in the rules. When doing an `&mut` +//! borrow -- as in the first example -- the set `ACTIONS` will be +//! `CLAIM|MUTATE|FREEZE`, because claiming the referent implies that it +//! cannot be claimed, mutated, or frozen by anyone else. These +//! restrictions are propagated back to the base path and hence the base +//! path is considered unfreezable. +//! +//! In contrast, when the referent is merely frozen -- as in the second +//! example -- the set `ACTIONS` will be `CLAIM|MUTATE`, because freezing +//! the referent implies that it cannot be claimed or mutated but permits +//! others to freeze. Hence when these restrictions are propagated back to +//! the base path, it will still be considered freezable. +//! +//! +//! +//! **FIXME #10520: Restrictions against mutating the base pointer.** When +//! an `&mut` pointer is frozen or claimed, we currently pass along the +//! restriction against MUTATE to the base pointer. I do not believe this +//! restriction is needed. It dates from the days when we had a way to +//! mutate that preserved the value being mutated (i.e., swap). Nowadays +//! the only form of mutation is assignment, which destroys the pointer +//! being mutated -- therefore, a mutation cannot create a new path to the +//! same data. Rather, it removes an existing path. This implies that not +//! only can we permit mutation, we can have mutation kill restrictions in +//! the dataflow sense. +//! +//! **WARNING:** We do not currently have `const` borrows in the +//! language. If they are added back in, we must ensure that they are +//! consistent with all of these examples. The crucial question will be +//! what sorts of actions are permitted with a `&const &mut` pointer. I +//! would suggest that an `&mut` referent found in an `&const` location be +//! prohibited from both freezes and claims. This would avoid the need to +//! prevent `const` borrows of the base pointer when the referent is +//! borrowed. +//! +//! # Moves and initialization +//! +//! The borrow checker is also in charge of ensuring that: +//! +//! - all memory which is accessed is initialized +//! - immutable local variables are assigned at most once. +//! +//! These are two separate dataflow analyses built on the same +//! framework. Let's look at checking that memory is initialized first; +//! the checking of immutable local variable assignments works in a very +//! similar way. +//! +//! To track the initialization of memory, we actually track all the +//! points in the program that *create uninitialized memory*, meaning +//! moves and the declaration of uninitialized variables. For each of +//! these points, we create a bit in the dataflow set. Assignments to a +//! variable `x` or path `a.b.c` kill the move/uninitialization bits for +//! those paths and any subpaths (e.g., `x`, `x.y`, `a.b.c`, `*a.b.c`). +//! Bits are unioned when two control-flow paths join. Thus, the +//! presence of a bit indicates that the move may have occurred without an +//! intervening assignment to the same memory. At each use of a variable, +//! we examine the bits in scope, and check that none of them are +//! moves/uninitializations of the variable that is being used. +//! +//! Let's look at a simple example: +//! +//! ``` +//! fn foo(a: Box) { +//! let b: Box; // Gen bit 0. +//! +//! if cond { // Bits: 0 +//! use(&*a); +//! b = a; // Gen bit 1, kill bit 0. +//! use(&*b); +//! } else { +//! // Bits: 0 +//! } +//! // Bits: 0,1 +//! use(&*a); // Error. +//! use(&*b); // Error. +//! } +//! +//! fn use(a: &int) { } +//! ``` +//! +//! In this example, the variable `b` is created uninitialized. In one +//! branch of an `if`, we then move the variable `a` into `b`. Once we +//! exit the `if`, therefore, it is an error to use `a` or `b` since both +//! are only conditionally initialized. I have annotated the dataflow +//! state using comments. There are two dataflow bits, with bit 0 +//! corresponding to the creation of `b` without an initializer, and bit 1 +//! corresponding to the move of `a`. The assignment `b = a` both +//! generates bit 1, because it is a move of `a`, and kills bit 0, because +//! `b` is now initialized. On the else branch, though, `b` is never +//! initialized, and so bit 0 remains untouched. When the two flows of +//! control join, we union the bits from both sides, resulting in both +//! bits 0 and 1 being set. Thus any attempt to use `a` uncovers the bit 1 +//! from the "then" branch, showing that `a` may be moved, and any attempt +//! to use `b` uncovers bit 0, from the "else" branch, showing that `b` +//! may not be initialized. +//! +//! ## Initialization of immutable variables +//! +//! Initialization of immutable variables works in a very similar way, +//! except that: +//! +//! 1. we generate bits for each assignment to a variable; +//! 2. the bits are never killed except when the variable goes out of scope. +//! +//! Thus the presence of an assignment bit indicates that the assignment +//! may have occurred. Note that assignments are only killed when the +//! variable goes out of scope, as it is not relevant whether or not there +//! has been a move in the meantime. Using these bits, we can declare that +//! an assignment to an immutable variable is legal iff there is no other +//! assignment bit to that same variable in scope. +//! +//! ## Why is the design made this way? +//! +//! It may seem surprising that we assign dataflow bits to *each move* +//! rather than *each path being moved*. This is somewhat less efficient, +//! since on each use, we must iterate through all moves and check whether +//! any of them correspond to the path in question. Similar concerns apply +//! to the analysis for double assignments to immutable variables. The +//! main reason to do it this way is that it allows us to print better +//! error messages, because when a use occurs, we can print out the +//! precise move that may be in scope, rather than simply having to say +//! "the variable may not be initialized". +//! +//! ## Data structures used in the move analysis +//! +//! The move analysis maintains several data structures that enable it to +//! cross-reference moves and assignments to determine when they may be +//! moving/assigning the same memory. These are all collected into the +//! `MoveData` and `FlowedMoveData` structs. The former represents the set +//! of move paths, moves, and assignments, and the latter adds in the +//! results of a dataflow computation. +//! +//! ### Move paths +//! +//! The `MovePath` tree tracks every path that is moved or assigned to. +//! These paths have the same form as the `LoanPath` data structure, which +//! in turn is the "real world version of the lvalues `LV` that we +//! introduced earlier. The difference between a `MovePath` and a `LoanPath` +//! is that move paths are: +//! +//! 1. Canonicalized, so that we have exactly one copy of each, and +//! we can refer to move paths by index; +//! 2. Cross-referenced with other paths into a tree, so that given a move +//! path we can efficiently find all parent move paths and all +//! extensions (e.g., given the `a.b` move path, we can easily find the +//! move path `a` and also the move paths `a.b.c`) +//! 3. Cross-referenced with moves and assignments, so that we can +//! easily find all moves and assignments to a given path. +//! +//! The mechanism that we use is to create a `MovePath` record for each +//! move path. These are arranged in an array and are referenced using +//! `MovePathIndex` values, which are newtype'd indices. The `MovePath` +//! structs are arranged into a tree, representing using the standard +//! Knuth representation where each node has a child 'pointer' and a "next +//! sibling" 'pointer'. In addition, each `MovePath` has a parent +//! 'pointer'. In this case, the 'pointers' are just `MovePathIndex` +//! values. +//! +//! In this way, if we want to find all base paths of a given move path, +//! we can just iterate up the parent pointers (see `each_base_path()` in +//! the `move_data` module). If we want to find all extensions, we can +//! iterate through the subtree (see `each_extending_path()`). +//! +//! ### Moves and assignments +//! +//! There are structs to represent moves (`Move`) and assignments +//! (`Assignment`), and these are also placed into arrays and referenced +//! by index. All moves of a particular path are arranged into a linked +//! lists, beginning with `MovePath.first_move` and continuing through +//! `Move.next_move`. +//! +//! We distinguish between "var" assignments, which are assignments to a +//! variable like `x = foo`, and "path" assignments (`x.f = foo`). This +//! is because we need to assign dataflows to the former, but not the +//! latter, so as to check for double initialization of immutable +//! variables. +//! +//! ### Gathering and checking moves +//! +//! Like loans, we distinguish two phases. The first, gathering, is where +//! we uncover all the moves and assignments. As with loans, we do some +//! basic sanity checking in this phase, so we'll report errors if you +//! attempt to move out of a borrowed pointer etc. Then we do the dataflow +//! (see `FlowedMoveData::new`). Finally, in the `check_loans.rs` code, we +//! walk back over, identify all uses, assignments, and captures, and +//! check that they are legal given the set of dataflow bits we have +//! computed for that program point. +//! +//! # Drop flags and structural fragments +//! +//! In addition to the job of enforcing memory safety, the borrow checker +//! code is also responsible for identifying the *structural fragments* of +//! data in the function, to support out-of-band dynamic drop flags +//! allocated on the stack. (For background, see [RFC PR #320].) +//! +//! [RFC PR #320]: https://github.com/rust-lang/rfcs/pull/320 +//! +//! Semantically, each piece of data that has a destructor may need a +//! boolean flag to indicate whether or not its destructor has been run +//! yet. However, in many cases there is no need to actually maintain such +//! a flag: It can be apparent from the code itself that a given path is +//! always initialized (or always deinitialized) when control reaches the +//! end of its owner's scope, and thus we can unconditionally emit (or +//! not) the destructor invocation for that path. +//! +//! A simple example of this is the following: +//! +//! ```rust +//! struct D { p: int } +//! impl D { fn new(x: int) -> D { ... } +//! impl Drop for D { ... } +//! +//! fn foo(a: D, b: D, t: || -> bool) { +//! let c: D; +//! let d: D; +//! if t() { c = b; } +//! } +//! ``` +//! +//! At the end of the body of `foo`, the compiler knows that `a` is +//! initialized, introducing a drop obligation (deallocating the boxed +//! integer) for the end of `a`'s scope that is run unconditionally. +//! Likewise the compiler knows that `d` is not initialized, and thus it +//! leave out the drop code for `d`. +//! +//! The compiler cannot statically know the drop-state of `b` nor `c` at +//! the end of their scope, since that depends on the value of +//! `t`. Therefore, we need to insert boolean flags to track whether we +//! need to drop `b` and `c`. +//! +//! However, the matter is not as simple as just mapping local variables +//! to their corresponding drop flags when necessary. In particular, in +//! addition to being able to move data out of local variables, Rust +//! allows one to move values in and out of structured data. +//! +//! Consider the following: +//! +//! ```rust +//! struct S { x: D, y: D, z: D } +//! +//! fn foo(a: S, mut b: S, t: || -> bool) { +//! let mut c: S; +//! let d: S; +//! let e: S = a.clone(); +//! if t() { +//! c = b; +//! b.x = e.y; +//! } +//! if t() { c.y = D::new(4); } +//! } +//! ``` +//! +//! As before, the drop obligations of `a` and `d` can be statically +//! determined, and again the state of `b` and `c` depend on dynamic +//! state. But additionally, the dynamic drop obligations introduced by +//! `b` and `c` are not just per-local boolean flags. For example, if the +//! first call to `t` returns `false` and the second call `true`, then at +//! the end of their scope, `b` will be completely initialized, but only +//! `c.y` in `c` will be initialized. If both calls to `t` return `true`, +//! then at the end of their scope, `c` will be completely initialized, +//! but only `b.x` will be initialized in `b`, and only `e.x` and `e.z` +//! will be initialized in `e`. +//! +//! Note that we need to cover the `z` field in each case in some way, +//! since it may (or may not) need to be dropped, even though `z` is never +//! directly mentioned in the body of the `foo` function. We call a path +//! like `b.z` a *fragment sibling* of `b.x`, since the field `z` comes +//! from the same structure `S` that declared the field `x` in `b.x`. +//! +//! In general we need to maintain boolean flags that match the +//! `S`-structure of both `b` and `c`. In addition, we need to consult +//! such a flag when doing an assignment (such as `c.y = D::new(4);` +//! above), in order to know whether or not there is a previous value that +//! needs to be dropped before we do the assignment. +//! +//! So for any given function, we need to determine what flags are needed +//! to track its drop obligations. Our strategy for determining the set of +//! flags is to represent the fragmentation of the structure explicitly: +//! by starting initially from the paths that are explicitly mentioned in +//! moves and assignments (such as `b.x` and `c.y` above), and then +//! traversing the structure of the path's type to identify leftover +//! *unmoved fragments*: assigning into `c.y` means that `c.x` and `c.z` +//! are leftover unmoved fragments. Each fragment represents a drop +//! obligation that may need to be tracked. Paths that are only moved or +//! assigned in their entirety (like `a` and `d`) are treated as a single +//! drop obligation. +//! +//! The fragment construction process works by piggy-backing on the +//! existing `move_data` module. We already have callbacks that visit each +//! direct move and assignment; these form the basis for the sets of +//! moved_leaf_paths and assigned_leaf_paths. From these leaves, we can +//! walk up their parent chain to identify all of their parent paths. +//! We need to identify the parents because of cases like the following: +//! +//! ```rust +//! struct Pair{ x: X, y: Y } +//! fn foo(dd_d_d: Pair, D>, D>) { +//! other_function(dd_d_d.x.y); +//! } +//! ``` +//! +//! In this code, the move of the path `dd_d.x.y` leaves behind not only +//! the fragment drop-obligation `dd_d.x.x` but also `dd_d.y` as well. +//! +//! Once we have identified the directly-referenced leaves and their +//! parents, we compute the left-over fragments, in the function +//! `fragments::add_fragment_siblings`. As of this writing this works by +//! looking at each directly-moved or assigned path P, and blindly +//! gathering all sibling fields of P (as well as siblings for the parents +//! of P, etc). After accumulating all such siblings, we filter out the +//! entries added as siblings of P that turned out to be +//! directly-referenced paths (or parents of directly referenced paths) +//! themselves, thus leaving the never-referenced "left-overs" as the only +//! thing left from the gathering step. +//! +//! ## Array structural fragments +//! +//! A special case of the structural fragments discussed above are +//! the elements of an array that has been passed by value, such as +//! the following: +//! +//! ```rust +//! fn foo(a: [D, ..10], i: uint) -> D { +//! a[i] +//! } +//! ``` +//! +//! The above code moves a single element out of the input array `a`. +//! The remainder of the array still needs to be dropped; i.e., it +//! is a structural fragment. Note that after performing such a move, +//! it is not legal to read from the array `a`. There are a number of +//! ways to deal with this, but the important thing to note is that +//! the semantics needs to distinguish in some manner between a +//! fragment that is the *entire* array versus a fragment that represents +//! all-but-one element of the array. A place where that distinction +//! would arise is the following: +//! +//! ```rust +//! fn foo(a: [D, ..10], b: [D, ..10], i: uint, t: bool) -> D { +//! if t { +//! a[i] +//! } else { +//! b[i] +//! } +//! +//! // When control exits, we will need either to drop all of `a` +//! // and all-but-one of `b`, or to drop all of `b` and all-but-one +//! // of `a`. +//! } +//! ``` +//! +//! There are a number of ways that the trans backend could choose to +//! compile this (e.g. a `[bool, ..10]` array for each such moved array; +//! or an `Option` for each moved array). From the viewpoint of the +//! borrow-checker, the important thing is to record what kind of fragment +//! is implied by the relevant moves. +//! +//! # Future work +//! +//! While writing up these docs, I encountered some rules I believe to be +//! stricter than necessary: +//! +//! - I think restricting the `&mut` LV against moves and `ALIAS` is sufficient, +//! `MUTATE` and `CLAIM` are overkill. `MUTATE` was necessary when swap was +//! a built-in operator, but as it is not, it is implied by `CLAIM`, +//! and `CLAIM` is implied by `ALIAS`. The only net effect of this is an +//! extra error message in some cases, though. +//! - I have not described how closures interact. Current code is unsound. +//! I am working on describing and implementing the fix. +//! - If we wish, we can easily extend the move checking to allow finer-grained +//! tracking of what is initialized and what is not, enabling code like +//! this: +//! +//! a = x.f.g; // x.f.g is now uninitialized +//! // here, x and x.f are not usable, but x.f.h *is* +//! x.f.g = b; // x.f.g is not initialized +//! // now x, x.f, x.f.g, x.f.h are all usable +//! +//! What needs to change here, most likely, is that the `moves` module +//! should record not only what paths are moved, but what expressions +//! are actual *uses*. For example, the reference to `x` in `x.f.g = b` +//! is not a true *use* in the sense that it requires `x` to be fully +//! initialized. This is in fact why the above code produces an error +//! today: the reference to `x` in `x.f.g = b` is considered illegal +//! because `x` is not fully initialized. +//! +//! There are also some possible refactorings: +//! +//! - It might be nice to replace all loan paths with the MovePath mechanism, +//! since they allow lightweight comparison using an integer. diff --git a/src/librustc/middle/borrowck/fragments.rs b/src/librustc/middle/borrowck/fragments.rs index 7e766e9138e..dddc326df35 100644 --- a/src/librustc/middle/borrowck/fragments.rs +++ b/src/librustc/middle/borrowck/fragments.rs @@ -8,13 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! +//! Helper routines used for fragmenting structural paths due to moves for +//! tracking drop obligations. Please see the extensive comments in the +//! section "Structural fragments" in `doc.rs`. -Helper routines used for fragmenting structural paths due to moves for -tracking drop obligations. Please see the extensive comments in the -section "Structural fragments" in `doc.rs`. - -*/ use self::Fragment::*; use session::config; @@ -176,16 +173,12 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>, instrument_all_paths("assigned_leaf_path", &fragments.assigned_leaf_paths); } +/// Normalizes the fragment sets in `this`; i.e., removes duplicate entries, constructs the set of +/// parents, and constructs the left-over fragments. +/// +/// Note: "left-over fragments" means paths that were not directly referenced in moves nor +/// assignments, but must nonetheless be tracked as potential drop obligations. pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { - /*! - * Normalizes the fragment sets in `this`; i.e., removes - * duplicate entries, constructs the set of parents, and - * constructs the left-over fragments. - * - * Note: "left-over fragments" means paths that were not - * directly referenced in moves nor assignments, but must - * nonetheless be tracked as potential drop obligations. - */ let mut fragments = this.fragments.borrow_mut(); @@ -283,18 +276,14 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { } } +/// Adds all of the precisely-tracked siblings of `lp` as potential move paths of interest. For +/// example, if `lp` represents `s.x.j`, then adds moves paths for `s.x.i` and `s.x.k`, the +/// siblings of `s.x.j`. fn add_fragment_siblings<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>, gathered_fragments: &mut Vec, lp: Rc>, origin_id: Option) { - /*! - * Adds all of the precisely-tracked siblings of `lp` as - * potential move paths of interest. For example, if `lp` - * represents `s.x.j`, then adds moves paths for `s.x.i` and - * `s.x.k`, the siblings of `s.x.j`. - */ - match lp.kind { LpVar(_) | LpUpvar(..) => {} // Local variables have no siblings. @@ -343,6 +332,8 @@ fn add_fragment_siblings<'tcx>(this: &MoveData<'tcx>, } } +/// We have determined that `origin_lp` destructures to LpExtend(parent, original_field_name). +/// Based on this, add move paths for all of the siblings of `origin_lp`. fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>, gathered_fragments: &mut Vec, @@ -353,12 +344,6 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>, origin_id: Option, enum_variant_info: Option<(ast::DefId, Rc>)>) { - /*! - * We have determined that `origin_lp` destructures to - * LpExtend(parent, original_field_name). Based on this, - * add move paths for all of the siblings of `origin_lp`. - */ - let parent_ty = parent_lp.to_type(); let add_fragment_sibling_local = |field_name| { @@ -454,6 +439,8 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>, } } +/// Adds the single sibling `LpExtend(parent, new_field_name)` of `origin_lp` (the original +/// loan-path). fn add_fragment_sibling_core<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>, gathered_fragments: &mut Vec, @@ -461,10 +448,6 @@ fn add_fragment_sibling_core<'tcx>(this: &MoveData<'tcx>, mc: mc::MutabilityCategory, new_field_name: mc::FieldName, origin_lp: &Rc>) -> MovePathIndex { - /*! - * Adds the single sibling `LpExtend(parent, new_field_name)` - * of `origin_lp` (the original loan-path). - */ let opt_variant_did = match parent.kind { LpDowncast(_, variant_did) => Some(variant_did), LpVar(..) | LpUpvar(..) | LpExtend(..) => None, diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 1d0b0558bb1..65114160504 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Computes moves. - */ +//! Computes moves. use middle::borrowck::*; use middle::borrowck::LoanPathKind::*; diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index 7a7ed3e75d2..e6a7c150df8 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * This module implements the check that the lifetime of a borrow - * does not exceed the lifetime of the value being borrowed. - */ +//! This module implements the check that the lifetime of a borrow +//! does not exceed the lifetime of the value being borrowed. use middle::borrowck::*; use middle::expr_use_visitor as euv; diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 088b62a12cf..4f7ecc99c89 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -225,6 +225,9 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.bccx.tcx } + /// Guarantees that `addr_of(cmt)` will be valid for the duration of `static_scope_r`, or + /// reports an error. This may entail taking out loans, which will be added to the + /// `req_loan_map`. fn guarantee_valid(&mut self, borrow_id: ast::NodeId, borrow_span: Span, @@ -232,12 +235,6 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { req_kind: ty::BorrowKind, loan_region: ty::Region, cause: euv::LoanCause) { - /*! - * Guarantees that `addr_of(cmt)` will be valid for the duration of - * `static_scope_r`, or reports an error. This may entail taking - * out loans, which will be added to the `req_loan_map`. - */ - debug!("guarantee_valid(borrow_id={}, cmt={}, \ req_mutbl={}, loan_region={})", borrow_id, diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index adae34b49dc..bd9cf8f84b6 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Computes the restrictions that result from a borrow. - */ +//! Computes the restrictions that result from a borrow. pub use self::RestrictionResult::*; diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 45040cd7b10..0bbcdfe61bb 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! See doc.rs for a thorough explanation of the borrow checker */ +//! See doc.rs for a thorough explanation of the borrow checker #![allow(non_camel_case_types)] diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index dc9516ccc5d..7bf3458f0ae 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -8,12 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Data structures used for tracking moves. Please see the extensive -comments in the section "Moves and initialization" in `doc.rs`. - -*/ +//! Data structures used for tracking moves. Please see the extensive +//! comments in the section "Moves and initialization" in `doc.rs`. pub use self::MoveKind::*; @@ -297,15 +293,11 @@ impl<'tcx> MoveData<'tcx> { self.path_parent(index) == InvalidMovePathIndex } + /// Returns the existing move path index for `lp`, if any, and otherwise adds a new index for + /// `lp` and any of its base paths that do not yet have an index. pub fn move_path(&self, tcx: &ty::ctxt<'tcx>, lp: Rc>) -> MovePathIndex { - /*! - * Returns the existing move path index for `lp`, if any, - * and otherwise adds a new index for `lp` and any of its - * base paths that do not yet have an index. - */ - match self.path_map.borrow().get(&lp) { Some(&index) => { return index; @@ -370,13 +362,10 @@ impl<'tcx> MoveData<'tcx> { result } + /// Adds any existing move path indices for `lp` and any base paths of `lp` to `result`, but + /// does not add new move paths fn add_existing_base_paths(&self, lp: &Rc>, result: &mut Vec) { - /*! - * Adds any existing move path indices for `lp` and any base - * paths of `lp` to `result`, but does not add new move paths - */ - match self.path_map.borrow().get(lp).cloned() { Some(index) => { self.each_base_path(index, |p| { @@ -397,16 +386,12 @@ impl<'tcx> MoveData<'tcx> { } + /// Adds a new move entry for a move of `lp` that occurs at location `id` with kind `kind`. pub fn add_move(&self, tcx: &ty::ctxt<'tcx>, lp: Rc>, id: ast::NodeId, kind: MoveKind) { - /*! - * Adds a new move entry for a move of `lp` that occurs at - * location `id` with kind `kind`. - */ - debug!("add_move(lp={}, id={}, kind={})", lp.repr(tcx), id, @@ -428,6 +413,8 @@ impl<'tcx> MoveData<'tcx> { }); } + /// Adds a new record for an assignment to `lp` that occurs at location `id` with the given + /// `span`. pub fn add_assignment(&self, tcx: &ty::ctxt<'tcx>, lp: Rc>, @@ -435,11 +422,6 @@ impl<'tcx> MoveData<'tcx> { span: Span, assignee_id: ast::NodeId, mode: euv::MutateMode) { - /*! - * Adds a new record for an assignment to `lp` that occurs at - * location `id` with the given `span`. - */ - debug!("add_assignment(lp={}, assign_id={}, assignee_id={}", lp.repr(tcx), assign_id, assignee_id); @@ -473,18 +455,16 @@ impl<'tcx> MoveData<'tcx> { } } + /// Adds a new record for a match of `base_lp`, downcast to + /// variant `lp`, that occurs at location `pattern_id`. (One + /// should be able to recover the span info from the + /// `pattern_id` and the ast_map, I think.) pub fn add_variant_match(&self, tcx: &ty::ctxt<'tcx>, lp: Rc>, pattern_id: ast::NodeId, base_lp: Rc>, mode: euv::MatchMode) { - /*! - * Adds a new record for a match of `base_lp`, downcast to - * variant `lp`, that occurs at location `pattern_id`. (One - * should be able to recover the span info from the - * `pattern_id` and the ast_map, I think.) - */ debug!("add_variant_match(lp={}, pattern_id={})", lp.repr(tcx), pattern_id); @@ -507,18 +487,15 @@ impl<'tcx> MoveData<'tcx> { fragments::fixup_fragment_sets(self, tcx) } + /// Adds the gen/kills for the various moves and + /// assignments into the provided data flow contexts. + /// Moves are generated by moves and killed by assignments and + /// scoping. Assignments are generated by assignment to variables and + /// killed by scoping. See `doc.rs` for more details. fn add_gen_kills(&self, tcx: &ty::ctxt<'tcx>, dfcx_moves: &mut MoveDataFlow, dfcx_assign: &mut AssignDataFlow) { - /*! - * Adds the gen/kills for the various moves and - * assignments into the provided data flow contexts. - * Moves are generated by moves and killed by assignments and - * scoping. Assignments are generated by assignment to variables and - * killed by scoping. See `doc.rs` for more details. - */ - for (i, the_move) in self.moves.borrow().iter().enumerate() { dfcx_moves.add_gen(the_move.id, i); } @@ -695,18 +672,14 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { ret } + /// Iterates through each move of `loan_path` (or some base path of `loan_path`) that *may* + /// have occurred on entry to `id` without an intervening assignment. In other words, any moves + /// that would invalidate a reference to `loan_path` at location `id`. pub fn each_move_of(&self, id: ast::NodeId, loan_path: &Rc>, f: |&Move, &LoanPath<'tcx>| -> bool) -> bool { - /*! - * Iterates through each move of `loan_path` (or some base path - * of `loan_path`) that *may* have occurred on entry to `id` without - * an intervening assignment. In other words, any moves that - * would invalidate a reference to `loan_path` at location `id`. - */ - // Bad scenarios: // // 1. Move of `a.b.c`, use of `a.b.c` @@ -755,17 +728,13 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { }) } + /// Iterates through every assignment to `loan_path` that may have occurred on entry to `id`. + /// `loan_path` must be a single variable. pub fn each_assignment_of(&self, id: ast::NodeId, loan_path: &Rc>, f: |&Assignment| -> bool) -> bool { - /*! - * Iterates through every assignment to `loan_path` that - * may have occurred on entry to `id`. `loan_path` must be - * a single variable. - */ - let loan_path_index = { match self.move_data.existing_move_path(loan_path) { Some(i) => i, diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs index bb758ec7c38..a2e8ba8d65c 100644 --- a/src/librustc/middle/cfg/mod.rs +++ b/src/librustc/middle/cfg/mod.rs @@ -8,12 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Module that constructs a control-flow graph representing an item. -Uses `Graph` as the underlying representation. - -*/ +//! Module that constructs a control-flow graph representing an item. +//! Uses `Graph` as the underlying representation. use middle::graph; use middle::ty; diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 141504cb6f7..53fea8ffc86 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -9,12 +9,10 @@ // except according to those terms. -/*! - * A module for propagating forward dataflow information. The analysis - * assumes that the items to be propagated can be represented as bits - * and thus uses bitvectors. Your job is simply to specify the so-called - * GEN and KILL bits for each expression. - */ +//! A module for propagating forward dataflow information. The analysis +//! assumes that the items to be propagated can be represented as bits +//! and thus uses bitvectors. Your job is simply to specify the so-called +//! GEN and KILL bits for each expression. pub use self::EntryOrExit::*; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 656feb51a1d..9bb5a6f9a24 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * A different sort of visitor for walking fn bodies. Unlike the - * normal visitor, which just walks the entire body in one shot, the - * `ExprUseVisitor` determines how expressions are being used. - */ +//! A different sort of visitor for walking fn bodies. Unlike the +//! normal visitor, which just walks the entire body in one shot, the +//! `ExprUseVisitor` determines how expressions are being used. pub use self::MutateMode::*; pub use self::LoanCause::*; @@ -716,12 +714,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } } + /// Indicates that the value of `blk` will be consumed, meaning either copied or moved + /// depending on its type. fn walk_block(&mut self, blk: &ast::Block) { - /*! - * Indicates that the value of `blk` will be consumed, - * meaning either copied or moved depending on its type. - */ - debug!("walk_block(blk.id={})", blk.id); for stmt in blk.stmts.iter() { @@ -821,16 +816,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } } + /// Autoderefs for overloaded Deref calls in fact reference their receiver. That is, if we have + /// `(*x)` where `x` is of type `Rc`, then this in fact is equivalent to `x.deref()`. Since + /// `deref()` is declared with `&self`, this is an autoref of `x`. fn walk_autoderefs(&mut self, expr: &ast::Expr, autoderefs: uint) { - /*! - * Autoderefs for overloaded Deref calls in fact reference - * their receiver. That is, if we have `(*x)` where `x` is of - * type `Rc`, then this in fact is equivalent to - * `x.deref()`. Since `deref()` is declared with `&self`, this - * is an autoref of `x`. - */ debug!("walk_autoderefs expr={} autoderefs={}", expr.repr(self.tcx()), autoderefs); for i in range(0, autoderefs) { diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs index 7514a63c7fa..da467c3d0d5 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -33,26 +33,20 @@ pub enum SimplifiedType { ParameterSimplifiedType, } +/// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc. +/// The idea is to get something simple that we can use to quickly decide if two types could unify +/// during method lookup. +/// +/// If `can_simplify_params` is false, then we will fail to simplify type parameters entirely. This +/// is useful when those type parameters would be instantiated with fresh type variables, since +/// then we can't say much about whether two types would unify. Put another way, +/// `can_simplify_params` should be true if type parameters appear free in `ty` and `false` if they +/// are to be considered bound. pub fn simplify_type(tcx: &ty::ctxt, ty: Ty, can_simplify_params: bool) -> Option { - /*! - * Tries to simplify a type by dropping type parameters, deref'ing - * away any reference types, etc. The idea is to get something - * simple that we can use to quickly decide if two types could - * unify during method lookup. - * - * If `can_simplify_params` is false, then we will fail to - * simplify type parameters entirely. This is useful when those - * type parameters would be instantiated with fresh type - * variables, since then we can't say much about whether two types - * would unify. Put another way, `can_simplify_params` should be - * true if type parameters appear free in `ty` and `false` if they - * are to be considered bound. - */ - match ty.sty { ty::ty_bool => Some(BoolSimplifiedType), ty::ty_char => Some(CharSimplifiedType), diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs index ac132477b87..2f50a964023 100644 --- a/src/librustc/middle/graph.rs +++ b/src/librustc/middle/graph.rs @@ -8,31 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -A graph module for use in dataflow, region resolution, and elsewhere. - -# Interface details - -You customize the graph by specifying a "node data" type `N` and an -"edge data" type `E`. You can then later gain access (mutable or -immutable) to these "user-data" bits. Currently, you can only add -nodes or edges to the graph. You cannot remove or modify them once -added. This could be changed if we have a need. - -# Implementation details - -The main tricky thing about this code is the way that edges are -stored. The edges are stored in a central array, but they are also -threaded onto two linked lists for each node, one for incoming edges -and one for outgoing edges. Note that every edge is a member of some -incoming list and some outgoing list. Basically you can load the -first index of the linked list from the node data structures (the -field `first_edge`) and then, for each edge, load the next index from -the field `next_edge`). Each of those fields is an array that should -be indexed by the direction (see the type `Direction`). - -*/ +//! A graph module for use in dataflow, region resolution, and elsewhere. +//! +//! # Interface details +//! +//! You customize the graph by specifying a "node data" type `N` and an +//! "edge data" type `E`. You can then later gain access (mutable or +//! immutable) to these "user-data" bits. Currently, you can only add +//! nodes or edges to the graph. You cannot remove or modify them once +//! added. This could be changed if we have a need. +//! +//! # Implementation details +//! +//! The main tricky thing about this code is the way that edges are +//! stored. The edges are stored in a central array, but they are also +//! threaded onto two linked lists for each node, one for incoming edges +//! and one for outgoing edges. Note that every edge is a member of some +//! incoming list and some outgoing list. Basically you can load the +//! first index of the linked list from the node data structures (the +//! field `first_edge`) and then, for each edge, load the next index from +//! the field `next_edge`). Each of those fields is an array that should +//! be indexed by the direction (see the type `Direction`). #![allow(dead_code)] // still WIP diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 15d9e87a9d5..a09ceac11a5 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -8,105 +8,103 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * A classic liveness analysis based on dataflow over the AST. Computes, - * for each local variable in a function, whether that variable is live - * at a given point. Program execution points are identified by their - * id. - * - * # Basic idea - * - * The basic model is that each local variable is assigned an index. We - * represent sets of local variables using a vector indexed by this - * index. The value in the vector is either 0, indicating the variable - * is dead, or the id of an expression that uses the variable. - * - * We conceptually walk over the AST in reverse execution order. If we - * find a use of a variable, we add it to the set of live variables. If - * we find an assignment to a variable, we remove it from the set of live - * variables. When we have to merge two flows, we take the union of - * those two flows---if the variable is live on both paths, we simply - * pick one id. In the event of loops, we continue doing this until a - * fixed point is reached. - * - * ## Checking initialization - * - * At the function entry point, all variables must be dead. If this is - * not the case, we can report an error using the id found in the set of - * live variables, which identifies a use of the variable which is not - * dominated by an assignment. - * - * ## Checking moves - * - * After each explicit move, the variable must be dead. - * - * ## Computing last uses - * - * Any use of the variable where the variable is dead afterwards is a - * last use. - * - * # Implementation details - * - * The actual implementation contains two (nested) walks over the AST. - * The outer walk has the job of building up the ir_maps instance for the - * enclosing function. On the way down the tree, it identifies those AST - * nodes and variable IDs that will be needed for the liveness analysis - * and assigns them contiguous IDs. The liveness id for an AST node is - * called a `live_node` (it's a newtype'd uint) and the id for a variable - * is called a `variable` (another newtype'd uint). - * - * On the way back up the tree, as we are about to exit from a function - * declaration we allocate a `liveness` instance. Now that we know - * precisely how many nodes and variables we need, we can allocate all - * the various arrays that we will need to precisely the right size. We then - * perform the actual propagation on the `liveness` instance. - * - * This propagation is encoded in the various `propagate_through_*()` - * methods. It effectively does a reverse walk of the AST; whenever we - * reach a loop node, we iterate until a fixed point is reached. - * - * ## The `Users` struct - * - * At each live node `N`, we track three pieces of information for each - * variable `V` (these are encapsulated in the `Users` struct): - * - * - `reader`: the `LiveNode` ID of some node which will read the value - * that `V` holds on entry to `N`. Formally: a node `M` such - * that there exists a path `P` from `N` to `M` where `P` does not - * write `V`. If the `reader` is `invalid_node()`, then the current - * value will never be read (the variable is dead, essentially). - * - * - `writer`: the `LiveNode` ID of some node which will write the - * variable `V` and which is reachable from `N`. Formally: a node `M` - * such that there exists a path `P` from `N` to `M` and `M` writes - * `V`. If the `writer` is `invalid_node()`, then there is no writer - * of `V` that follows `N`. - * - * - `used`: a boolean value indicating whether `V` is *used*. We - * distinguish a *read* from a *use* in that a *use* is some read that - * is not just used to generate a new value. For example, `x += 1` is - * a read but not a use. This is used to generate better warnings. - * - * ## Special Variables - * - * We generate various special variables for various, well, special purposes. - * These are described in the `specials` struct: - * - * - `exit_ln`: a live node that is generated to represent every 'exit' from - * the function, whether it be by explicit return, panic, or other means. - * - * - `fallthrough_ln`: a live node that represents a fallthrough - * - * - `no_ret_var`: a synthetic variable that is only 'read' from, the - * fallthrough node. This allows us to detect functions where we fail - * to return explicitly. - * - `clean_exit_var`: a synthetic variable that is only 'read' from the - * fallthrough node. It is only live if the function could converge - * via means other than an explicit `return` expression. That is, it is - * only dead if the end of the function's block can never be reached. - * It is the responsibility of typeck to ensure that there are no - * `return` expressions in a function declared as diverging. - */ +//! A classic liveness analysis based on dataflow over the AST. Computes, +//! for each local variable in a function, whether that variable is live +//! at a given point. Program execution points are identified by their +//! id. +//! +//! # Basic idea +//! +//! The basic model is that each local variable is assigned an index. We +//! represent sets of local variables using a vector indexed by this +//! index. The value in the vector is either 0, indicating the variable +//! is dead, or the id of an expression that uses the variable. +//! +//! We conceptually walk over the AST in reverse execution order. If we +//! find a use of a variable, we add it to the set of live variables. If +//! we find an assignment to a variable, we remove it from the set of live +//! variables. When we have to merge two flows, we take the union of +//! those two flows---if the variable is live on both paths, we simply +//! pick one id. In the event of loops, we continue doing this until a +//! fixed point is reached. +//! +//! ## Checking initialization +//! +//! At the function entry point, all variables must be dead. If this is +//! not the case, we can report an error using the id found in the set of +//! live variables, which identifies a use of the variable which is not +//! dominated by an assignment. +//! +//! ## Checking moves +//! +//! After each explicit move, the variable must be dead. +//! +//! ## Computing last uses +//! +//! Any use of the variable where the variable is dead afterwards is a +//! last use. +//! +//! # Implementation details +//! +//! The actual implementation contains two (nested) walks over the AST. +//! The outer walk has the job of building up the ir_maps instance for the +//! enclosing function. On the way down the tree, it identifies those AST +//! nodes and variable IDs that will be needed for the liveness analysis +//! and assigns them contiguous IDs. The liveness id for an AST node is +//! called a `live_node` (it's a newtype'd uint) and the id for a variable +//! is called a `variable` (another newtype'd uint). +//! +//! On the way back up the tree, as we are about to exit from a function +//! declaration we allocate a `liveness` instance. Now that we know +//! precisely how many nodes and variables we need, we can allocate all +//! the various arrays that we will need to precisely the right size. We then +//! perform the actual propagation on the `liveness` instance. +//! +//! This propagation is encoded in the various `propagate_through_*()` +//! methods. It effectively does a reverse walk of the AST; whenever we +//! reach a loop node, we iterate until a fixed point is reached. +//! +//! ## The `Users` struct +//! +//! At each live node `N`, we track three pieces of information for each +//! variable `V` (these are encapsulated in the `Users` struct): +//! +//! - `reader`: the `LiveNode` ID of some node which will read the value +//! that `V` holds on entry to `N`. Formally: a node `M` such +//! that there exists a path `P` from `N` to `M` where `P` does not +//! write `V`. If the `reader` is `invalid_node()`, then the current +//! value will never be read (the variable is dead, essentially). +//! +//! - `writer`: the `LiveNode` ID of some node which will write the +//! variable `V` and which is reachable from `N`. Formally: a node `M` +//! such that there exists a path `P` from `N` to `M` and `M` writes +//! `V`. If the `writer` is `invalid_node()`, then there is no writer +//! of `V` that follows `N`. +//! +//! - `used`: a boolean value indicating whether `V` is *used*. We +//! distinguish a *read* from a *use* in that a *use* is some read that +//! is not just used to generate a new value. For example, `x += 1` is +//! a read but not a use. This is used to generate better warnings. +//! +//! ## Special Variables +//! +//! We generate various special variables for various, well, special purposes. +//! These are described in the `specials` struct: +//! +//! - `exit_ln`: a live node that is generated to represent every 'exit' from +//! the function, whether it be by explicit return, panic, or other means. +//! +//! - `fallthrough_ln`: a live node that represents a fallthrough +//! +//! - `no_ret_var`: a synthetic variable that is only 'read' from, the +//! fallthrough node. This allows us to detect functions where we fail +//! to return explicitly. +//! - `clean_exit_var`: a synthetic variable that is only 'read' from the +//! fallthrough node. It is only live if the function could converge +//! via means other than an explicit `return` expression. That is, it is +//! only dead if the end of the function's block can never be reached. +//! It is the responsibility of typeck to ensure that there are no +//! `return` expressions in a function declared as diverging. use self::LoopKind::*; use self::LiveNodeKind::*; use self::VarKind::*; diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 046ab162cfc..53a5ac7a093 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -8,57 +8,55 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * # Categorization - * - * The job of the categorization module is to analyze an expression to - * determine what kind of memory is used in evaluating it (for example, - * where dereferences occur and what kind of pointer is dereferenced; - * whether the memory is mutable; etc) - * - * Categorization effectively transforms all of our expressions into - * expressions of the following forms (the actual enum has many more - * possibilities, naturally, but they are all variants of these base - * forms): - * - * E = rvalue // some computed rvalue - * | x // address of a local variable or argument - * | *E // deref of a ptr - * | E.comp // access to an interior component - * - * Imagine a routine ToAddr(Expr) that evaluates an expression and returns an - * address where the result is to be found. If Expr is an lvalue, then this - * is the address of the lvalue. If Expr is an rvalue, this is the address of - * some temporary spot in memory where the result is stored. - * - * Now, cat_expr() classifies the expression Expr and the address A=ToAddr(Expr) - * as follows: - * - * - cat: what kind of expression was this? This is a subset of the - * full expression forms which only includes those that we care about - * for the purpose of the analysis. - * - mutbl: mutability of the address A - * - ty: the type of data found at the address A - * - * The resulting categorization tree differs somewhat from the expressions - * themselves. For example, auto-derefs are explicit. Also, an index a[b] is - * decomposed into two operations: a dereference to reach the array data and - * then an index to jump forward to the relevant item. - * - * ## By-reference upvars - * - * One part of the translation which may be non-obvious is that we translate - * closure upvars into the dereference of a borrowed pointer; this more closely - * resembles the runtime translation. So, for example, if we had: - * - * let mut x = 3; - * let y = 5; - * let inc = || x += y; - * - * Then when we categorize `x` (*within* the closure) we would yield a - * result of `*x'`, effectively, where `x'` is a `cat_upvar` reference - * tied to `x`. The type of `x'` will be a borrowed pointer. - */ +//! # Categorization +//! +//! The job of the categorization module is to analyze an expression to +//! determine what kind of memory is used in evaluating it (for example, +//! where dereferences occur and what kind of pointer is dereferenced; +//! whether the memory is mutable; etc) +//! +//! Categorization effectively transforms all of our expressions into +//! expressions of the following forms (the actual enum has many more +//! possibilities, naturally, but they are all variants of these base +//! forms): +//! +//! E = rvalue // some computed rvalue +//! | x // address of a local variable or argument +//! | *E // deref of a ptr +//! | E.comp // access to an interior component +//! +//! Imagine a routine ToAddr(Expr) that evaluates an expression and returns an +//! address where the result is to be found. If Expr is an lvalue, then this +//! is the address of the lvalue. If Expr is an rvalue, this is the address of +//! some temporary spot in memory where the result is stored. +//! +//! Now, cat_expr() classifies the expression Expr and the address A=ToAddr(Expr) +//! as follows: +//! +//! - cat: what kind of expression was this? This is a subset of the +//! full expression forms which only includes those that we care about +//! for the purpose of the analysis. +//! - mutbl: mutability of the address A +//! - ty: the type of data found at the address A +//! +//! The resulting categorization tree differs somewhat from the expressions +//! themselves. For example, auto-derefs are explicit. Also, an index a[b] is +//! decomposed into two operations: a dereference to reach the array data and +//! then an index to jump forward to the relevant item. +//! +//! ## By-reference upvars +//! +//! One part of the translation which may be non-obvious is that we translate +//! closure upvars into the dereference of a borrowed pointer; this more closely +//! resembles the runtime translation. So, for example, if we had: +//! +//! let mut x = 3; +//! let y = 5; +//! let inc = || x += y; +//! +//! Then when we categorize `x` (*within* the closure) we would yield a +//! result of `*x'`, effectively, where `x'` is a `cat_upvar` reference +//! tied to `x`. The type of `x'` will be a borrowed pointer. #![allow(non_camel_case_types)] @@ -1058,20 +1056,17 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } + /// Given a pattern P like: `[_, ..Q, _]`, where `vec_cmt` is the cmt for `P`, `slice_pat` is + /// the pattern `Q`, returns: + /// + /// * a cmt for `Q` + /// * the mutability and region of the slice `Q` + /// + /// These last two bits of info happen to be things that borrowck needs. pub fn cat_slice_pattern(&self, vec_cmt: cmt<'tcx>, slice_pat: &ast::Pat) -> McResult<(cmt<'tcx>, ast::Mutability, ty::Region)> { - /*! - * Given a pattern P like: `[_, ..Q, _]`, where `vec_cmt` is - * the cmt for `P`, `slice_pat` is the pattern `Q`, returns: - * - a cmt for `Q` - * - the mutability and region of the slice `Q` - * - * These last two bits of info happen to be things that - * borrowck needs. - */ - let slice_ty = if_ok!(self.node_ty(slice_pat.id)); let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(), slice_pat, @@ -1079,17 +1074,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { let cmt_slice = self.cat_index(slice_pat, self.deref_vec(slice_pat, vec_cmt)); return Ok((cmt_slice, slice_mutbl, slice_r)); + /// In a pattern like [a, b, ..c], normally `c` has slice type, but if you have [a, b, + /// ..ref c], then the type of `ref c` will be `&&[]`, so to extract the slice details we + /// have to recurse through rptrs. fn vec_slice_info(tcx: &ty::ctxt, pat: &ast::Pat, slice_ty: Ty) -> (ast::Mutability, ty::Region) { - /*! - * In a pattern like [a, b, ..c], normally `c` has slice type, - * but if you have [a, b, ..ref c], then the type of `ref c` - * will be `&&[]`, so to extract the slice details we have - * to recurse through rptrs. - */ - match slice_ty.sty { ty::ty_rptr(r, ref mt) => match mt.ty.sty { ty::ty_vec(_, None) => (mt.mutbl, r), @@ -1428,13 +1419,9 @@ impl<'tcx> cmt_<'tcx> { } } + /// Returns `Some(_)` if this lvalue represents a freely aliasable pointer type. pub fn freely_aliasable(&self, ctxt: &ty::ctxt<'tcx>) -> Option { - /*! - * Returns `Some(_)` if this lvalue represents a freely aliasable - * pointer type. - */ - // Maybe non-obvious: copied upvars can only be considered // non-aliasable in once closures, since any other kind can be // aliased and eventually recused. diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index c5511f995bc..20be98ca977 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -8,18 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -This file actually contains two passes related to regions. The first -pass builds up the `scope_map`, which describes the parent links in -the region hierarchy. The second pass infers which types must be -region parameterized. - -Most of the documentation on regions can be found in -`middle/typeck/infer/region_inference.rs` - -*/ - +//! This file actually contains two passes related to regions. The first +//! pass builds up the `scope_map`, which describes the parent links in +//! the region hierarchy. The second pass infers which types must be +//! region parameterized. +//! +//! Most of the documentation on regions can be found in +//! `middle/typeck/infer/region_inference.rs` use session::Session; use middle::ty::{mod, Ty, FreeRegion}; @@ -171,14 +166,10 @@ impl RegionMaps { self.rvalue_scopes.borrow_mut().insert(var, lifetime); } + /// Records that a scope is a TERMINATING SCOPE. Whenever we create automatic temporaries -- + /// e.g. by an expression like `a().f` -- they will be freed within the innermost terminating + /// scope. pub fn mark_as_terminating_scope(&self, scope_id: CodeExtent) { - /*! - * Records that a scope is a TERMINATING SCOPE. Whenever we - * create automatic temporaries -- e.g. by an - * expression like `a().f` -- they will be freed within - * the innermost terminating scope. - */ - debug!("record_terminating_scope(scope_id={})", scope_id); self.terminating_scopes.borrow_mut().insert(scope_id); } @@ -197,10 +188,8 @@ impl RegionMaps { } } + /// Returns the lifetime of the local variable `var_id` pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent { - /*! - * Returns the lifetime of the local variable `var_id` - */ match self.var_map.borrow().get(&var_id) { Some(&r) => r, None => { panic!("no enclosing scope for id {}", var_id); } @@ -257,15 +246,12 @@ impl RegionMaps { self.is_subscope_of(scope2, scope1) } + /// Returns true if `subscope` is equal to or is lexically nested inside `superscope` and false + /// otherwise. pub fn is_subscope_of(&self, subscope: CodeExtent, superscope: CodeExtent) -> bool { - /*! - * Returns true if `subscope` is equal to or is lexically - * nested inside `superscope` and false otherwise. - */ - let mut s = subscope; while superscope != s { match self.scope_map.borrow().get(&s) { @@ -285,27 +271,20 @@ impl RegionMaps { return true; } + /// Determines whether two free regions have a subregion relationship + /// by walking the graph encoded in `free_region_map`. Note that + /// it is possible that `sub != sup` and `sub <= sup` and `sup <= sub` + /// (that is, the user can give two different names to the same lifetime). pub fn sub_free_region(&self, sub: FreeRegion, sup: FreeRegion) -> bool { - /*! - * Determines whether two free regions have a subregion relationship - * by walking the graph encoded in `free_region_map`. Note that - * it is possible that `sub != sup` and `sub <= sup` and `sup <= sub` - * (that is, the user can give two different names to the same lifetime). - */ - can_reach(&*self.free_region_map.borrow(), sub, sup) } + /// Determines whether one region is a subregion of another. This is intended to run *after + /// inference* and sadly the logic is somewhat duplicated with the code in infer.rs. pub fn is_subregion_of(&self, sub_region: ty::Region, super_region: ty::Region) -> bool { - /*! - * Determines whether one region is a subregion of another. This is - * intended to run *after inference* and sadly the logic is somewhat - * duplicated with the code in infer.rs. - */ - debug!("is_subregion_of(sub_region={}, super_region={})", sub_region, super_region); @@ -345,16 +324,12 @@ impl RegionMaps { } } + /// Finds the nearest common ancestor (if any) of two scopes. That is, finds the smallest + /// scope which is greater than or equal to both `scope_a` and `scope_b`. pub fn nearest_common_ancestor(&self, scope_a: CodeExtent, scope_b: CodeExtent) -> Option { - /*! - * Finds the nearest common ancestor (if any) of two scopes. That - * is, finds the smallest scope which is greater than or equal to - * both `scope_a` and `scope_b`. - */ - if scope_a == scope_b { return Some(scope_a); } let a_ancestors = ancestors_of(self, scope_a); @@ -681,18 +656,15 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { visit::walk_local(visitor, local); + /// True if `pat` match the `P&` nonterminal: + /// + /// P& = ref X + /// | StructName { ..., P&, ... } + /// | VariantName(..., P&, ...) + /// | [ ..., P&, ... ] + /// | ( ..., P&, ... ) + /// | box P& fn is_binding_pat(pat: &ast::Pat) -> bool { - /*! - * True if `pat` match the `P&` nonterminal: - * - * P& = ref X - * | StructName { ..., P&, ... } - * | VariantName(..., P&, ...) - * | [ ..., P&, ... ] - * | ( ..., P&, ... ) - * | box P& - */ - match pat.node { ast::PatIdent(ast::BindByRef(_), _, _) => true, @@ -719,35 +691,27 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { } } + /// True if `ty` is a borrowed pointer type like `&int` or `&[...]`. fn is_borrowed_ty(ty: &ast::Ty) -> bool { - /*! - * True if `ty` is a borrowed pointer type - * like `&int` or `&[...]`. - */ - match ty.node { ast::TyRptr(..) => true, _ => false } } + /// If `expr` matches the `E&` grammar, then records an extended rvalue scope as appropriate: + /// + /// E& = & ET + /// | StructName { ..., f: E&, ... } + /// | [ ..., E&, ... ] + /// | ( ..., E&, ... ) + /// | {...; E&} + /// | box E& + /// | E& as ... + /// | ( E& ) fn record_rvalue_scope_if_borrow_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr, blk_id: CodeExtent) { - /*! - * If `expr` matches the `E&` grammar, then records an extended - * rvalue scope as appropriate: - * - * E& = & ET - * | StructName { ..., f: E&, ... } - * | [ ..., E&, ... ] - * | ( ..., E&, ... ) - * | {...; E&} - * | box E& - * | E& as ... - * | ( E& ) - */ - match expr.node { ast::ExprAddrOf(_, ref subexpr) => { record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id); @@ -787,29 +751,24 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { } } + /// Applied to an expression `expr` if `expr` -- or something owned or partially owned by + /// `expr` -- is going to be indirectly referenced by a variable in a let statement. In that + /// case, the "temporary lifetime" or `expr` is extended to be the block enclosing the `let` + /// statement. + /// + /// More formally, if `expr` matches the grammar `ET`, record the rvalue scope of the matching + /// `` as `blk_id`: + /// + /// ET = *ET + /// | ET[...] + /// | ET.f + /// | (ET) + /// | + /// + /// Note: ET is intended to match "rvalues or lvalues based on rvalues". fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor, expr: &'a ast::Expr, blk_scope: CodeExtent) { - /*! - * Applied to an expression `expr` if `expr` -- or something - * owned or partially owned by `expr` -- is going to be - * indirectly referenced by a variable in a let statement. In - * that case, the "temporary lifetime" or `expr` is extended - * to be the block enclosing the `let` statement. - * - * More formally, if `expr` matches the grammar `ET`, record - * the rvalue scope of the matching `` as `blk_id`: - * - * ET = *ET - * | ET[...] - * | ET.f - * | (ET) - * | - * - * Note: ET is intended to match "rvalues or - * lvalues based on rvalues". - */ - let mut expr = expr; loop { // Note: give all the expressions matching `ET` with the diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index fae64ff9242..9c32410ecbf 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -8,14 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Name resolution for lifetimes. - * - * Name resolution for lifetimes follows MUCH simpler rules than the - * full resolve. For example, lifetime names are never exported or - * used between functions, and they operate in a purely top-down - * way. Therefore we break lifetime name resolution into a separate pass. - */ +//! Name resolution for lifetimes. +//! +//! Name resolution for lifetimes follows MUCH simpler rules than the +//! full resolve. For example, lifetime names are never exported or +//! used between functions, and they operate in a purely top-down +//! way. Therefore we break lifetime name resolution into a separate pass. pub use self::DefRegion::*; use self::ScopeChain::*; @@ -254,34 +252,27 @@ impl<'a> LifetimeContext<'a> { } /// Visits self by adding a scope and handling recursive walk over the contents with `walk`. + /// + /// Handles visiting fns and methods. These are a bit complicated because we must distinguish + /// early- vs late-bound lifetime parameters. We do this by checking which lifetimes appear + /// within type bounds; those are early bound lifetimes, and the rest are late bound. + /// + /// For example: + /// + /// fn foo<'a,'b,'c,T:Trait<'b>>(...) + /// + /// Here `'a` and `'c` are late bound but `'b` is early bound. Note that early- and late-bound + /// lifetimes may be interspersed together. + /// + /// If early bound lifetimes are present, we separate them into their own list (and likewise + /// for late bound). They will be numbered sequentially, starting from the lowest index that is + /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late + /// bound lifetimes are resolved by name and associated with a binder id (`binder_id`), so the + /// ordering is not important there. fn visit_early_late(&mut self, early_space: subst::ParamSpace, generics: &ast::Generics, walk: |&mut LifetimeContext|) { - /*! - * Handles visiting fns and methods. These are a bit - * complicated because we must distinguish early- vs late-bound - * lifetime parameters. We do this by checking which lifetimes - * appear within type bounds; those are early bound lifetimes, - * and the rest are late bound. - * - * For example: - * - * fn foo<'a,'b,'c,T:Trait<'b>>(...) - * - * Here `'a` and `'c` are late bound but `'b` is early - * bound. Note that early- and late-bound lifetimes may be - * interspersed together. - * - * If early bound lifetimes are present, we separate them into - * their own list (and likewise for late bound). They will be - * numbered sequentially, starting from the lowest index that - * is already in scope (for a fn item, that will be 0, but for - * a method it might not be). Late bound lifetimes are - * resolved by name and associated with a binder id (`binder_id`), so - * the ordering is not important there. - */ - let referenced_idents = early_bound_lifetime_names(generics); debug!("visit_early_late: referenced_idents={}", @@ -479,13 +470,9 @@ pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec Vec { - /*! - * Given a set of generic declarations, returns a list of names - * containing all early bound lifetime names for those - * generics. (In fact, this list may also contain other names.) - */ - // Create two lists, dividing the lifetimes into early/late bound. // Initially, all of them are considered late, but we will move // things from late into early as we go if we find references to diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index b030867fc84..365c2ed39db 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -131,26 +131,18 @@ pub fn self_ty(&self) -> Option> { Substs { types: types, regions: ErasedRegions } } + /// Since ErasedRegions are only to be used in trans, most of the compiler can use this method + /// to easily access the set of region substitutions. pub fn regions<'a>(&'a self) -> &'a VecPerParamSpace { - /*! - * Since ErasedRegions are only to be used in trans, most of - * the compiler can use this method to easily access the set - * of region substitutions. - */ - match self.regions { ErasedRegions => panic!("Erased regions only expected in trans"), NonerasedRegions(ref r) => r } } + /// Since ErasedRegions are only to be used in trans, most of the compiler can use this method + /// to easily access the set of region substitutions. pub fn mut_regions<'a>(&'a mut self) -> &'a mut VecPerParamSpace { - /*! - * Since ErasedRegions are only to be used in trans, most of - * the compiler can use this method to easily access the set - * of region substitutions. - */ - match self.regions { ErasedRegions => panic!("Erased regions only expected in trans"), NonerasedRegions(ref mut r) => r @@ -688,59 +680,49 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> { self.shift_regions_through_binders(ty) } + /// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs + /// when we are substituting a type with escaping regions into a context where we have passed + /// through region binders. That's quite a mouthful. Let's see an example: + /// + /// ``` + /// type Func = fn(A); + /// type MetaFunc = for<'a> fn(Func<&'a int>) + /// ``` + /// + /// The type `MetaFunc`, when fully expanded, will be + /// + /// for<'a> fn(fn(&'a int)) + /// ^~ ^~ ^~~ + /// | | | + /// | | DebruijnIndex of 2 + /// Binders + /// + /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the + /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip + /// over the inner binder (remember that we count Debruijn indices from 1). However, in the + /// definition of `MetaFunc`, the binder is not visible, so the type `&'a int` will have a + /// debruijn index of 1. It's only during the substitution that we can see we must increase the + /// depth by 1 to account for the binder that we passed through. + /// + /// As a second example, consider this twist: + /// + /// ``` + /// type FuncTuple = (A,fn(A)); + /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>) + /// ``` + /// + /// Here the final type will be: + /// + /// for<'a> fn((&'a int, fn(&'a int))) + /// ^~~ ^~~ + /// | | + /// DebruijnIndex of 1 | + /// DebruijnIndex of 2 + /// + /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the + /// first case we do not increase the Debruijn index and in the second case we do. The reason + /// is that only in the second case have we passed through a fn binder. fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> { - /*! - * It is sometimes necessary to adjust the debruijn indices - * during substitution. This occurs when we are substituting a - * type with escaping regions into a context where we have - * passed through region binders. That's quite a - * mouthful. Let's see an example: - * - * ``` - * type Func = fn(A); - * type MetaFunc = for<'a> fn(Func<&'a int>) - * ``` - * - * The type `MetaFunc`, when fully expanded, will be - * - * for<'a> fn(fn(&'a int)) - * ^~ ^~ ^~~ - * | | | - * | | DebruijnIndex of 2 - * Binders - * - * Here the `'a` lifetime is bound in the outer function, but - * appears as an argument of the inner one. Therefore, that - * appearance will have a DebruijnIndex of 2, because we must - * skip over the inner binder (remember that we count Debruijn - * indices from 1). However, in the definition of `MetaFunc`, - * the binder is not visible, so the type `&'a int` will have - * a debruijn index of 1. It's only during the substitution - * that we can see we must increase the depth by 1 to account - * for the binder that we passed through. - * - * As a second example, consider this twist: - * - * ``` - * type FuncTuple = (A,fn(A)); - * type MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>) - * ``` - * - * Here the final type will be: - * - * for<'a> fn((&'a int, fn(&'a int))) - * ^~~ ^~~ - * | | - * DebruijnIndex of 1 | - * DebruijnIndex of 2 - * - * As indicated in the diagram, here the same type `&'a int` - * is substituted once, but in the first case we do not - * increase the Debruijn index and in the second case we - * do. The reason is that only in the second case have we - * passed through a fn binder. - */ - debug!("shift_regions(ty={}, region_binders_passed={}, type_has_escaping_regions={})", ty.repr(self.tcx()), self.region_binders_passed, ty::type_has_escaping_regions(ty)); diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index c84a2a0d11e..048f394224c 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! See `doc.rs` for high-level documentation */ +//! See `doc.rs` for high-level documentation use super::SelectionContext; use super::Obligation; diff --git a/src/librustc/middle/traits/doc.rs b/src/librustc/middle/traits/doc.rs index c014bc0c164..62246b77ee9 100644 --- a/src/librustc/middle/traits/doc.rs +++ b/src/librustc/middle/traits/doc.rs @@ -8,403 +8,399 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -# TRAIT RESOLUTION - -This document describes the general process and points out some non-obvious -things. - -## Major concepts - -Trait resolution is the process of pairing up an impl with each -reference to a trait. So, for example, if there is a generic function like: - - fn clone_slice(x: &[T]) -> Vec { ... } - -and then a call to that function: - - let v: Vec = clone_slice([1, 2, 3].as_slice()) - -it is the job of trait resolution to figure out (in which case) -whether there exists an impl of `int : Clone` - -Note that in some cases, like generic functions, we may not be able to -find a specific impl, but we can figure out that the caller must -provide an impl. To see what I mean, consider the body of `clone_slice`: - - fn clone_slice(x: &[T]) -> Vec { - let mut v = Vec::new(); - for e in x.iter() { - v.push((*e).clone()); // (*) - } - } - -The line marked `(*)` is only legal if `T` (the type of `*e`) -implements the `Clone` trait. Naturally, since we don't know what `T` -is, we can't find the specific impl; but based on the bound `T:Clone`, -we can say that there exists an impl which the caller must provide. - -We use the term *obligation* to refer to a trait reference in need of -an impl. - -## Overview - -Trait resolution consists of three major parts: - -- SELECTION: Deciding how to resolve a specific obligation. For - example, selection might decide that a specific obligation can be - resolved by employing an impl which matches the self type, or by - using a parameter bound. In the case of an impl, Selecting one - obligation can create *nested obligations* because of where clauses - on the impl itself. It may also require evaluating those nested - obligations to resolve ambiguities. - -- FULFILLMENT: The fulfillment code is what tracks that obligations - are completely fulfilled. Basically it is a worklist of obligations - to be selected: once selection is successful, the obligation is - removed from the worklist and any nested obligations are enqueued. - -- COHERENCE: The coherence checks are intended to ensure that there - are never overlapping impls, where two impls could be used with - equal precedence. - -## Selection - -Selection is the process of deciding whether an obligation can be -resolved and, if so, how it is to be resolved (via impl, where clause, etc). -The main interface is the `select()` function, which takes an obligation -and returns a `SelectionResult`. There are three possible outcomes: - -- `Ok(Some(selection))` -- yes, the obligation can be resolved, and - `selection` indicates how. If the impl was resolved via an impl, - then `selection` may also indicate nested obligations that are required - by the impl. - -- `Ok(None)` -- we are not yet sure whether the obligation can be - resolved or not. This happens most commonly when the obligation - contains unbound type variables. - -- `Err(err)` -- the obligation definitely cannot be resolved due to a - type error, or because there are no impls that could possibly apply, - etc. - -The basic algorithm for selection is broken into two big phases: -candidate assembly and confirmation. - -### Candidate assembly - -Searches for impls/where-clauses/etc that might -possibly be used to satisfy the obligation. Each of those is called -a candidate. To avoid ambiguity, we want to find exactly one -candidate that is definitively applicable. In some cases, we may not -know whether an impl/where-clause applies or not -- this occurs when -the obligation contains unbound inference variables. - -The basic idea for candidate assembly is to do a first pass in which -we identify all possible candidates. During this pass, all that we do -is try and unify the type parameters. (In particular, we ignore any -nested where clauses.) Presuming that this unification succeeds, the -impl is added as a candidate. - -Once this first pass is done, we can examine the set of candidates. If -it is a singleton set, then we are done: this is the only impl in -scope that could possibly apply. Otherwise, we can winnow down the set -of candidates by using where clauses and other conditions. If this -reduced set yields a single, unambiguous entry, we're good to go, -otherwise the result is considered ambiguous. - -#### The basic process: Inferring based on the impls we see - -This process is easier if we work through some examples. Consider -the following trait: - -``` -trait Convert { - fn convert(&self) -> Target; -} -``` - -This trait just has one method. It's about as simple as it gets. It -converts from the (implicit) `Self` type to the `Target` type. If we -wanted to permit conversion between `int` and `uint`, we might -implement `Convert` like so: - -```rust -impl Convert for int { ... } // int -> uint -impl Convert for uint { ... } // uint -> uint -``` - -Now imagine there is some code like the following: - -```rust -let x: int = ...; -let y = x.convert(); -``` - -The call to convert will generate a trait reference `Convert<$Y> for -int`, where `$Y` is the type variable representing the type of -`y`. When we match this against the two impls we can see, we will find -that only one remains: `Convert for int`. Therefore, we can -select this impl, which will cause the type of `$Y` to be unified to -`uint`. (Note that while assembling candidates, we do the initial -unifications in a transaction, so that they don't affect one another.) - -There are tests to this effect in src/test/run-pass: - - traits-multidispatch-infer-convert-source-and-target.rs - traits-multidispatch-infer-convert-target.rs - -#### Winnowing: Resolving ambiguities - -But what happens if there are multiple impls where all the types -unify? Consider this example: - -```rust -trait Get { - fn get(&self) -> Self; -} - -impl Get for T { - fn get(&self) -> T { *self } -} - -impl Get for Box { - fn get(&self) -> Box { box get_it(&**self) } -} -``` - -What happens when we invoke `get_it(&box 1_u16)`, for example? In this -case, the `Self` type is `Box` -- that unifies with both impls, -because the first applies to all types, and the second to all -boxes. In the olden days we'd have called this ambiguous. But what we -do now is do a second *winnowing* pass that considers where clauses -and attempts to remove candidates -- in this case, the first impl only -applies if `Box : Copy`, which doesn't hold. After winnowing, -then, we are left with just one candidate, so we can proceed. There is -a test of this in `src/test/run-pass/traits-conditional-dispatch.rs`. - -#### Matching - -The subroutines that decide whether a particular impl/where-clause/etc -applies to a particular obligation. At the moment, this amounts to -unifying the self types, but in the future we may also recursively -consider some of the nested obligations, in the case of an impl. - -#### Lifetimes and selection - -Because of how that lifetime inference works, it is not possible to -give back immediate feedback as to whether a unification or subtype -relationship between lifetimes holds or not. Therefore, lifetime -matching is *not* considered during selection. This is reflected in -the fact that subregion assignment is infallible. This may yield -lifetime constraints that will later be found to be in error (in -contrast, the non-lifetime-constraints have already been checked -during selection and can never cause an error, though naturally they -may lead to other errors downstream). - -#### Where clauses - -Besides an impl, the other major way to resolve an obligation is via a -where clause. The selection process is always given a *parameter -environment* which contains a list of where clauses, which are -basically obligations that can assume are satisfiable. We will iterate -over that list and check whether our current obligation can be found -in that list, and if so it is considered satisfied. More precisely, we -want to check whether there is a where-clause obligation that is for -the same trait (or some subtrait) and for which the self types match, -using the definition of *matching* given above. - -Consider this simple example: - - trait A1 { ... } - trait A2 : A1 { ... } - - trait B { ... } - - fn foo { ... } - -Clearly we can use methods offered by `A1`, `A2`, or `B` within the -body of `foo`. In each case, that will incur an obligation like `X : -A1` or `X : A2`. The parameter environment will contain two -where-clauses, `X : A2` and `X : B`. For each obligation, then, we -search this list of where-clauses. To resolve an obligation `X:A1`, -we would note that `X:A2` implies that `X:A1`. - -### Confirmation - -Confirmation unifies the output type parameters of the trait with the -values found in the obligation, possibly yielding a type error. If we -return to our example of the `Convert` trait from the previous -section, confirmation is where an error would be reported, because the -impl specified that `T` would be `uint`, but the obligation reported -`char`. Hence the result of selection would be an error. - -### Selection during translation - -During type checking, we do not store the results of trait selection. -We simply wish to verify that trait selection will succeed. Then -later, at trans time, when we have all concrete types available, we -can repeat the trait selection. In this case, we do not consider any -where-clauses to be in scope. We know that therefore each resolution -will resolve to a particular impl. - -One interesting twist has to do with nested obligations. In general, in trans, -we only need to do a "shallow" selection for an obligation. That is, we wish to -identify which impl applies, but we do not (yet) need to decide how to select -any nested obligations. Nonetheless, we *do* currently do a complete resolution, -and that is because it can sometimes inform the results of type inference. That is, -we do not have the full substitutions in terms of the type varibales of the impl available -to us, so we must run trait selection to figure everything out. - -Here is an example: - - trait Foo { ... } - impl> Foo for Vec { ... } - - impl Bar for int { ... } - -After one shallow round of selection for an obligation like `Vec -: Foo`, we would know which impl we want, and we would know that -`T=int`, but we do not know the type of `U`. We must select the -nested obligation `int : Bar` to find out that `U=uint`. - -It would be good to only do *just as much* nested resolution as -necessary. Currently, though, we just do a full resolution. - -## Method matching - -Method dispach follows a slightly different path than normal trait -selection. This is because it must account for the transformed self -type of the receiver and various other complications. The procedure is -described in `select.rs` in the "METHOD MATCHING" section. - -# Caching and subtle considerations therewith - -In general we attempt to cache the results of trait selection. This -is a somewhat complex process. Part of the reason for this is that we -want to be able to cache results even when all the types in the trait -reference are not fully known. In that case, it may happen that the -trait selection process is also influencing type variables, so we have -to be able to not only cache the *result* of the selection process, -but *replay* its effects on the type variables. - -## An example - -The high-level idea of how the cache works is that we first replace -all unbound inference variables with skolemized versions. Therefore, -if we had a trait reference `uint : Foo<$1>`, where `$n` is an unbound -inference variable, we might replace it with `uint : Foo<%0>`, where -`%n` is a skolemized type. We would then look this up in the cache. -If we found a hit, the hit would tell us the immediate next step to -take in the selection process: i.e., apply impl #22, or apply where -clause `X : Foo`. Let's say in this case there is no hit. -Therefore, we search through impls and where clauses and so forth, and -we come to the conclusion that the only possible impl is this one, -with def-id 22: - - impl Foo for uint { ... } // Impl #22 - -We would then record in the cache `uint : Foo<%0> ==> -ImplCandidate(22)`. Next we would confirm `ImplCandidate(22)`, which -would (as a side-effect) unify `$1` with `int`. - -Now, at some later time, we might come along and see a `uint : -Foo<$3>`. When skolemized, this would yield `uint : Foo<%0>`, just as -before, and hence the cache lookup would succeed, yielding -`ImplCandidate(22)`. We would confirm `ImplCandidate(22)` which would -(as a side-effect) unify `$3` with `int`. - -## Where clauses and the local vs global cache - -One subtle interaction is that the results of trait lookup will vary -depending on what where clauses are in scope. Therefore, we actually -have *two* caches, a local and a global cache. The local cache is -attached to the `ParameterEnvironment` and the global cache attached -to the `tcx`. We use the local cache whenever the result might depend -on the where clauses that are in scope. The determination of which -cache to use is done by the method `pick_candidate_cache` in -`select.rs`. - -There are two cases where we currently use the local cache. The -current rules are probably more conservative than necessary. - -### Trait references that involve parameter types - -The most obvious case where you need the local environment is -when the trait reference includes parameter types. For example, -consider the following function: - - impl Vec { - fn foo(x: T) - where T : Foo - { ... } - - fn bar(x: T) - { ... } - } - -If there is an obligation `T : Foo`, or `int : Bar`, or whatever, -clearly the results from `foo` and `bar` are potentially different, -since the set of where clauses in scope are different. - -### Trait references with unbound variables when where clauses are in scope - -There is another less obvious interaction which involves unbound variables -where *only* where clauses are in scope (no impls). This manifested as -issue #18209 (`run-pass/trait-cache-issue-18209.rs`). Consider -this snippet: - -``` -pub trait Foo { - fn load_from() -> Box; - fn load() -> Box { - Foo::load_from() - } -} -``` - -The default method will incur an obligation `$0 : Foo` from the call -to `load_from`. If there are no impls, this can be eagerly resolved to -`VtableParam(Self : Foo)` and cached. Because the trait reference -doesn't involve any parameters types (only the resolution does), this -result was stored in the global cache, causing later calls to -`Foo::load_from()` to get nonsense. - -To fix this, we always use the local cache if there are unbound -variables and where clauses in scope. This is more conservative than -necessary as far as I can tell. However, it still seems to be a simple -rule and I observe ~99% hit rate on rustc, so it doesn't seem to hurt -us in particular. - -Here is an example of the kind of subtle case that I would be worried -about with a more complex rule (although this particular case works -out ok). Imagine the trait reference doesn't directly reference a -where clause, but the where clause plays a role in the winnowing -phase. Something like this: - -``` -pub trait Foo { ... } -pub trait Bar { ... } -impl Foo for T { ... } // Impl A -impl Foo for uint { ... } // Impl B -``` - -Now, in some function, we have no where clauses in scope, and we have -an obligation `$1 : Foo<$0>`. We might then conclude that `$0=char` -and `$1=uint`: this is because for impl A to apply, `uint:Bar` would -have to hold, and we know it does not or else the coherence check -would have failed. So we might enter into our global cache: `$1 : -Foo<$0> => Impl B`. Then we come along in a different scope, where a -generic type `A` is around with the bound `A:Bar`. Now suddenly the -impl is viable. - -The flaw in this imaginary DOOMSDAY SCENARIO is that we would not -currently conclude that `$1 : Foo<$0>` implies that `$0 == uint` and -`$1 == char`, even though it is true that (absent type parameters) -there is no other type the user could enter. However, it is not -*completely* implausible that we *could* draw this conclusion in the -future; we wouldn't have to guess types, in particular, we could be -led by the impls. - -*/ +//! # TRAIT RESOLUTION +//! +//! This document describes the general process and points out some non-obvious +//! things. +//! +//! ## Major concepts +//! +//! Trait resolution is the process of pairing up an impl with each +//! reference to a trait. So, for example, if there is a generic function like: +//! +//! fn clone_slice(x: &[T]) -> Vec { ... } +//! +//! and then a call to that function: +//! +//! let v: Vec = clone_slice([1, 2, 3].as_slice()) +//! +//! it is the job of trait resolution to figure out (in which case) +//! whether there exists an impl of `int : Clone` +//! +//! Note that in some cases, like generic functions, we may not be able to +//! find a specific impl, but we can figure out that the caller must +//! provide an impl. To see what I mean, consider the body of `clone_slice`: +//! +//! fn clone_slice(x: &[T]) -> Vec { +//! let mut v = Vec::new(); +//! for e in x.iter() { +//! v.push((*e).clone()); // (*) +//! } +//! } +//! +//! The line marked `(*)` is only legal if `T` (the type of `*e`) +//! implements the `Clone` trait. Naturally, since we don't know what `T` +//! is, we can't find the specific impl; but based on the bound `T:Clone`, +//! we can say that there exists an impl which the caller must provide. +//! +//! We use the term *obligation* to refer to a trait reference in need of +//! an impl. +//! +//! ## Overview +//! +//! Trait resolution consists of three major parts: +//! +//! - SELECTION: Deciding how to resolve a specific obligation. For +//! example, selection might decide that a specific obligation can be +//! resolved by employing an impl which matches the self type, or by +//! using a parameter bound. In the case of an impl, Selecting one +//! obligation can create *nested obligations* because of where clauses +//! on the impl itself. It may also require evaluating those nested +//! obligations to resolve ambiguities. +//! +//! - FULFILLMENT: The fulfillment code is what tracks that obligations +//! are completely fulfilled. Basically it is a worklist of obligations +//! to be selected: once selection is successful, the obligation is +//! removed from the worklist and any nested obligations are enqueued. +//! +//! - COHERENCE: The coherence checks are intended to ensure that there +//! are never overlapping impls, where two impls could be used with +//! equal precedence. +//! +//! ## Selection +//! +//! Selection is the process of deciding whether an obligation can be +//! resolved and, if so, how it is to be resolved (via impl, where clause, etc). +//! The main interface is the `select()` function, which takes an obligation +//! and returns a `SelectionResult`. There are three possible outcomes: +//! +//! - `Ok(Some(selection))` -- yes, the obligation can be resolved, and +//! `selection` indicates how. If the impl was resolved via an impl, +//! then `selection` may also indicate nested obligations that are required +//! by the impl. +//! +//! - `Ok(None)` -- we are not yet sure whether the obligation can be +//! resolved or not. This happens most commonly when the obligation +//! contains unbound type variables. +//! +//! - `Err(err)` -- the obligation definitely cannot be resolved due to a +//! type error, or because there are no impls that could possibly apply, +//! etc. +//! +//! The basic algorithm for selection is broken into two big phases: +//! candidate assembly and confirmation. +//! +//! ### Candidate assembly +//! +//! Searches for impls/where-clauses/etc that might +//! possibly be used to satisfy the obligation. Each of those is called +//! a candidate. To avoid ambiguity, we want to find exactly one +//! candidate that is definitively applicable. In some cases, we may not +//! know whether an impl/where-clause applies or not -- this occurs when +//! the obligation contains unbound inference variables. +//! +//! The basic idea for candidate assembly is to do a first pass in which +//! we identify all possible candidates. During this pass, all that we do +//! is try and unify the type parameters. (In particular, we ignore any +//! nested where clauses.) Presuming that this unification succeeds, the +//! impl is added as a candidate. +//! +//! Once this first pass is done, we can examine the set of candidates. If +//! it is a singleton set, then we are done: this is the only impl in +//! scope that could possibly apply. Otherwise, we can winnow down the set +//! of candidates by using where clauses and other conditions. If this +//! reduced set yields a single, unambiguous entry, we're good to go, +//! otherwise the result is considered ambiguous. +//! +//! #### The basic process: Inferring based on the impls we see +//! +//! This process is easier if we work through some examples. Consider +//! the following trait: +//! +//! ``` +//! trait Convert { +//! fn convert(&self) -> Target; +//! } +//! ``` +//! +//! This trait just has one method. It's about as simple as it gets. It +//! converts from the (implicit) `Self` type to the `Target` type. If we +//! wanted to permit conversion between `int` and `uint`, we might +//! implement `Convert` like so: +//! +//! ```rust +//! impl Convert for int { ... } // int -> uint +//! impl Convert for uint { ... } // uint -> uint +//! ``` +//! +//! Now imagine there is some code like the following: +//! +//! ```rust +//! let x: int = ...; +//! let y = x.convert(); +//! ``` +//! +//! The call to convert will generate a trait reference `Convert<$Y> for +//! int`, where `$Y` is the type variable representing the type of +//! `y`. When we match this against the two impls we can see, we will find +//! that only one remains: `Convert for int`. Therefore, we can +//! select this impl, which will cause the type of `$Y` to be unified to +//! `uint`. (Note that while assembling candidates, we do the initial +//! unifications in a transaction, so that they don't affect one another.) +//! +//! There are tests to this effect in src/test/run-pass: +//! +//! traits-multidispatch-infer-convert-source-and-target.rs +//! traits-multidispatch-infer-convert-target.rs +//! +//! #### Winnowing: Resolving ambiguities +//! +//! But what happens if there are multiple impls where all the types +//! unify? Consider this example: +//! +//! ```rust +//! trait Get { +//! fn get(&self) -> Self; +//! } +//! +//! impl Get for T { +//! fn get(&self) -> T { *self } +//! } +//! +//! impl Get for Box { +//! fn get(&self) -> Box { box get_it(&**self) } +//! } +//! ``` +//! +//! What happens when we invoke `get_it(&box 1_u16)`, for example? In this +//! case, the `Self` type is `Box` -- that unifies with both impls, +//! because the first applies to all types, and the second to all +//! boxes. In the olden days we'd have called this ambiguous. But what we +//! do now is do a second *winnowing* pass that considers where clauses +//! and attempts to remove candidates -- in this case, the first impl only +//! applies if `Box : Copy`, which doesn't hold. After winnowing, +//! then, we are left with just one candidate, so we can proceed. There is +//! a test of this in `src/test/run-pass/traits-conditional-dispatch.rs`. +//! +//! #### Matching +//! +//! The subroutines that decide whether a particular impl/where-clause/etc +//! applies to a particular obligation. At the moment, this amounts to +//! unifying the self types, but in the future we may also recursively +//! consider some of the nested obligations, in the case of an impl. +//! +//! #### Lifetimes and selection +//! +//! Because of how that lifetime inference works, it is not possible to +//! give back immediate feedback as to whether a unification or subtype +//! relationship between lifetimes holds or not. Therefore, lifetime +//! matching is *not* considered during selection. This is reflected in +//! the fact that subregion assignment is infallible. This may yield +//! lifetime constraints that will later be found to be in error (in +//! contrast, the non-lifetime-constraints have already been checked +//! during selection and can never cause an error, though naturally they +//! may lead to other errors downstream). +//! +//! #### Where clauses +//! +//! Besides an impl, the other major way to resolve an obligation is via a +//! where clause. The selection process is always given a *parameter +//! environment* which contains a list of where clauses, which are +//! basically obligations that can assume are satisfiable. We will iterate +//! over that list and check whether our current obligation can be found +//! in that list, and if so it is considered satisfied. More precisely, we +//! want to check whether there is a where-clause obligation that is for +//! the same trait (or some subtrait) and for which the self types match, +//! using the definition of *matching* given above. +//! +//! Consider this simple example: +//! +//! trait A1 { ... } +//! trait A2 : A1 { ... } +//! +//! trait B { ... } +//! +//! fn foo { ... } +//! +//! Clearly we can use methods offered by `A1`, `A2`, or `B` within the +//! body of `foo`. In each case, that will incur an obligation like `X : +//! A1` or `X : A2`. The parameter environment will contain two +//! where-clauses, `X : A2` and `X : B`. For each obligation, then, we +//! search this list of where-clauses. To resolve an obligation `X:A1`, +//! we would note that `X:A2` implies that `X:A1`. +//! +//! ### Confirmation +//! +//! Confirmation unifies the output type parameters of the trait with the +//! values found in the obligation, possibly yielding a type error. If we +//! return to our example of the `Convert` trait from the previous +//! section, confirmation is where an error would be reported, because the +//! impl specified that `T` would be `uint`, but the obligation reported +//! `char`. Hence the result of selection would be an error. +//! +//! ### Selection during translation +//! +//! During type checking, we do not store the results of trait selection. +//! We simply wish to verify that trait selection will succeed. Then +//! later, at trans time, when we have all concrete types available, we +//! can repeat the trait selection. In this case, we do not consider any +//! where-clauses to be in scope. We know that therefore each resolution +//! will resolve to a particular impl. +//! +//! One interesting twist has to do with nested obligations. In general, in trans, +//! we only need to do a "shallow" selection for an obligation. That is, we wish to +//! identify which impl applies, but we do not (yet) need to decide how to select +//! any nested obligations. Nonetheless, we *do* currently do a complete resolution, +//! and that is because it can sometimes inform the results of type inference. That is, +//! we do not have the full substitutions in terms of the type varibales of the impl available +//! to us, so we must run trait selection to figure everything out. +//! +//! Here is an example: +//! +//! trait Foo { ... } +//! impl> Foo for Vec { ... } +//! +//! impl Bar for int { ... } +//! +//! After one shallow round of selection for an obligation like `Vec +//! : Foo`, we would know which impl we want, and we would know that +//! `T=int`, but we do not know the type of `U`. We must select the +//! nested obligation `int : Bar` to find out that `U=uint`. +//! +//! It would be good to only do *just as much* nested resolution as +//! necessary. Currently, though, we just do a full resolution. +//! +//! ## Method matching +//! +//! Method dispach follows a slightly different path than normal trait +//! selection. This is because it must account for the transformed self +//! type of the receiver and various other complications. The procedure is +//! described in `select.rs` in the "METHOD MATCHING" section. +//! +//! # Caching and subtle considerations therewith +//! +//! In general we attempt to cache the results of trait selection. This +//! is a somewhat complex process. Part of the reason for this is that we +//! want to be able to cache results even when all the types in the trait +//! reference are not fully known. In that case, it may happen that the +//! trait selection process is also influencing type variables, so we have +//! to be able to not only cache the *result* of the selection process, +//! but *replay* its effects on the type variables. +//! +//! ## An example +//! +//! The high-level idea of how the cache works is that we first replace +//! all unbound inference variables with skolemized versions. Therefore, +//! if we had a trait reference `uint : Foo<$1>`, where `$n` is an unbound +//! inference variable, we might replace it with `uint : Foo<%0>`, where +//! `%n` is a skolemized type. We would then look this up in the cache. +//! If we found a hit, the hit would tell us the immediate next step to +//! take in the selection process: i.e., apply impl #22, or apply where +//! clause `X : Foo`. Let's say in this case there is no hit. +//! Therefore, we search through impls and where clauses and so forth, and +//! we come to the conclusion that the only possible impl is this one, +//! with def-id 22: +//! +//! impl Foo for uint { ... } // Impl #22 +//! +//! We would then record in the cache `uint : Foo<%0> ==> +//! ImplCandidate(22)`. Next we would confirm `ImplCandidate(22)`, which +//! would (as a side-effect) unify `$1` with `int`. +//! +//! Now, at some later time, we might come along and see a `uint : +//! Foo<$3>`. When skolemized, this would yield `uint : Foo<%0>`, just as +//! before, and hence the cache lookup would succeed, yielding +//! `ImplCandidate(22)`. We would confirm `ImplCandidate(22)` which would +//! (as a side-effect) unify `$3` with `int`. +//! +//! ## Where clauses and the local vs global cache +//! +//! One subtle interaction is that the results of trait lookup will vary +//! depending on what where clauses are in scope. Therefore, we actually +//! have *two* caches, a local and a global cache. The local cache is +//! attached to the `ParameterEnvironment` and the global cache attached +//! to the `tcx`. We use the local cache whenever the result might depend +//! on the where clauses that are in scope. The determination of which +//! cache to use is done by the method `pick_candidate_cache` in +//! `select.rs`. +//! +//! There are two cases where we currently use the local cache. The +//! current rules are probably more conservative than necessary. +//! +//! ### Trait references that involve parameter types +//! +//! The most obvious case where you need the local environment is +//! when the trait reference includes parameter types. For example, +//! consider the following function: +//! +//! impl Vec { +//! fn foo(x: T) +//! where T : Foo +//! { ... } +//! +//! fn bar(x: T) +//! { ... } +//! } +//! +//! If there is an obligation `T : Foo`, or `int : Bar`, or whatever, +//! clearly the results from `foo` and `bar` are potentially different, +//! since the set of where clauses in scope are different. +//! +//! ### Trait references with unbound variables when where clauses are in scope +//! +//! There is another less obvious interaction which involves unbound variables +//! where *only* where clauses are in scope (no impls). This manifested as +//! issue #18209 (`run-pass/trait-cache-issue-18209.rs`). Consider +//! this snippet: +//! +//! ``` +//! pub trait Foo { +//! fn load_from() -> Box; +//! fn load() -> Box { +//! Foo::load_from() +//! } +//! } +//! ``` +//! +//! The default method will incur an obligation `$0 : Foo` from the call +//! to `load_from`. If there are no impls, this can be eagerly resolved to +//! `VtableParam(Self : Foo)` and cached. Because the trait reference +//! doesn't involve any parameters types (only the resolution does), this +//! result was stored in the global cache, causing later calls to +//! `Foo::load_from()` to get nonsense. +//! +//! To fix this, we always use the local cache if there are unbound +//! variables and where clauses in scope. This is more conservative than +//! necessary as far as I can tell. However, it still seems to be a simple +//! rule and I observe ~99% hit rate on rustc, so it doesn't seem to hurt +//! us in particular. +//! +//! Here is an example of the kind of subtle case that I would be worried +//! about with a more complex rule (although this particular case works +//! out ok). Imagine the trait reference doesn't directly reference a +//! where clause, but the where clause plays a role in the winnowing +//! phase. Something like this: +//! +//! ``` +//! pub trait Foo { ... } +//! pub trait Bar { ... } +//! impl Foo for T { ... } // Impl A +//! impl Foo for uint { ... } // Impl B +//! ``` +//! +//! Now, in some function, we have no where clauses in scope, and we have +//! an obligation `$1 : Foo<$0>`. We might then conclude that `$0=char` +//! and `$1=uint`: this is because for impl A to apply, `uint:Bar` would +//! have to hold, and we know it does not or else the coherence check +//! would have failed. So we might enter into our global cache: `$1 : +//! Foo<$0> => Impl B`. Then we come along in a different scope, where a +//! generic type `A` is around with the bound `A:Bar`. Now suddenly the +//! impl is viable. +//! +//! The flaw in this imaginary DOOMSDAY SCENARIO is that we would not +//! currently conclude that `$1 : Foo<$0>` implies that `$0 == uint` and +//! `$1 == char`, even though it is true that (absent type parameters) +//! there is no other type the user could enter. However, it is not +//! *completely* implausible that we *could* draw this conclusion in the +//! future; we wouldn't have to guess types, in particular, we could be +//! led by the impls. diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 62382ac386f..a22eba486e8 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -81,20 +81,16 @@ impl<'tcx> FulfillmentContext<'tcx> { } } + /// Attempts to select obligations that were registered since the call to a selection routine. + /// This is used by the type checker to eagerly attempt to resolve obligations in hopes of + /// gaining type information. It'd be equally valid to use `select_where_possible` but it + /// results in `O(n^2)` performance (#18208). pub fn select_new_obligations<'a>(&mut self, infcx: &InferCtxt<'a,'tcx>, param_env: &ty::ParameterEnvironment<'tcx>, typer: &Typer<'tcx>) -> Result<(),Vec>> { - /*! - * Attempts to select obligations that were registered since - * the call to a selection routine. This is used by the type checker - * to eagerly attempt to resolve obligations in hopes of gaining - * type information. It'd be equally valid to use `select_where_possible` - * but it results in `O(n^2)` performance (#18208). - */ - let mut selcx = SelectionContext::new(infcx, param_env, typer); self.select(&mut selcx, true) } @@ -113,16 +109,13 @@ impl<'tcx> FulfillmentContext<'tcx> { self.trait_obligations[] } + /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it + /// only attempts to select obligations that haven't been seen before. fn select<'a>(&mut self, selcx: &mut SelectionContext<'a, 'tcx>, only_new_obligations: bool) -> Result<(),Vec>> { - /*! - * Attempts to select obligations using `selcx`. If - * `only_new_obligations` is true, then it only attempts to - * select obligations that haven't been seen before. - */ debug!("select({} obligations, only_new_obligations={}) start", self.trait_obligations.len(), only_new_obligations); diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 0a47d647890..c4eeff8caf6 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Trait Resolution. See doc.rs. - */ +//! Trait Resolution. See doc.rs. pub use self::SelectionError::*; pub use self::FulfillmentErrorCode::*; @@ -226,6 +224,10 @@ pub struct VtableParamData<'tcx> { pub bound: Rc>, } +/// Matches the self type of the inherent impl `impl_def_id` +/// against `self_ty` and returns the resulting resolution. This +/// routine may modify the surrounding type context (for example, +/// it may unify variables). pub fn select_inherent_impl<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, param_env: &ty::ParameterEnvironment<'tcx>, typer: &Typer<'tcx>, @@ -235,13 +237,6 @@ pub fn select_inherent_impl<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, -> SelectionResult<'tcx, VtableImplData<'tcx, Obligation<'tcx>>> { - /*! - * Matches the self type of the inherent impl `impl_def_id` - * against `self_ty` and returns the resulting resolution. This - * routine may modify the surrounding type context (for example, - * it may unify variables). - */ - // This routine is only suitable for inherent impls. This is // because it does not attempt to unify the output type parameters // from the trait ref against the values from the obligation. @@ -256,53 +251,41 @@ pub fn select_inherent_impl<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, selcx.select_inherent_impl(impl_def_id, cause, self_ty) } +/// True if neither the trait nor self type is local. Note that `impl_def_id` must refer to an impl +/// of a trait, not an inherent impl. pub fn is_orphan_impl(tcx: &ty::ctxt, impl_def_id: ast::DefId) -> bool { - /*! - * True if neither the trait nor self type is local. Note that - * `impl_def_id` must refer to an impl of a trait, not an inherent - * impl. - */ - !coherence::impl_is_local(tcx, impl_def_id) } +/// True if there exist types that satisfy both of the two given impls. pub fn overlapping_impls(infcx: &InferCtxt, impl1_def_id: ast::DefId, impl2_def_id: ast::DefId) -> bool { - /*! - * True if there exist types that satisfy both of the two given impls. - */ - coherence::impl_can_satisfy(infcx, impl1_def_id, impl2_def_id) && coherence::impl_can_satisfy(infcx, impl2_def_id, impl1_def_id) } +/// Given generic bounds from an impl like: +/// +/// impl ... +/// +/// along with the bindings for the types `A` and `B` (e.g., ``), yields a result like +/// +/// [[Foo for A0, Bar for B0, Qux for B0], [], []] +/// +/// Expects that `generic_bounds` have already been fully substituted, late-bound regions liberated +/// and so forth, so that they are in the same namespace as `type_substs`. pub fn obligations_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, generic_bounds: &ty::GenericBounds<'tcx>, type_substs: &subst::VecPerParamSpace>) -> subst::VecPerParamSpace> { - /*! - * Given generic bounds from an impl like: - * - * impl ... - * - * along with the bindings for the types `A` and `B` (e.g., - * ``), yields a result like - * - * [[Foo for A0, Bar for B0, Qux for B0], [], []] - * - * Expects that `generic_bounds` have already been fully - * substituted, late-bound regions liberated and so forth, - * so that they are in the same namespace as `type_substs`. - */ - util::obligations_for_generics(tcx, cause, 0, generic_bounds, type_substs) } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index d1cc851c41f..f49cd2dd19f 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! See `doc.rs` for high-level documentation */ +//! See `doc.rs` for high-level documentation #![allow(dead_code)] // FIXME -- just temporarily pub use self::MethodMatchResult::*; @@ -201,15 +201,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // is `Vec:Iterable`, but the impl specifies // `impl Iterable for Vec`, than an error would result. + /// Evaluates whether the obligation can be satisfied. Returns an indication of whether the + /// obligation can be satisfied and, if so, by what means. Never affects surrounding typing + /// environment. pub fn select(&mut self, obligation: &Obligation<'tcx>) -> SelectionResult<'tcx, Selection<'tcx>> { - /*! - * Evaluates whether the obligation can be satisfied. Returns - * an indication of whether the obligation can be satisfied - * and, if so, by what means. Never affects surrounding typing - * environment. - */ - debug!("select({})", obligation.repr(self.tcx())); assert!(!obligation.trait_ref.has_escaping_regions()); @@ -253,15 +249,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The result is "true" if the obligation *may* hold and "false" if // we can be sure it does not. + /// Evaluates whether the obligation `obligation` can be satisfied (by any means). pub fn evaluate_obligation(&mut self, obligation: &Obligation<'tcx>) -> bool { - /*! - * Evaluates whether the obligation `obligation` can be - * satisfied (by any means). - */ - debug!("evaluate_obligation({})", obligation.repr(self.tcx())); assert!(!obligation.trait_ref.has_escaping_regions()); @@ -387,17 +379,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + /// Evaluates whether the impl with id `impl_def_id` could be applied to the self type + /// `obligation_self_ty`. This can be used either for trait or inherent impls. pub fn evaluate_impl(&mut self, impl_def_id: ast::DefId, obligation: &Obligation<'tcx>) -> bool { - /*! - * Evaluates whether the impl with id `impl_def_id` could be - * applied to the self type `obligation_self_ty`. This can be - * used either for trait or inherent impls. - */ - debug!("evaluate_impl(impl_def_id={}, obligation={})", impl_def_id.repr(self.tcx()), obligation.repr(self.tcx())); @@ -435,23 +423,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // the body of `evaluate_method_obligation()` for more details on // the algorithm. + /// Determine whether a trait-method is applicable to a receiver of + /// type `rcvr_ty`. *Does not affect the inference state.* + /// + /// - `rcvr_ty` -- type of the receiver + /// - `xform_self_ty` -- transformed self type declared on the method, with `Self` + /// to a fresh type variable + /// - `obligation` -- a reference to the trait where the method is declared, with + /// the input types on the trait replaced with fresh type variables pub fn evaluate_method_obligation(&mut self, rcvr_ty: Ty<'tcx>, xform_self_ty: Ty<'tcx>, obligation: &Obligation<'tcx>) -> MethodMatchResult { - /*! - * Determine whether a trait-method is applicable to a receiver of - * type `rcvr_ty`. *Does not affect the inference state.* - * - * - `rcvr_ty` -- type of the receiver - * - `xform_self_ty` -- transformed self type declared on the method, with `Self` - * to a fresh type variable - * - `obligation` -- a reference to the trait where the method is declared, with - * the input types on the trait replaced with fresh type variables - */ - // Here is the situation. We have a trait method declared (say) like so: // // trait TheTrait { @@ -563,19 +548,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + /// Given the successful result of a method match, this function "confirms" the result, which + /// basically repeats the various matching operations, but outside of any snapshot so that + /// their effects are committed into the inference state. pub fn confirm_method_match(&mut self, rcvr_ty: Ty<'tcx>, xform_self_ty: Ty<'tcx>, obligation: &Obligation<'tcx>, data: MethodMatchedData) { - /*! - * Given the successful result of a method match, this - * function "confirms" the result, which basically repeats the - * various matching operations, but outside of any snapshot so - * that their effects are committed into the inference state. - */ - let is_ok = match data { PreciseMethodMatch => { self.match_method_precise(rcvr_ty, xform_self_ty, obligation).is_ok() @@ -597,17 +578,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + /// Implements the *precise method match* procedure described in + /// `evaluate_method_obligation()`. fn match_method_precise(&mut self, rcvr_ty: Ty<'tcx>, xform_self_ty: Ty<'tcx>, obligation: &Obligation<'tcx>) -> Result<(),()> { - /*! - * Implements the *precise method match* procedure described in - * `evaluate_method_obligation()`. - */ - self.infcx.commit_if_ok(|| { match self.infcx.sub_types(false, infer::RelateSelfType(obligation.cause.span), rcvr_ty, xform_self_ty) { @@ -623,18 +601,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } + /// Assembles a list of potentially applicable impls using the *coercive match* procedure + /// described in `evaluate_method_obligation()`. fn assemble_method_candidates_from_impls(&mut self, rcvr_ty: Ty<'tcx>, xform_self_ty: Ty<'tcx>, obligation: &Obligation<'tcx>) -> Vec { - /*! - * Assembles a list of potentially applicable impls using the - * *coercive match* procedure described in - * `evaluate_method_obligation()`. - */ - let mut candidates = Vec::new(); let all_impls = self.all_impls(obligation.trait_ref.def_id); @@ -650,6 +624,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates } + /// Applies the *coercive match* procedure described in `evaluate_method_obligation()` to a + /// particular impl. fn match_method_coerce(&mut self, impl_def_id: ast::DefId, rcvr_ty: Ty<'tcx>, @@ -657,11 +633,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &Obligation<'tcx>) -> Result, ()> { - /*! - * Applies the *coercive match* procedure described in - * `evaluate_method_obligation()` to a particular impl. - */ - // This is almost always expected to succeed. It // causes the impl's self-type etc to be unified with // the type variable that is shared between @@ -683,6 +654,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(substs) } + /// A version of `winnow_impl` applicable to coerice method matching. This is basically the + /// same as `winnow_impl` but it uses the method matching procedure and is specific to impls. fn winnow_method_impl(&mut self, impl_def_id: ast::DefId, rcvr_ty: Ty<'tcx>, @@ -690,13 +663,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &Obligation<'tcx>) -> bool { - /*! - * A version of `winnow_impl` applicable to coerice method - * matching. This is basically the same as `winnow_impl` but - * it uses the method matching procedure and is specific to - * impls. - */ - debug!("winnow_method_impl: impl_def_id={} rcvr_ty={} xform_self_ty={} obligation={}", impl_def_id.repr(self.tcx()), rcvr_ty.repr(self.tcx()), @@ -962,19 +928,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(candidates) } + /// Given an obligation like ``, search the obligations that the caller + /// supplied to find out whether it is listed among them. + /// + /// Never affects inference environment. fn assemble_candidates_from_caller_bounds(&mut self, obligation: &Obligation<'tcx>, candidates: &mut CandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - /*! - * Given an obligation like ``, search the obligations - * that the caller supplied to find out whether it is listed among - * them. - * - * Never affects inference environment. - */ - debug!("assemble_candidates_from_caller_bounds({})", obligation.repr(self.tcx())); @@ -1002,22 +964,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(()) } + /// Check for the artificial impl that the compiler will create for an obligation like `X : + /// FnMut<..>` where `X` is an unboxed closure type. + /// + /// Note: the type parameters on an unboxed closure candidate are modeled as *output* type + /// parameters and hence do not affect whether this trait is a match or not. They will be + /// unified during the confirmation step. fn assemble_unboxed_candidates(&mut self, obligation: &Obligation<'tcx>, candidates: &mut CandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - /*! - * Check for the artificial impl that the compiler will create - * for an obligation like `X : FnMut<..>` where `X` is an - * unboxed closure type. - * - * Note: the type parameters on an unboxed closure candidate - * are modeled as *output* type parameters and hence do not - * affect whether this trait is a match or not. They will be - * unified during the confirmation step. - */ - let tcx = self.tcx(); let kind = if Some(obligation.trait_ref.def_id) == tcx.lang_items.fn_trait() { ty::FnUnboxedClosureKind @@ -1060,15 +1017,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(()) } + /// Search for impls that might apply to `obligation`. fn assemble_candidates_from_impls(&mut self, obligation: &Obligation<'tcx>, candidates: &mut CandidateSet<'tcx>) -> Result<(), SelectionError<'tcx>> { - /*! - * Search for impls that might apply to `obligation`. - */ - let all_impls = self.all_impls(obligation.trait_ref.def_id); for &impl_def_id in all_impls.iter() { self.infcx.probe(|| { @@ -1092,17 +1046,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // attempt to evaluate recursive bounds to see if they are // satisfied. + /// Further evaluate `candidate` to decide whether all type parameters match and whether nested + /// obligations are met. Returns true if `candidate` remains viable after this further + /// scrutiny. fn winnow_candidate<'o>(&mut self, stack: &ObligationStack<'o, 'tcx>, candidate: &Candidate<'tcx>) -> EvaluationResult { - /*! - * Further evaluate `candidate` to decide whether all type parameters match - * and whether nested obligations are met. Returns true if `candidate` remains - * viable after this further scrutiny. - */ - debug!("winnow_candidate: candidate={}", candidate.repr(self.tcx())); self.infcx.probe(|| { let candidate = (*candidate).clone(); @@ -1129,37 +1080,35 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { result } + /// Returns true if `candidate_i` should be dropped in favor of `candidate_j`. + /// + /// This is generally true if either: + /// - candidate i and candidate j are equivalent; or, + /// - candidate i is a conrete impl and candidate j is a where clause bound, + /// and the concrete impl is applicable to the types in the where clause bound. + /// + /// The last case refers to cases where there are blanket impls (often conditional + /// blanket impls) as well as a where clause. This can come down to one of two cases: + /// + /// - The impl is truly unconditional (it has no where clauses + /// of its own), in which case the where clause is + /// unnecessary, because coherence requires that we would + /// pick that particular impl anyhow (at least so long as we + /// don't have specialization). + /// + /// - The impl is conditional, in which case we may not have winnowed it out + /// because we don't know if the conditions apply, but the where clause is basically + /// telling us taht there is some impl, though not necessarily the one we see. + /// + /// In both cases we prefer to take the where clause, which is + /// essentially harmless. See issue #18453 for more details of + /// a case where doing the opposite caused us harm. fn candidate_should_be_dropped_in_favor_of<'o>(&mut self, stack: &ObligationStack<'o, 'tcx>, candidate_i: &Candidate<'tcx>, candidate_j: &Candidate<'tcx>) -> bool { - /*! - * Returns true if `candidate_i` should be dropped in favor of `candidate_j`. - * This is generally true if either: - * - candidate i and candidate j are equivalent; or, - * - candidate i is a conrete impl and candidate j is a where clause bound, - * and the concrete impl is applicable to the types in the where clause bound. - * - * The last case refers to cases where there are blanket impls (often conditional - * blanket impls) as well as a where clause. This can come down to one of two cases: - * - * - The impl is truly unconditional (it has no where clauses - * of its own), in which case the where clause is - * unnecessary, because coherence requires that we would - * pick that particular impl anyhow (at least so long as we - * don't have specialization). - * - * - The impl is conditional, in which case we may not have winnowed it out - * because we don't know if the conditions apply, but the where clause is basically - * telling us taht there is some impl, though not necessarily the one we see. - * - * In both cases we prefer to take the where clause, which is - * essentially harmless. See issue #18453 for more details of - * a case where doing the opposite caused us harm. - */ - match (candidate_i, candidate_j) { (&ImplCandidate(impl_def_id), &ParamCandidate(ref vt)) => { debug!("Considering whether to drop param {} in favor of impl {}", @@ -1848,26 +1797,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + /// Determines whether the self type declared against + /// `impl_def_id` matches `obligation_self_ty`. If successful, + /// returns the substitutions used to make them match. See + /// `match_impl()`. For example, if `impl_def_id` is declared + /// as: + /// + /// impl Foo for ~T { ... } + /// + /// and `obligation_self_ty` is `int`, we'd back an `Err(_)` + /// result. But if `obligation_self_ty` were `~int`, we'd get + /// back `Ok(T=int)`. fn match_inherent_impl(&mut self, impl_def_id: ast::DefId, obligation_cause: ObligationCause, obligation_self_ty: Ty<'tcx>) -> Result,()> { - /*! - * Determines whether the self type declared against - * `impl_def_id` matches `obligation_self_ty`. If successful, - * returns the substitutions used to make them match. See - * `match_impl()`. For example, if `impl_def_id` is declared - * as: - * - * impl Foo for ~T { ... } - * - * and `obligation_self_ty` is `int`, we'd back an `Err(_)` - * result. But if `obligation_self_ty` were `~int`, we'd get - * back `Ok(T=int)`. - */ - // Create fresh type variables for each type parameter declared // on the impl etc. let impl_substs = util::fresh_substs_for_impl(self.infcx, @@ -1928,6 +1874,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // the output type parameters from the obligation with those found // on the impl/bound, which may yield type errors. + /// Relates the output type parameters from an impl to the + /// trait. This may lead to type errors. The confirmation step + /// is separated from the main match procedure because these + /// type errors do not cause us to select another impl. + /// + /// As an example, consider matching the obligation + /// `Iterator for Elems` using the following impl: + /// + /// impl Iterator for Elems { ... } + /// + /// The match phase will succeed with substitution `T=int`. + /// The confirm step will then try to unify `int` and `char` + /// and yield an error. fn confirm_impl_vtable(&mut self, impl_def_id: ast::DefId, obligation_cause: ObligationCause<'tcx>, @@ -1935,22 +1894,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { substs: &Substs<'tcx>) -> Result<(), SelectionError<'tcx>> { - /*! - * Relates the output type parameters from an impl to the - * trait. This may lead to type errors. The confirmation step - * is separated from the main match procedure because these - * type errors do not cause us to select another impl. - * - * As an example, consider matching the obligation - * `Iterator for Elems` using the following impl: - * - * impl Iterator for Elems { ... } - * - * The match phase will succeed with substitution `T=int`. - * The confirm step will then try to unify `int` and `char` - * and yield an error. - */ - let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap(); let impl_trait_ref = impl_trait_ref.subst(self.tcx(), @@ -1958,38 +1901,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.confirm(obligation_cause, obligation_trait_ref, impl_trait_ref) } + /// After we have determined which impl applies, and with what substitutions, there is one last + /// step. We have to go back and relate the "output" type parameters from the obligation to the + /// types that are specified in the impl. + /// + /// For example, imagine we have: + /// + /// impl Iterator for Vec { ... } + /// + /// and our obligation is `Iterator for Vec` (note the mismatch in the obligation + /// types). Up until this step, no error would be reported: the self type is `Vec`, and + /// that matches `Vec` with the substitution `T=int`. At this stage, we could then go and + /// check that the type parameters to the `Iterator` trait match. (In terms of the parameters, + /// the `expected_trait_ref` here would be `Iterator for Vec`, and the + /// `obligation_trait_ref` would be `Iterator for Vec`. + /// + /// Note that this checking occurs *after* the impl has selected, because these output type + /// parameters should not affect the selection of the impl. Therefore, if there is a mismatch, + /// we report an error to the user. fn confirm(&mut self, obligation_cause: ObligationCause, obligation_trait_ref: Rc>, expected_trait_ref: Rc>) -> Result<(), SelectionError<'tcx>> { - /*! - * After we have determined which impl applies, and with what - * substitutions, there is one last step. We have to go back - * and relate the "output" type parameters from the obligation - * to the types that are specified in the impl. - * - * For example, imagine we have: - * - * impl Iterator for Vec { ... } - * - * and our obligation is `Iterator for Vec` (note - * the mismatch in the obligation types). Up until this step, - * no error would be reported: the self type is `Vec`, - * and that matches `Vec` with the substitution `T=int`. - * At this stage, we could then go and check that the type - * parameters to the `Iterator` trait match. - * (In terms of the parameters, the `expected_trait_ref` - * here would be `Iterator for Vec`, and the - * `obligation_trait_ref` would be `Iterator for Vec`. - * - * Note that this checking occurs *after* the impl has - * selected, because these output type parameters should not - * affect the selection of the impl. Therefore, if there is a - * mismatch, we report an error to the user. - */ - let origin = infer::RelateOutputImplTypes(obligation_cause.span); let obligation_trait_ref = obligation_trait_ref.clone(); @@ -2019,11 +1954,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + /// Returns set of all impls for a given trait. fn all_impls(&self, trait_def_id: ast::DefId) -> Vec { - /*! - * Returns set of all impls for a given trait. - */ - ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_def_id); match self.tcx().trait_impls.borrow().get(&trait_def_id) { diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index ec49d501056..b9e694ff4e2 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -42,22 +42,18 @@ pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, trait_ref: Rc>) -> Supertraits<'cx, 'tcx> { - /*! - * Returns an iterator over the trait reference `T` and all of its - * supertrait references. May contain duplicates. In general - * the ordering is not defined. - * - * Example: - * - * ``` - * trait Foo { ... } - * trait Bar : Foo { ... } - * trait Baz : Bar+Foo { ... } - * ``` - * - * `supertraits(Baz)` yields `[Baz, Bar, Foo, Foo]` in some order. - */ - + /// Returns an iterator over the trait reference `T` and all of its supertrait references. May + /// contain duplicates. In general the ordering is not defined. + /// + /// Example: + /// + /// ``` + /// trait Foo { ... } + /// trait Bar : Foo { ... } + /// trait Baz : Bar+Foo { ... } + /// ``` + /// + /// `supertraits(Baz)` yields `[Baz, Bar, Foo, Foo]` in some order. transitive_bounds(tcx, &[trait_ref]) } @@ -97,12 +93,8 @@ impl<'cx, 'tcx> Supertraits<'cx, 'tcx> { self.stack.push(entry); } + /// Returns the path taken through the trait supertraits to reach the current point. pub fn indices(&self) -> Vec { - /*! - * Returns the path taken through the trait supertraits to - * reach the current point. - */ - self.stack.iter().map(|e| e.position).collect() } } @@ -171,6 +163,7 @@ impl<'tcx> fmt::Show for VtableParamData<'tcx> { } } +/// See `super::obligations_for_generics` pub fn obligations_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, recursion_depth: uint, @@ -178,7 +171,6 @@ pub fn obligations_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, type_substs: &VecPerParamSpace>) -> VecPerParamSpace> { - /*! See `super::obligations_for_generics` */ debug!("obligations_for_generics(generic_bounds={}, type_substs={})", generic_bounds.repr(tcx), type_substs.repr(tcx)); @@ -272,20 +264,15 @@ pub fn obligation_for_builtin_bound<'tcx>( } } +/// Starting from a caller obligation `caller_bound` (which has coordinates `space`/`i` in the list +/// of caller obligations), search through the trait and supertraits to find one where `test(d)` is +/// true, where `d` is the def-id of the trait/supertrait. If any is found, return `Some(p)` where +/// `p` is the path to that trait/supertrait. Else `None`. pub fn search_trait_and_supertraits_from_bound<'tcx>(tcx: &ty::ctxt<'tcx>, caller_bound: Rc>, test: |ast::DefId| -> bool) -> Option> { - /*! - * Starting from a caller obligation `caller_bound` (which has - * coordinates `space`/`i` in the list of caller obligations), - * search through the trait and supertraits to find one where - * `test(d)` is true, where `d` is the def-id of the - * trait/supertrait. If any is found, return `Some(p)` where `p` - * is the path to that trait/supertrait. Else `None`. - */ - for bound in transitive_bounds(tcx, &[caller_bound]) { if test(bound.def_id) { let vtable_param = VtableParamData { bound: bound }; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2c8465e62d7..b79bce62f0b 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -671,39 +671,29 @@ pub fn type_has_late_bound_regions(ty: Ty) -> bool { ty.flags.intersects(HAS_RE_LATE_BOUND) } +/// An "escaping region" is a bound region whose binder is not part of `t`. +/// +/// So, for example, consider a type like the following, which has two binders: +/// +/// for<'a> fn(x: for<'b> fn(&'a int, &'b int)) +/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope +/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope +/// +/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the +/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner +/// fn type*, that type has an escaping region: `'a`. +/// +/// Note that what I'm calling an "escaping region" is often just called a "free region". However, +/// we already use the term "free region". It refers to the regions that we use to represent bound +/// regions on a fn definition while we are typechecking its body. +/// +/// To clarify, conceptually there is no particular difference between an "escaping" region and a +/// "free" region. However, there is a big difference in practice. Basically, when "entering" a +/// binding level, one is generally required to do some sort of processing to a bound region, such +/// as replacing it with a fresh/skolemized region, or making an entry in the environment to +/// represent the scope to which it is attached, etc. An escaping region represents a bound region +/// for which this processing has not yet been done. pub fn type_has_escaping_regions(ty: Ty) -> bool { - /*! - * An "escaping region" is a bound region whose binder is not part of `t`. - * - * So, for example, consider a type like the following, which has two - * binders: - * - * for<'a> fn(x: for<'b> fn(&'a int, &'b int)) - * ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope - * ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope - * - * This type has *bound regions* (`'a`, `'b`), but it does not - * have escaping regions, because the binders of both `'a` and - * `'b` are part of the type itself. However, if we consider the - * *inner fn type*, that type has an escaping region: `'a`. - * - * Note that what I'm calling an "escaping region" is often just - * called a "free region". However, we already use the term "free - * region". It refers to the regions that we use to represent - * bound regions on a fn definition while we are typechecking its - * body. - * - * To clarify, conceptually there is no particular difference - * between an "escaping" region and a "free" region. However, - * there is a big difference in practice. Basically, when - * "entering" a binding level, one is generally required to do - * some sort of processing to a bound region, such as replacing it - * with a fresh/skolemized region, or making an entry in the - * environment to represent the scope to which it is attached, - * etc. An escaping region represents a bound region for which - * this processing has not yet been done. - */ - type_escapes_depth(ty, 0) } @@ -1248,11 +1238,8 @@ pub fn all_builtin_bounds() -> BuiltinBounds { set } +/// An existential bound that does not implement any traits. pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds { - /*! - * An existential bound that does not implement any traits. - */ - ty::ExistentialBounds { region_bound: r, builtin_bounds: empty_builtin_bounds() } } @@ -1834,12 +1821,9 @@ impl FlagComputation { } } + /// Adds the flags/depth from a set of types that appear within the current type, but within a + /// region binder. fn add_bound_computation(&mut self, computation: &FlagComputation) { - /*! - * Adds the flags/depth from a set of types that appear within - * the current type, but within a region binder. - */ - self.add_flags(computation.flags); // The types that contributed to `computation` occured within @@ -2575,38 +2559,26 @@ impl TypeContents { self.intersects(TC::NeedsDrop) } + /// Includes only those bits that still apply when indirected through a `Box` pointer pub fn owned_pointer(&self) -> TypeContents { - /*! - * Includes only those bits that still apply - * when indirected through a `Box` pointer - */ TC::OwnsOwned | ( *self & (TC::OwnsAll | TC::ReachesAll)) } + /// Includes only those bits that still apply when indirected through a reference (`&`) pub fn reference(&self, bits: TypeContents) -> TypeContents { - /*! - * Includes only those bits that still apply - * when indirected through a reference (`&`) - */ bits | ( *self & TC::ReachesAll) } + /// Includes only those bits that still apply when indirected through a managed pointer (`@`) pub fn managed_pointer(&self) -> TypeContents { - /*! - * Includes only those bits that still apply - * when indirected through a managed pointer (`@`) - */ TC::Managed | ( *self & TC::ReachesAll) } + /// Includes only those bits that still apply when indirected through an unsafe pointer (`*`) pub fn unsafe_pointer(&self) -> TypeContents { - /*! - * Includes only those bits that still apply - * when indirected through an unsafe pointer (`*`) - */ *self & TC::ReachesAll } @@ -2883,14 +2855,10 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { } } + /// Type contents due to containing a reference with the region `region` and borrow kind `bk` fn borrowed_contents(region: ty::Region, mutbl: ast::Mutability) -> TypeContents { - /*! - * Type contents due to containing a reference - * with the region `region` and borrow kind `bk` - */ - let b = match mutbl { ast::MutMutable => TC::ReachesMutable | TC::OwnsAffine, ast::MutImmutable => TC::None, @@ -3648,20 +3616,16 @@ pub fn expr_ty_opt<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Option> return node_id_to_type_opt(cx, expr.id); } +/// Returns the type of `expr`, considering any `AutoAdjustment` +/// entry recorded for that expression. +/// +/// It would almost certainly be better to store the adjusted ty in with +/// the `AutoAdjustment`, but I opted not to do this because it would +/// require serializing and deserializing the type and, although that's not +/// hard to do, I just hate that code so much I didn't want to touch it +/// unless it was to fix it properly, which seemed a distraction from the +/// task at hand! -nmatsakis pub fn expr_ty_adjusted<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> { - /*! - * - * Returns the type of `expr`, considering any `AutoAdjustment` - * entry recorded for that expression. - * - * It would almost certainly be better to store the adjusted ty in with - * the `AutoAdjustment`, but I opted not to do this because it would - * require serializing and deserializing the type and, although that's not - * hard to do, I just hate that code so much I didn't want to touch it - * unless it was to fix it properly, which seemed a distraction from the - * task at hand! -nmatsakis - */ - adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr), cx.adjustments.borrow().get(&expr.id), |method_call| cx.method_map.borrow().get(&method_call).map(|method| method.ty)) @@ -3707,6 +3671,7 @@ pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString { } } +/// See `expr_ty_adjusted` pub fn adjust_ty<'tcx>(cx: &ctxt<'tcx>, span: Span, expr_id: ast::NodeId, @@ -3714,7 +3679,6 @@ pub fn adjust_ty<'tcx>(cx: &ctxt<'tcx>, adjustment: Option<&AutoAdjustment<'tcx>>, method_type: |typeck::MethodCall| -> Option>) -> Ty<'tcx> { - /*! See `expr_ty_adjusted` */ match unadjusted_ty.sty { ty_err => return unadjusted_ty, @@ -4128,16 +4092,11 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String { } } +/// Explains the source of a type err in a short, human readable way. This is meant to be placed +/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()` +/// afterwards to present additional details, particularly when it comes to lifetime-related +/// errors. pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String { - /*! - * - * Explains the source of a type err in a short, - * human readable way. This is meant to be placed in - * parentheses after some larger message. You should - * also invoke `note_and_explain_type_err()` afterwards - * to present additional details, particularly when - * it comes to lifetime-related errors. */ - fn tstore_to_closure(s: &TraitStore) -> String { match s { &UniqTraitStore => "proc".to_string(), @@ -4352,21 +4311,16 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) } } +/// Helper for looking things up in the various maps that are populated during typeck::collect +/// (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of these share the pattern that if the +/// id is local, it should have been loaded into the map by the `typeck::collect` phase. If the +/// def-id is external, then we have to go consult the crate loading code (and cache the result for +/// the future). fn lookup_locally_or_in_crate_store( descr: &str, def_id: ast::DefId, map: &mut DefIdMap, load_external: || -> V) -> V { - /*! - * Helper for looking things up in the various maps - * that are populated during typeck::collect (e.g., - * `cx.impl_or_trait_items`, `cx.tcache`, etc). All of these share - * the pattern that if the id is local, it should have - * been loaded into the map by the `typeck::collect` phase. - * If the def-id is external, then we have to go consult - * the crate loading code (and cache the result for the future). - */ - match map.get(&def_id).cloned() { Some(v) => { return v; } None => { } @@ -5238,19 +5192,16 @@ pub fn each_bound_trait_and_supertraits<'tcx>(tcx: &ctxt<'tcx>, return true; } +/// Given a type which must meet the builtin bounds and trait bounds, returns a set of lifetimes +/// which the type must outlive. +/// +/// Requires that trait definitions have been processed. pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>, region_bounds: &[ty::Region], builtin_bounds: BuiltinBounds, trait_bounds: &[Rc>]) -> Vec { - /*! - * Given a type which must meet the builtin bounds and trait - * bounds, returns a set of lifetimes which the type must outlive. - * - * Requires that trait definitions have been processed. - */ - let mut all_bounds = Vec::new(); debug!("required_region_bounds(builtin_bounds={}, trait_bounds={})", @@ -5636,13 +5587,9 @@ impl Variance { } } +/// Construct a parameter environment suitable for static contexts or other contexts where there +/// are no free type/lifetime parameters in scope. pub fn empty_parameter_environment<'tcx>() -> ParameterEnvironment<'tcx> { - /*! - * Construct a parameter environment suitable for static contexts - * or other contexts where there are no free type/lifetime - * parameters in scope. - */ - ty::ParameterEnvironment { free_substs: Substs::empty(), bounds: VecPerParamSpace::empty(), caller_obligations: VecPerParamSpace::empty(), @@ -5650,6 +5597,7 @@ pub fn empty_parameter_environment<'tcx>() -> ParameterEnvironment<'tcx> { selection_cache: traits::SelectionCache::new(), } } +/// See `ParameterEnvironment` struct def'n for details pub fn construct_parameter_environment<'tcx>( tcx: &ctxt<'tcx>, span: Span, @@ -5657,7 +5605,6 @@ pub fn construct_parameter_environment<'tcx>( free_id: ast::NodeId) -> ParameterEnvironment<'tcx> { - /*! See `ParameterEnvironment` struct def'n for details */ // // Construct the free substs. @@ -5786,15 +5733,11 @@ impl BorrowKind { } } + /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow + /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a + /// mutability that is stronger than necessary so that it at least *would permit* the borrow in + /// question. pub fn to_mutbl_lossy(self) -> ast::Mutability { - /*! - * Returns a mutability `m` such that an `&m T` pointer could - * be used to obtain this borrow kind. Because borrow kinds - * are richer than mutabilities, we sometimes have to pick a - * mutability that is stronger than necessary so that it at - * least *would permit* the borrow in question. - */ - match self { MutBorrow => ast::MutMutable, ImmBorrow => ast::MutImmutable, @@ -5959,6 +5902,8 @@ impl<'tcx> AutoDerefRef<'tcx> { } } +/// Replace any late-bound regions bound in `value` with free variants attached to scope-id +/// `scope_id`. pub fn liberate_late_bound_regions<'tcx, HR>( tcx: &ty::ctxt<'tcx>, scope: region::CodeExtent, @@ -5966,31 +5911,23 @@ pub fn liberate_late_bound_regions<'tcx, HR>( -> HR where HR : HigherRankedFoldable<'tcx> { - /*! - * Replace any late-bound regions bound in `value` with free variants - * attached to scope-id `scope_id`. - */ - replace_late_bound_regions( tcx, value, |br, _| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0 } +/// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also +/// method lookup and a few other places where precise region relationships are not required. pub fn erase_late_bound_regions<'tcx, HR>( tcx: &ty::ctxt<'tcx>, value: &HR) -> HR where HR : HigherRankedFoldable<'tcx> { - /*! - * Replace any late-bound regions bound in `value` with `'static`. - * Useful in trans but also method lookup and a few other places - * where precise region relationships are not required. - */ - replace_late_bound_regions(tcx, value, |_, _| ty::ReStatic).0 } +/// Replaces the late-bound-regions in `value` that are bound by `value`. pub fn replace_late_bound_regions<'tcx, HR>( tcx: &ty::ctxt<'tcx>, value: &HR, @@ -5998,10 +5935,6 @@ pub fn replace_late_bound_regions<'tcx, HR>( -> (HR, FnvHashMap) where HR : HigherRankedFoldable<'tcx> { - /*! - * Replaces the late-bound-regions in `value` that are bound by `value`. - */ - debug!("replace_late_bound_regions({})", value.repr(tcx)); let mut map = FnvHashMap::new(); diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 913919fe774..0d7b9b99c57 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -8,33 +8,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Generalized type folding mechanism. The setup is a bit convoluted - * but allows for convenient usage. Let T be an instance of some - * "foldable type" (one which implements `TypeFoldable`) and F be an - * instance of a "folder" (a type which implements `TypeFolder`). Then - * the setup is intended to be: - * - * T.fold_with(F) --calls--> F.fold_T(T) --calls--> super_fold_T(F, T) - * - * This way, when you define a new folder F, you can override - * `fold_T()` to customize the behavior, and invoke `super_fold_T()` - * to get the original behavior. Meanwhile, to actually fold - * something, you can just write `T.fold_with(F)`, which is - * convenient. (Note that `fold_with` will also transparently handle - * things like a `Vec` where T is foldable and so on.) - * - * In this ideal setup, the only function that actually *does* - * anything is `super_fold_T`, which traverses the type `T`. Moreover, - * `super_fold_T` should only ever call `T.fold_with()`. - * - * In some cases, we follow a degenerate pattern where we do not have - * a `fold_T` nor `super_fold_T` method. Instead, `T.fold_with` - * traverses the structure directly. This is suboptimal because the - * behavior cannot be overriden, but it's much less work to implement. - * If you ever *do* need an override that doesn't exist, it's not hard - * to convert the degenerate pattern into the proper thing. - */ +//! Generalized type folding mechanism. The setup is a bit convoluted +//! but allows for convenient usage. Let T be an instance of some +//! "foldable type" (one which implements `TypeFoldable`) and F be an +//! instance of a "folder" (a type which implements `TypeFolder`). Then +//! the setup is intended to be: +//! +//! T.fold_with(F) --calls--> F.fold_T(T) --calls--> super_fold_T(F, T) +//! +//! This way, when you define a new folder F, you can override +//! `fold_T()` to customize the behavior, and invoke `super_fold_T()` +//! to get the original behavior. Meanwhile, to actually fold +//! something, you can just write `T.fold_with(F)`, which is +//! convenient. (Note that `fold_with` will also transparently handle +//! things like a `Vec` where T is foldable and so on.) +//! +//! In this ideal setup, the only function that actually *does* +//! anything is `super_fold_T`, which traverses the type `T`. Moreover, +//! `super_fold_T` should only ever call `T.fold_with()`. +//! +//! In some cases, we follow a degenerate pattern where we do not have +//! a `fold_T` nor `super_fold_T` method. Instead, `T.fold_with` +//! traverses the structure directly. This is suboptimal because the +//! behavior cannot be overriden, but it's much less work to implement. +//! If you ever *do* need an override that doesn't exist, it's not hard +//! to convert the degenerate pattern into the proper thing. use middle::subst; use middle::subst::VecPerParamSpace; diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index fd5b1bd4793..5dfe3fc3a58 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -8,46 +8,44 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Conversion from AST representation of types to the ty.rs - * representation. The main routine here is `ast_ty_to_ty()`: each use - * is parameterized by an instance of `AstConv` and a `RegionScope`. - * - * The parameterization of `ast_ty_to_ty()` is because it behaves - * somewhat differently during the collect and check phases, - * particularly with respect to looking up the types of top-level - * items. In the collect phase, the crate context is used as the - * `AstConv` instance; in this phase, the `get_item_ty()` function - * triggers a recursive call to `ty_of_item()` (note that - * `ast_ty_to_ty()` will detect recursive types and report an error). - * In the check phase, when the FnCtxt is used as the `AstConv`, - * `get_item_ty()` just looks up the item type in `tcx.tcache`. - * - * The `RegionScope` trait controls what happens when the user does - * not specify a region in some location where a region is required - * (e.g., if the user writes `&Foo` as a type rather than `&'a Foo`). - * See the `rscope` module for more details. - * - * Unlike the `AstConv` trait, the region scope can change as we descend - * the type. This is to accommodate the fact that (a) fn types are binding - * scopes and (b) the default region may change. To understand case (a), - * consider something like: - * - * type foo = { x: &a.int, y: |&a.int| } - * - * The type of `x` is an error because there is no region `a` in scope. - * In the type of `y`, however, region `a` is considered a bound region - * as it does not already appear in scope. - * - * Case (b) says that if you have a type: - * type foo<'a> = ...; - * type bar = fn(&foo, &a.foo) - * The fully expanded version of type bar is: - * type bar = fn(&'foo &, &a.foo<'a>) - * Note that the self region for the `foo` defaulted to `&` in the first - * case but `&a` in the second. Basically, defaults that appear inside - * an rptr (`&r.T`) use the region `r` that appears in the rptr. - */ +//! Conversion from AST representation of types to the ty.rs +//! representation. The main routine here is `ast_ty_to_ty()`: each use +//! is parameterized by an instance of `AstConv` and a `RegionScope`. +//! +//! The parameterization of `ast_ty_to_ty()` is because it behaves +//! somewhat differently during the collect and check phases, +//! particularly with respect to looking up the types of top-level +//! items. In the collect phase, the crate context is used as the +//! `AstConv` instance; in this phase, the `get_item_ty()` function +//! triggers a recursive call to `ty_of_item()` (note that +//! `ast_ty_to_ty()` will detect recursive types and report an error). +//! In the check phase, when the FnCtxt is used as the `AstConv`, +//! `get_item_ty()` just looks up the item type in `tcx.tcache`. +//! +//! The `RegionScope` trait controls what happens when the user does +//! not specify a region in some location where a region is required +//! (e.g., if the user writes `&Foo` as a type rather than `&'a Foo`). +//! See the `rscope` module for more details. +//! +//! Unlike the `AstConv` trait, the region scope can change as we descend +//! the type. This is to accommodate the fact that (a) fn types are binding +//! scopes and (b) the default region may change. To understand case (a), +//! consider something like: +//! +//! type foo = { x: &a.int, y: |&a.int| } +//! +//! The type of `x` is an error because there is no region `a` in scope. +//! In the type of `y`, however, region `a` is considered a bound region +//! as it does not already appear in scope. +//! +//! Case (b) says that if you have a type: +//! type foo<'a> = ...; +//! type bar = fn(&foo, &a.foo) +//! The fully expanded version of type bar is: +//! type bar = fn(&'foo &, &a.foo<'a>) +//! Note that the self region for the `foo` defaulted to `&` in the first +//! case but `&a` in the second. Basically, defaults that appear inside +//! an rptr (`&r.T`) use the region `r` that appears in the rptr. use middle::const_eval; use middle::def; use middle::resolve_lifetime as rl; @@ -201,6 +199,8 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( r } +/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`, +/// returns an appropriate set of substitutions for this particular reference to `I`. fn ast_path_substs_for_ty<'tcx,AC,RS>( this: &AC, rscope: &RS, @@ -211,12 +211,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>( -> Substs<'tcx> where AC: AstConv<'tcx>, RS: RegionScope { - /*! - * Given a path `path` that refers to an item `I` with the - * declared generics `decl_generics`, returns an appropriate - * set of substitutions for this particular reference to `I`. - */ - let tcx = this.tcx(); // ast_path_substs() is only called to convert paths that are @@ -422,6 +416,9 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>( instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty) } +/// Instantiates the path for the given trait reference, assuming that it's bound to a valid trait +/// type. Returns the def_id for the defining trait. Fails if the type is a type other than a trait +/// type. pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC, rscope: &RS, ast_trait_ref: &ast::TraitRef, @@ -430,12 +427,6 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC, where AC: AstConv<'tcx>, RS: RegionScope { - /*! - * Instantiates the path for the given trait reference, assuming that - * it's bound to a valid trait type. Returns the def_id for the defining - * trait. Fails if the type is a type other than a trait type. - */ - match lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) { @@ -1318,6 +1309,10 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( } } +/// Given an existential type like `Foo+'a+Bar`, this routine converts the `'a` and `Bar` intos an +/// `ExistentialBounds` struct. The `main_trait_refs` argument specifies the `Foo` -- it is absent +/// for closures. Eventually this should all be normalized, I think, so that there is no "main +/// trait ref" and instead we just have a flat list of bounds as the existential type. pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( this: &AC, rscope: &RS, @@ -1326,16 +1321,6 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( ast_bounds: &[ast::TyParamBound]) -> ty::ExistentialBounds { - /*! - * Given an existential type like `Foo+'a+Bar`, this routine - * converts the `'a` and `Bar` intos an `ExistentialBounds` - * struct. The `main_trait_refs` argument specifies the `Foo` -- - * it is absent for closures. Eventually this should all be - * normalized, I think, so that there is no "main trait ref" and - * instead we just have a flat list of bounds as the existential - * type. - */ - let ast_bound_refs: Vec<&ast::TyParamBound> = ast_bounds.iter().collect(); @@ -1432,6 +1417,10 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( } } +/// Given the bounds on a type parameter / existential type, determines what single region bound +/// (if any) we can use to summarize this type. The basic idea is that we will use the bound the +/// user provided, if they provided one, and otherwise search the supertypes of trait bounds for +/// region bounds. It may be that we can derive no bound at all, in which case we return `None`. pub fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, span: Span, builtin_bounds: ty::BuiltinBounds, @@ -1439,16 +1428,6 @@ pub fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, trait_bounds: &[Rc>]) -> Option { - /*! - * Given the bounds on a type parameter / existential type, - * determines what single region bound (if any) we can use to - * summarize this type. The basic idea is that we will use the - * bound the user provided, if they provided one, and otherwise - * search the supertypes of trait bounds for region bounds. It may - * be that we can derive no bound at all, in which case we return - * `None`. - */ - if region_bounds.len() > 1 { tcx.sess.span_err( region_bounds[1].span, @@ -1495,6 +1474,9 @@ pub fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, return Some(r); } +/// A version of `compute_opt_region_bound` for use where some region bound is required +/// (existential types, basically). Reports an error if no region bound can be derived and we are +/// in an `rscope` that does not provide a default. fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( this: &AC, rscope: &RS, @@ -1504,13 +1486,6 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( trait_bounds: &[Rc>]) -> ty::Region { - /*! - * A version of `compute_opt_region_bound` for use where some - * region bound is required (existential types, - * basically). Reports an error if no region bound can be derived - * and we are in an `rscope` that does not provide a default. - */ - match compute_opt_region_bound(this.tcx(), span, builtin_bounds, region_bounds, trait_bounds) { Some(r) => r, @@ -1534,17 +1509,13 @@ pub struct PartitionedBounds<'a> { pub region_bounds: Vec<&'a ast::Lifetime>, } +/// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc), +/// general trait bounds, and region bounds. pub fn partition_bounds<'a>(tcx: &ty::ctxt, _span: Span, ast_bounds: &'a [&ast::TyParamBound]) -> PartitionedBounds<'a> { - /*! - * Divides a list of bounds from the AST into three groups: - * builtin bounds (Copy, Sized etc), general trait bounds, - * and region bounds. - */ - let mut builtin_bounds = ty::empty_builtin_bounds(); let mut region_bounds = Vec::new(); let mut trait_bounds = Vec::new(); diff --git a/src/librustc/middle/typeck/check/closure.rs b/src/librustc/middle/typeck/check/closure.rs index 51636f00c39..0a93b3a5ec7 100644 --- a/src/librustc/middle/typeck/check/closure.rs +++ b/src/librustc/middle/typeck/check/closure.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Code for type-checking closure expressions. - */ +//! Code for type-checking closure expressions. use super::check_fn; use super::{Expectation, ExpectCastableToType, ExpectHasType, NoExpectation}; diff --git a/src/librustc/middle/typeck/check/method/confirm.rs b/src/librustc/middle/typeck/check/method/confirm.rs index 5bcd96e66ef..e866627be3d 100644 --- a/src/librustc/middle/typeck/check/method/confirm.rs +++ b/src/librustc/middle/typeck/check/method/confirm.rs @@ -189,22 +189,17 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { /////////////////////////////////////////////////////////////////////////// // + /// Returns a set of substitutions for the method *receiver* where all type and region + /// parameters are instantiated with fresh variables. This substitution does not include any + /// parameters declared on the method itself. + /// + /// Note that this substitution may include late-bound regions from the impl level. If so, + /// these are instantiated later in the `instantiate_method_sig` routine. fn fresh_receiver_substs(&mut self, self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) -> (subst::Substs<'tcx>, MethodOrigin<'tcx>) { - /*! - * Returns a set of substitutions for the method *receiver* - * where all type and region parameters are instantiated with - * fresh variables. This substitution does not include any - * parameters declared on the method itself. - * - * Note that this substitution may include late-bound regions - * from the impl level. If so, these are instantiated later in - * the `instantiate_method_sig` routine. - */ - match pick.kind { probe::InherentImplPick(impl_def_id) => { assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(), @@ -478,14 +473,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { /////////////////////////////////////////////////////////////////////////// // RECONCILIATION + /// When we select a method with an `&mut self` receiver, we have to go convert any + /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut` + /// respectively. fn fixup_derefs_on_method_receiver_if_necessary(&self, method_callee: &MethodCallee) { - /*! - * When we select a method with an `&mut self` receiver, we have to go - * convert any auto-derefs, indices, etc from `Deref` and `Index` into - * `DerefMut` and `IndexMut` respectively. - */ - let sig = match method_callee.ty.sty { ty::ty_bare_fn(ref f) => f.sig.clone(), ty::ty_closure(ref f) => f.sig.clone(), diff --git a/src/librustc/middle/typeck/check/method/doc.rs b/src/librustc/middle/typeck/check/method/doc.rs index 8c691e02ca9..6129e38e39c 100644 --- a/src/librustc/middle/typeck/check/method/doc.rs +++ b/src/librustc/middle/typeck/check/method/doc.rs @@ -8,119 +8,114 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -# Method lookup - -Method lookup can be rather complex due to the interaction of a number -of factors, such as self types, autoderef, trait lookup, etc. This -file provides an overview of the process. More detailed notes are in -the code itself, naturally. - -One way to think of method lookup is that we convert an expression of -the form: - - receiver.method(...) - -into a more explicit UFCS form: - - Trait::method(ADJ(receiver), ...) // for a trait call - ReceiverType::method(ADJ(receiver), ...) // for an inherent method call - -Here `ADJ` is some kind of adjustment, which is typically a series of -autoderefs and then possibly an autoref (e.g., `&**receiver`). However -we sometimes do other adjustments and coercions along the way, in -particular unsizing (e.g., converting from `[T, ..n]` to `[T]`). - -## The Two Phases - -Method lookup is divided into two major phases: probing (`probe.rs`) -and confirmation (`confirm.rs`). The probe phase is when we decide -what method to call and how to adjust the receiver. The confirmation -phase "applies" this selection, updating the side-tables, unifying -type variables, and otherwise doing side-effectful things. - -One reason for this division is to be more amenable to caching. The -probe phase produces a "pick" (`probe::Pick`), which is designed to be -cacheable across method-call sites. Therefore, it does not include -inference variables or other information. - -## Probe phase - -The probe phase (`probe.rs`) decides what method is being called and -how to adjust the receiver. - -### Steps - -The first thing that the probe phase does is to create a series of -*steps*. This is done by progressively dereferencing the receiver type -until it cannot be deref'd anymore, as well as applying an optional -"unsize" step. So if the receiver has type `Rc>`, this -might yield: - - Rc> - Box<[T, ..3]> - [T, ..3] - [T] - -### Candidate assembly - -We then search along those steps to create a list of *candidates*. A -`Candidate` is a method item that might plausibly be the method being -invoked. For each candidate, we'll derive a "transformed self type" -that takes into account explicit self. - -Candidates are grouped into two kinds, inherent and extension. - -**Inherent candidates** are those that are derived from the -type of the receiver itself. So, if you have a receiver of some -nominal type `Foo` (e.g., a struct), any methods defined within an -impl like `impl Foo` are inherent methods. Nothing needs to be -imported to use an inherent method, they are associated with the type -itself (note that inherent impls can only be defined in the same -module as the type itself). - -FIXME: Inherent candidates are not always derived from impls. If you -have a trait object, such as a value of type `Box`, then the -trait methods (`to_string()`, in this case) are inherently associated -with it. Another case is type parameters, in which case the methods of -their bounds are inherent. However, this part of the rules is subject -to change: when DST's "impl Trait for Trait" is complete, trait object -dispatch could be subsumed into trait matching, and the type parameter -behavior should be reconsidered in light of where clauses. - -**Extension candidates** are derived from imported traits. If I have -the trait `ToString` imported, and I call `to_string()` on a value of -type `T`, then we will go off to find out whether there is an impl of -`ToString` for `T`. These kinds of method calls are called "extension -methods". They can be defined in any module, not only the one that -defined `T`. Furthermore, you must import the trait to call such a -method. - -So, let's continue our example. Imagine that we were calling a method -`foo` with the receiver `Rc>` and there is a trait `Foo` -that defines it with `&self` for the type `Rc` as well as a method -on the type `Box` that defines `Foo` but with `&mut self`. Then we -might have two candidates: - - &Rc> from the impl of `Foo` for `Rc` where `U=Box - &mut Box<[T, ..3]>> from the inherent impl on `Box` where `U=[T, ..3]` - -### Candidate search - -Finally, to actually pick the method, we will search down the steps, -trying to match the receiver type against the candidate types. At -each step, we also consider an auto-ref and auto-mut-ref to see whether -that makes any of the candidates match. We pick the first step where -we find a match. - -In the case of our example, the first step is `Rc>`, -which does not itself match any candidate. But when we autoref it, we -get the type `&Rc>` which does match. We would then -recursively consider all where-clauses that appear on the impl: if -those match (or we cannot rule out that they do), then this is the -method we would pick. Otherwise, we would continue down the series of -steps. - -*/ - +//! # Method lookup +//! +//! Method lookup can be rather complex due to the interaction of a number +//! of factors, such as self types, autoderef, trait lookup, etc. This +//! file provides an overview of the process. More detailed notes are in +//! the code itself, naturally. +//! +//! One way to think of method lookup is that we convert an expression of +//! the form: +//! +//! receiver.method(...) +//! +//! into a more explicit UFCS form: +//! +//! Trait::method(ADJ(receiver), ...) // for a trait call +//! ReceiverType::method(ADJ(receiver), ...) // for an inherent method call +//! +//! Here `ADJ` is some kind of adjustment, which is typically a series of +//! autoderefs and then possibly an autoref (e.g., `&**receiver`). However +//! we sometimes do other adjustments and coercions along the way, in +//! particular unsizing (e.g., converting from `[T, ..n]` to `[T]`). +//! +//! ## The Two Phases +//! +//! Method lookup is divided into two major phases: probing (`probe.rs`) +//! and confirmation (`confirm.rs`). The probe phase is when we decide +//! what method to call and how to adjust the receiver. The confirmation +//! phase "applies" this selection, updating the side-tables, unifying +//! type variables, and otherwise doing side-effectful things. +//! +//! One reason for this division is to be more amenable to caching. The +//! probe phase produces a "pick" (`probe::Pick`), which is designed to be +//! cacheable across method-call sites. Therefore, it does not include +//! inference variables or other information. +//! +//! ## Probe phase +//! +//! The probe phase (`probe.rs`) decides what method is being called and +//! how to adjust the receiver. +//! +//! ### Steps +//! +//! The first thing that the probe phase does is to create a series of +//! *steps*. This is done by progressively dereferencing the receiver type +//! until it cannot be deref'd anymore, as well as applying an optional +//! "unsize" step. So if the receiver has type `Rc>`, this +//! might yield: +//! +//! Rc> +//! Box<[T, ..3]> +//! [T, ..3] +//! [T] +//! +//! ### Candidate assembly +//! +//! We then search along those steps to create a list of *candidates*. A +//! `Candidate` is a method item that might plausibly be the method being +//! invoked. For each candidate, we'll derive a "transformed self type" +//! that takes into account explicit self. +//! +//! Candidates are grouped into two kinds, inherent and extension. +//! +//! **Inherent candidates** are those that are derived from the +//! type of the receiver itself. So, if you have a receiver of some +//! nominal type `Foo` (e.g., a struct), any methods defined within an +//! impl like `impl Foo` are inherent methods. Nothing needs to be +//! imported to use an inherent method, they are associated with the type +//! itself (note that inherent impls can only be defined in the same +//! module as the type itself). +//! +//! FIXME: Inherent candidates are not always derived from impls. If you +//! have a trait object, such as a value of type `Box`, then the +//! trait methods (`to_string()`, in this case) are inherently associated +//! with it. Another case is type parameters, in which case the methods of +//! their bounds are inherent. However, this part of the rules is subject +//! to change: when DST's "impl Trait for Trait" is complete, trait object +//! dispatch could be subsumed into trait matching, and the type parameter +//! behavior should be reconsidered in light of where clauses. +//! +//! **Extension candidates** are derived from imported traits. If I have +//! the trait `ToString` imported, and I call `to_string()` on a value of +//! type `T`, then we will go off to find out whether there is an impl of +//! `ToString` for `T`. These kinds of method calls are called "extension +//! methods". They can be defined in any module, not only the one that +//! defined `T`. Furthermore, you must import the trait to call such a +//! method. +//! +//! So, let's continue our example. Imagine that we were calling a method +//! `foo` with the receiver `Rc>` and there is a trait `Foo` +//! that defines it with `&self` for the type `Rc` as well as a method +//! on the type `Box` that defines `Foo` but with `&mut self`. Then we +//! might have two candidates: +//! +//! &Rc> from the impl of `Foo` for `Rc` where `U=Box +//! &mut Box<[T, ..3]>> from the inherent impl on `Box` where `U=[T, ..3]` +//! +//! ### Candidate search +//! +//! Finally, to actually pick the method, we will search down the steps, +//! trying to match the receiver type against the candidate types. At +//! each step, we also consider an auto-ref and auto-mut-ref to see whether +//! that makes any of the candidates match. We pick the first step where +//! we find a match. +//! +//! In the case of our example, the first step is `Rc>`, +//! which does not itself match any candidate. But when we autoref it, we +//! get the type `&Rc>` which does match. We would then +//! recursively consider all where-clauses that appear on the impl: if +//! those match (or we cannot rule out that they do), then this is the +//! method we would pick. Otherwise, we would continue down the series of +//! steps. diff --git a/src/librustc/middle/typeck/check/method/mod.rs b/src/librustc/middle/typeck/check/method/mod.rs index 0f4152644ad..34c3292f8cd 100644 --- a/src/librustc/middle/typeck/check/method/mod.rs +++ b/src/librustc/middle/typeck/check/method/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Method lookup: the secret sauce of Rust. See `doc.rs`. */ +//! Method lookup: the secret sauce of Rust. See `doc.rs`. use middle::subst; use middle::subst::{Subst}; @@ -56,6 +56,7 @@ pub enum CandidateSource { type MethodIndex = uint; // just for doc purposes +/// Determines whether the type `self_ty` supports a method name `method_name` or not. pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, method_name: ast::Name, @@ -63,10 +64,6 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, call_expr_id: ast::NodeId) -> bool { - /*! - * Determines whether the type `self_ty` supports a method name `method_name` or not. - */ - match probe::probe(fcx, span, method_name, self_ty, call_expr_id) { Ok(_) => true, Err(NoMatch(_)) => false, @@ -74,6 +71,20 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } +/// Performs method lookup. If lookup is successful, it will return the callee and store an +/// appropriate adjustment for the self-expr. In some cases it may report an error (e.g., invoking +/// the `drop` method). +/// +/// # Arguments +/// +/// Given a method call like `foo.bar::(...)`: +/// +/// * `fcx`: the surrounding `FnCtxt` (!) +/// * `span`: the span for the method call +/// * `method_name`: the name of the method being called (`bar`) +/// * `self_ty`: the (unadjusted) type of the self expression (`foo`) +/// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`) +/// * `self_expr`: the self expression (`foo`) pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, method_name: ast::Name, @@ -83,23 +94,6 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, self_expr: &ast::Expr) -> Result, MethodError> { - /*! - * Performs method lookup. If lookup is successful, it will return the callee - * and store an appropriate adjustment for the self-expr. In some cases it may - * report an error (e.g., invoking the `drop` method). - * - * # Arguments - * - * Given a method call like `foo.bar::(...)`: - * - * - `fcx`: the surrounding `FnCtxt` (!) - * - `span`: the span for the method call - * - `method_name`: the name of the method being called (`bar`) - * - `self_ty`: the (unadjusted) type of the self expression (`foo`) - * - `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`) - * - `self_expr`: the self expression (`foo`) - */ - debug!("lookup(method_name={}, self_ty={}, call_expr={}, self_expr={})", method_name.repr(fcx.tcx()), self_ty.repr(fcx.tcx()), @@ -124,6 +118,15 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, self_ty, opt_input_types) } +/// `lookup_in_trait_adjusted` is used for overloaded operators. It does a very narrow slice of +/// what the normal probe/confirm path does. In particular, it doesn't really do any probing: it +/// simply constructs an obligation for a particular trait with the given self-type and checks +/// whether that trait is implemented. +/// +/// FIXME(#18741) -- It seems likely that we can consolidate some of this code with the other +/// method-lookup code. In particular, autoderef on index is basically identical to autoderef with +/// normal probes, except that the test also looks for built-in indexing. Also, the second half of +/// this method is basically the same as confirmation. pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, span: Span, self_expr: Option<&'a ast::Expr>, @@ -134,21 +137,6 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, opt_input_types: Option>>) -> Option> { - /*! - * `lookup_in_trait_adjusted` is used for overloaded operators. It - * does a very narrow slice of what the normal probe/confirm path - * does. In particular, it doesn't really do any probing: it - * simply constructs an obligation for a particular trait with the - * given self-type and checks whether that trait is implemented. - * - * FIXME(#18741) -- It seems likely that we can consolidate some of this - * code with the other method-lookup code. In particular, - * autoderef on index is basically identical to autoderef with - * normal probes, except that the test also looks for built-in - * indexing. Also, the second half of this method is basically - * the same as confirmation. - */ - debug!("lookup_in_trait_adjusted(self_ty={}, self_expr={}, m_name={}, trait_def_id={})", self_ty.repr(fcx.tcx()), self_expr.repr(fcx.tcx()), @@ -408,16 +396,13 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } +/// Find method with name `method_name` defined in `trait_def_id` and return it, along with its +/// index (or `None`, if no such method). fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, trait_def_id: ast::DefId, method_name: ast::Name) -> Option<(uint, Rc>)> { - /*! - * Find method with name `method_name` defined in `trait_def_id` and return it, - * along with its index (or `None`, if no such method). - */ - let trait_items = ty::trait_items(tcx, trait_def_id); trait_items .iter() diff --git a/src/librustc/middle/typeck/check/method/probe.rs b/src/librustc/middle/typeck/check/method/probe.rs index a98b4cf011d..484d72130e6 100644 --- a/src/librustc/middle/typeck/check/method/probe.rs +++ b/src/librustc/middle/typeck/check/method/probe.rs @@ -807,33 +807,26 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { }) } + /// Sometimes we get in a situation where we have multiple probes that are all impls of the + /// same trait, but we don't know which impl to use. In this case, since in all cases the + /// external interface of the method can be determined from the trait, it's ok not to decide. + /// We can basically just collapse all of the probes for various impls into one where-clause + /// probe. This will result in a pending obligation so when more type-info is available we can + /// make the final decision. + /// + /// Example (`src/test/run-pass/method-two-trait-defer-resolution-1.rs`): + /// + /// ``` + /// trait Foo { ... } + /// impl Foo for Vec { ... } + /// impl Foo for Vec { ... } + /// ``` + /// + /// Now imagine the receiver is `Vec<_>`. It doesn't really matter at this time which impl we + /// use, so it's ok to just commit to "using the method from the trait Foo". fn collapse_candidates_to_trait_pick(&self, probes: &[&Candidate<'tcx>]) -> Option> { - /*! - * Sometimes we get in a situation where we have multiple - * probes that are all impls of the same trait, but we don't - * know which impl to use. In this case, since in all cases - * the external interface of the method can be determined from - * the trait, it's ok not to decide. We can basically just - * collapse all of the probes for various impls into one - * where-clause probe. This will result in a pending - * obligation so when more type-info is available we can make - * the final decision. - * - * Example (`src/test/run-pass/method-two-trait-defer-resolution-1.rs`): - * - * ``` - * trait Foo { ... } - * impl Foo for Vec { ... } - * impl Foo for Vec { ... } - * ``` - * - * Now imagine the receiver is `Vec<_>`. It doesn't really - * matter at this time which impl we use, so it's ok to just - * commit to "using the method from the trait Foo". - */ - // Do all probes correspond to the same trait? let trait_data = match probes[0].to_trait_data() { Some(data) => data, @@ -952,36 +945,27 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { subst::Substs::new(type_vars, region_placeholders) } + /// Replace late-bound-regions bound by `value` with `'static` using + /// `ty::erase_late_bound_regions`. + /// + /// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of + /// method matching. It is reasonable during the probe phase because we don't consider region + /// relationships at all. Therefore, we can just replace all the region variables with 'static + /// rather than creating fresh region variables. This is nice for two reasons: + /// + /// 1. Because the numbers of the region variables would otherwise be fairly unique to this + /// particular method call, it winds up creating fewer types overall, which helps for memory + /// usage. (Admittedly, this is a rather small effect, though measureable.) + /// + /// 2. It makes it easier to deal with higher-ranked trait bounds, because we can replace any + /// late-bound regions with 'static. Otherwise, if we were going to replace late-bound + /// regions with actual region variables as is proper, we'd have to ensure that the same + /// region got replaced with the same variable, which requires a bit more coordination + /// and/or tracking the substitution and + /// so forth. fn erase_late_bound_regions(&self, value: &T) -> T where T : HigherRankedFoldable<'tcx> { - /*! - * Replace late-bound-regions bound by `value` with `'static` - * using `ty::erase_late_bound_regions`. - * - * This is only a reasonable thing to do during the *probe* - * phase, not the *confirm* phase, of method matching. It is - * reasonable during the probe phase because we don't consider - * region relationships at all. Therefore, we can just replace - * all the region variables with 'static rather than creating - * fresh region variables. This is nice for two reasons: - * - * 1. Because the numbers of the region variables would - * otherwise be fairly unique to this particular method - * call, it winds up creating fewer types overall, which - * helps for memory usage. (Admittedly, this is a rather - * small effect, though measureable.) - * - * 2. It makes it easier to deal with higher-ranked trait - * bounds, because we can replace any late-bound regions - * with 'static. Otherwise, if we were going to replace - * late-bound regions with actual region variables as is - * proper, we'd have to ensure that the same region got - * replaced with the same variable, which requires a bit - * more coordination and/or tracking the substitution and - * so forth. - */ - ty::erase_late_bound_regions(self.tcx(), value) } } @@ -1000,16 +984,13 @@ fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, .and_then(|item| item.as_opt_method()) } +/// Find method with name `method_name` defined in `trait_def_id` and return it, along with its +/// index (or `None`, if no such method). fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, trait_def_id: ast::DefId, method_name: ast::Name) -> Option<(uint, Rc>)> { - /*! - * Find method with name `method_name` defined in `trait_def_id` and return it, - * along with its index (or `None`, if no such method). - */ - let trait_items = ty::trait_items(tcx, trait_def_id); trait_items .iter() diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 754bdc8c8ea..b33ce04f5eb 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -486,6 +486,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { } +/// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function +/// body and returns the function context used for that purpose, since in the case of a fn item +/// there is still a bit more to do. +/// +/// * ... +/// * inherited: other fields inherited from the enclosing fn (if any) fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fn_style: ast::FnStyle, fn_style_id: ast::NodeId, @@ -495,16 +501,6 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, body: &ast::Block, inherited: &'a Inherited<'a, 'tcx>) -> FnCtxt<'a, 'tcx> { - /*! - * Helper used by check_bare_fn and check_expr_fn. Does the - * grungy work of checking a function body and returns the - * function context used for that purpose, since in the case of a - * fn item there is still a bit more to do. - * - * - ... - * - inherited: other fields inherited from the enclosing fn (if any) - */ - let tcx = ccx.tcx; let err_count_on_creation = tcx.sess.err_count(); @@ -701,19 +697,17 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { } } +/// Type checks a method body. +/// +/// # Parameters +/// +/// * `item_generics`: generics defined on the impl/trait that contains +/// the method +/// * `self_bound`: bound for the `Self` type parameter, if any +/// * `method`: the method definition fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, item_generics: &ty::Generics<'tcx>, method: &ast::Method) { - /*! - * Type checks a method body. - * - * # Parameters - * - `item_generics`: generics defined on the impl/trait that contains - * the method - * - `self_bound`: bound for the `Self` type parameter, if any - * - `method`: the method definition - */ - debug!("check_method_body(item_generics={}, method.id={})", item_generics.repr(ccx.tcx), method.id); @@ -1222,6 +1216,33 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // parameters. infcx.resolve_regions_and_report_errors(); + /// Check that region bounds on impl method are the same as those on the trait. In principle, + /// it could be ok for there to be fewer region bounds on the impl method, but this leads to an + /// annoying corner case that is painful to handle (described below), so for now we can just + /// forbid it. + /// + /// Example (see `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`): + /// + /// ``` + /// trait Foo<'a> { + /// fn method1<'b>(); + /// fn method2<'b:'a>(); + /// } + /// + /// impl<'a> Foo<'a> for ... { + /// fn method1<'b:'a>() { .. case 1, definitely bad .. } + /// fn method2<'b>() { .. case 2, could be ok .. } + /// } + /// ``` + /// + /// The "definitely bad" case is case #1. Here, the impl adds an extra constraint not present + /// in the trait. + /// + /// The "maybe bad" case is case #2. Here, the impl adds an extra constraint not present in the + /// trait. We could in principle allow this, but it interacts in a complex way with early/late + /// bound resolution of lifetimes. Basically the presence or absence of a lifetime bound + /// affects whether the lifetime is early/late bound, and right now the code breaks if the + /// trait has an early bound lifetime parameter and the method does not. fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, span: Span, impl_m: &ty::Method<'tcx>, @@ -1232,37 +1253,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, impl_to_skol_substs: &Substs<'tcx>) -> bool { - /*! - - Check that region bounds on impl method are the same as those - on the trait. In principle, it could be ok for there to be - fewer region bounds on the impl method, but this leads to an - annoying corner case that is painful to handle (described - below), so for now we can just forbid it. - - Example (see - `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`): - - trait Foo<'a> { - fn method1<'b>(); - fn method2<'b:'a>(); - } - - impl<'a> Foo<'a> for ... { - fn method1<'b:'a>() { .. case 1, definitely bad .. } - fn method2<'b>() { .. case 2, could be ok .. } - } - - The "definitely bad" case is case #1. Here, the impl adds an - extra constraint not present in the trait. - - The "maybe bad" case is case #2. Here, the impl adds an extra - constraint not present in the trait. We could in principle - allow this, but it interacts in a complex way with early/late - bound resolution of lifetimes. Basically the presence or - absence of a lifetime bound affects whether the lifetime is - early/late bound, and right now the code breaks if the trait - has an early bound lifetime parameter and the method does not. */ @@ -1770,23 +1760,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables. + /// Also returns the substitution from the type parameters on `def_id` to the fresh variables. + /// Registers any trait obligations specified on `def_id` at the same time. + /// + /// Note that function is only intended to be used with types (notably, not impls). This is + /// because it doesn't do any instantiation of late-bound regions. pub fn instantiate_type(&self, span: Span, def_id: ast::DefId) -> TypeAndSubsts<'tcx> { - /*! - * Returns the type of `def_id` with all generics replaced by - * by fresh type/region variables. Also returns the - * substitution from the type parameters on `def_id` to the - * fresh variables. Registers any trait obligations specified - * on `def_id` at the same time. - * - * Note that function is only intended to be used with types - * (notably, not impls). This is because it doesn't do any - * instantiation of late-bound regions. - */ - let polytype = ty::lookup_item_type(self.tcx(), def_id); let substs = @@ -1886,26 +1870,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Fetch type of `expr` after applying adjustments that have been recorded in the fcx. pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> { - /*! - * Fetch type of `expr` after applying adjustments that - * have been recorded in the fcx. - */ - let adjustments = self.inh.adjustments.borrow(); let adjustment = adjustments.get(&expr.id); self.adjust_expr_ty(expr, adjustment) } + /// Apply `adjustment` to the type of `expr` pub fn adjust_expr_ty(&self, expr: &ast::Expr, adjustment: Option<&ty::AutoAdjustment<'tcx>>) -> Ty<'tcx> { - /*! - * Apply `adjustment` to the type of `expr` - */ - let raw_ty = self.expr_ty(expr); let raw_ty = self.infcx().shallow_resolve(raw_ty); ty::adjust_ty(self.tcx(), @@ -2013,16 +1990,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.infcx().report_mismatched_types(sp, e, a, err) } + /// Registers an obligation for checking later, during regionck, that the type `ty` must + /// outlive the region `r`. pub fn register_region_obligation(&self, origin: infer::SubregionOrigin<'tcx>, ty: Ty<'tcx>, r: ty::Region) { - /*! - * Registers an obligation for checking later, during - * regionck, that the type `ty` must outlive the region `r`. - */ - let mut region_obligations = self.inh.region_obligations.borrow_mut(); let region_obligation = RegionObligation { sub_region: r, sup_type: ty, @@ -2045,31 +2019,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each + /// type/region parameter was instantiated (`substs`), creates and registers suitable + /// trait/region obligations. + /// + /// For example, if there is a function: + /// + /// ``` + /// fn foo<'a,T:'a>(...) + /// ``` + /// + /// and a reference: + /// + /// ``` + /// let f = foo; + /// ``` + /// + /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a` + /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally. pub fn add_obligations_for_parameters(&self, cause: traits::ObligationCause<'tcx>, substs: &Substs<'tcx>, generic_bounds: &ty::GenericBounds<'tcx>) { - /*! - * Given a fully substituted set of bounds (`generic_bounds`), - * and the values with which each type/region parameter was - * instantiated (`substs`), creates and registers suitable - * trait/region obligations. - * - * For example, if there is a function: - * - * fn foo<'a,T:'a>(...) - * - * and a reference: - * - * let f = foo; - * - * Then we will create a fresh region variable `'$0` and a - * fresh type variable `$1` for `'a` and `T`. This routine - * will add a region obligation `$1:'$0` and register it - * locally. - */ - assert!(!generic_bounds.has_escaping_regions()); debug!("add_obligations_for_parameters(substs={}, generic_bounds={})", @@ -2160,22 +2132,17 @@ pub enum LvaluePreference { NoPreference } +/// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide +/// whether to terminate the loop. Returns the final type and number of derefs that it performed. +/// +/// Note: this method does not modify the adjustments table. The caller is responsible for +/// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods. pub fn autoderef<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, base_ty: Ty<'tcx>, expr_id: Option, mut lvalue_pref: LvaluePreference, should_stop: |Ty<'tcx>, uint| -> Option) -> (Ty<'tcx>, uint, Option) { - /*! - * Executes an autoderef loop for the type `t`. At each step, invokes - * `should_stop` to decide whether to terminate the loop. Returns - * the final type and number of derefs that it performed. - * - * Note: this method does not modify the adjustments table. The caller is - * responsible for inserting an AutoAdjustment record into the `fcx` - * using one of the suitable methods. - */ - let mut t = base_ty; for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) { let resolved_t = structurally_resolved_type(fcx, sp, t); @@ -2306,19 +2273,14 @@ fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, make_overloaded_lvalue_return_type(fcx, method_call, method) } +/// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the +/// actual type we assign to the *expression* is `T`. So this function just peels off the return +/// type by one layer to yield `T`. It also inserts the `method-callee` into the method map. fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_call: Option, method: Option>) -> Option> { - /*! - * For the overloaded lvalue expressions (`*x`, `x[3]`), the trait - * returns a type of `&T`, but the actual type we assign to the - * *expression* is `T`. So this function just peels off the return - * type by one layer to yield `T`. It also inserts the - * `method-callee` into the method map. - */ - match method { Some(method) => { let ref_ty = ty::ty_fn_ret(method.ty); @@ -2380,6 +2342,8 @@ fn autoderef_for_index<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>, } } +/// Autoderefs `base_expr`, looking for a `Slice` impl. If it finds one, installs the relevant +/// method info and returns the result type (else None). fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_call: MethodCall, expr: &ast::Expr, @@ -2390,12 +2354,6 @@ fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, mutbl: ast::Mutability) -> Option> // return type is result of slice { - /*! - * Autoderefs `base_expr`, looking for a `Slice` impl. If it - * finds one, installs the relevant method info and returns the - * result type (else None). - */ - let lvalue_pref = match mutbl { ast::MutMutable => PreferMutLvalue, ast::MutImmutable => NoPreference @@ -2436,6 +2394,8 @@ fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }) } +/// Checks for a `Slice` (or `SliceMut`) impl at the relevant level of autoderef. If it finds one, +/// installs method info and returns type of method (else None). fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_call: MethodCall, expr: &ast::Expr, @@ -2448,12 +2408,6 @@ fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // result type is type of method being called -> Option> { - /*! - * Checks for a `Slice` (or `SliceMut`) impl at the relevant level - * of autoderef. If it finds one, installs method info and returns - * type of method (else None). - */ - let method = if mutbl == ast::MutMutable { // Try `SliceMut` first, if preferred. match fcx.tcx().lang_items.slice_mut_trait() { @@ -2510,6 +2464,10 @@ fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }) } +/// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust) +/// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing. +/// This loop implements one step in that search; the autoderef loop is implemented by +/// `autoderef_for_index`. fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_call: MethodCall, expr: &ast::Expr, @@ -2519,13 +2477,6 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, lvalue_pref: LvaluePreference) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { - /*! - * To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust) - * `base_expr`, looking for a type which either supports builtin indexing or overloaded - * indexing. This loop implements one step in that search; the autoderef loop is implemented - * by `autoderef_for_index`. - */ - debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={})", expr.repr(fcx.tcx()), base_expr.repr(fcx.tcx()), @@ -2712,6 +2663,8 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } +/// Generic function that factors out common logic from function calls, method calls and overloaded +/// operators. fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, fn_inputs: &[Ty<'tcx>], @@ -2720,12 +2673,6 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, deref_args: DerefArgs, variadic: bool, tuple_arguments: TupleArgumentsFlag) { - /*! - * - * Generic function that factors out common logic from - * function calls, method calls and overloaded operators. - */ - let tcx = fcx.ccx.tcx; // Grab the argument types, supplying fresh type variables @@ -5289,6 +5236,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } + /// Finds the parameters that the user provided and adds them to `substs`. If too many + /// parameters are provided, then reports an error and clears the output vector. + /// + /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to + /// use inference variables. This seems less likely to lead to derived errors. + /// + /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults + /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters + /// here because we can easily use the precise span of the N+1'th parameter. fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>( fcx: &FnCtxt<'a, 'tcx>, space: subst::ParamSpace, @@ -5298,23 +5254,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, segment: &ast::PathSegment, substs: &mut Substs<'tcx>) { - /*! - * Finds the parameters that the user provided and adds them - * to `substs`. If too many parameters are provided, then - * reports an error and clears the output vector. - * - * We clear the output vector because that will cause the - * `adjust_XXX_parameters()` later to use inference - * variables. This seems less likely to lead to derived - * errors. - * - * Note that we *do not* check for *too few* parameters here. - * Due to the presence of defaults etc that is more - * complicated. I wanted however to do the reporting of *too - * many* parameters here because we can easily use the precise - * span of the N+1'th parameter. - */ - match segment.parameters { ast::AngleBracketedParameters(ref data) => { push_explicit_angle_bracketed_parameters_from_segment_to_substs( @@ -5373,6 +5312,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } + /// As with + /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`, + /// but intended for `Foo(A,B) -> C` form. This expands to + /// roughly the same thing as `Foo<(A,B),C>`. One important + /// difference has to do with the treatment of anonymous + /// regions, which are translated into bound regions (NYI). fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>( fcx: &FnCtxt<'a, 'tcx>, space: subst::ParamSpace, @@ -5381,15 +5326,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, data: &ast::ParenthesizedParameterData, substs: &mut Substs<'tcx>) { - /*! - * As with - * `push_explicit_angle_bracketed_parameters_from_segment_to_substs`, - * but intended for `Foo(A,B) -> C` form. This expands to - * roughly the same thing as `Foo<(A,B),C>`. One important - * difference has to do with the treatment of anonymous - * regions, which are translated into bound regions (NYI). - */ - let type_count = type_defs.len(space); if type_count < 2 { span_err!(fcx.tcx().sess, span, E0167, diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index f12b5cdad98..bc6e7d9d87f 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -8,115 +8,111 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -The region check is a final pass that runs over the AST after we have -inferred the type constraints but before we have actually finalized -the types. Its purpose is to embed a variety of region constraints. -Inserting these constraints as a separate pass is good because (1) it -localizes the code that has to do with region inference and (2) often -we cannot know what constraints are needed until the basic types have -been inferred. - -### Interaction with the borrow checker - -In general, the job of the borrowck module (which runs later) is to -check that all soundness criteria are met, given a particular set of -regions. The job of *this* module is to anticipate the needs of the -borrow checker and infer regions that will satisfy its requirements. -It is generally true that the inference doesn't need to be sound, -meaning that if there is a bug and we inferred bad regions, the borrow -checker should catch it. This is not entirely true though; for -example, the borrow checker doesn't check subtyping, and it doesn't -check that region pointers are always live when they are used. It -might be worthwhile to fix this so that borrowck serves as a kind of -verification step -- that would add confidence in the overall -correctness of the compiler, at the cost of duplicating some type -checks and effort. - -### Inferring the duration of borrows, automatic and otherwise - -Whenever we introduce a borrowed pointer, for example as the result of -a borrow expression `let x = &data`, the lifetime of the pointer `x` -is always specified as a region inference variable. `regionck` has the -job of adding constraints such that this inference variable is as -narrow as possible while still accommodating all uses (that is, every -dereference of the resulting pointer must be within the lifetime). - -#### Reborrows - -Generally speaking, `regionck` does NOT try to ensure that the data -`data` will outlive the pointer `x`. That is the job of borrowck. The -one exception is when "re-borrowing" the contents of another borrowed -pointer. For example, imagine you have a borrowed pointer `b` with -lifetime L1 and you have an expression `&*b`. The result of this -expression will be another borrowed pointer with lifetime L2 (which is -an inference variable). The borrow checker is going to enforce the -constraint that L2 < L1, because otherwise you are re-borrowing data -for a lifetime larger than the original loan. However, without the -routines in this module, the region inferencer would not know of this -dependency and thus it might infer the lifetime of L2 to be greater -than L1 (issue #3148). - -There are a number of troublesome scenarios in the tests -`region-dependent-*.rs`, but here is one example: - - struct Foo { i: int } - struct Bar { foo: Foo } - fn get_i(x: &'a Bar) -> &'a int { - let foo = &x.foo; // Lifetime L1 - &foo.i // Lifetime L2 - } - -Note that this comes up either with `&` expressions, `ref` -bindings, and `autorefs`, which are the three ways to introduce -a borrow. - -The key point here is that when you are borrowing a value that -is "guaranteed" by a borrowed pointer, you must link the -lifetime of that borrowed pointer (L1, here) to the lifetime of -the borrow itself (L2). What do I mean by "guaranteed" by a -borrowed pointer? I mean any data that is reached by first -dereferencing a borrowed pointer and then either traversing -interior offsets or owned pointers. We say that the guarantor -of such data it the region of the borrowed pointer that was -traversed. This is essentially the same as the ownership -relation, except that a borrowed pointer never owns its -contents. - -### Inferring borrow kinds for upvars - -Whenever there is a closure expression, we need to determine how each -upvar is used. We do this by initially assigning each upvar an -immutable "borrow kind" (see `ty::BorrowKind` for details) and then -"escalating" the kind as needed. The borrow kind proceeds according to -the following lattice: - - ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow - -So, for example, if we see an assignment `x = 5` to an upvar `x`, we -will promote its borrow kind to mutable borrow. If we see an `&mut x` -we'll do the same. Naturally, this applies not just to the upvar, but -to everything owned by `x`, so the result is the same for something -like `x.f = 5` and so on (presuming `x` is not a borrowed pointer to a -struct). These adjustments are performed in -`adjust_upvar_borrow_kind()` (you can trace backwards through the code -from there). - -The fact that we are inferring borrow kinds as we go results in a -semi-hacky interaction with mem-categorization. In particular, -mem-categorization will query the current borrow kind as it -categorizes, and we'll return the *current* value, but this may get -adjusted later. Therefore, in this module, we generally ignore the -borrow kind (and derived mutabilities) that are returned from -mem-categorization, since they may be inaccurate. (Another option -would be to use a unification scheme, where instead of returning a -concrete borrow kind like `ty::ImmBorrow`, we return a -`ty::InferBorrow(upvar_id)` or something like that, but this would -then mean that all later passes would have to check for these figments -and report an error, and it just seems like more mess in the end.) - -*/ +//! The region check is a final pass that runs over the AST after we have +//! inferred the type constraints but before we have actually finalized +//! the types. Its purpose is to embed a variety of region constraints. +//! Inserting these constraints as a separate pass is good because (1) it +//! localizes the code that has to do with region inference and (2) often +//! we cannot know what constraints are needed until the basic types have +//! been inferred. +//! +//! ### Interaction with the borrow checker +//! +//! In general, the job of the borrowck module (which runs later) is to +//! check that all soundness criteria are met, given a particular set of +//! regions. The job of *this* module is to anticipate the needs of the +//! borrow checker and infer regions that will satisfy its requirements. +//! It is generally true that the inference doesn't need to be sound, +//! meaning that if there is a bug and we inferred bad regions, the borrow +//! checker should catch it. This is not entirely true though; for +//! example, the borrow checker doesn't check subtyping, and it doesn't +//! check that region pointers are always live when they are used. It +//! might be worthwhile to fix this so that borrowck serves as a kind of +//! verification step -- that would add confidence in the overall +//! correctness of the compiler, at the cost of duplicating some type +//! checks and effort. +//! +//! ### Inferring the duration of borrows, automatic and otherwise +//! +//! Whenever we introduce a borrowed pointer, for example as the result of +//! a borrow expression `let x = &data`, the lifetime of the pointer `x` +//! is always specified as a region inference variable. `regionck` has the +//! job of adding constraints such that this inference variable is as +//! narrow as possible while still accommodating all uses (that is, every +//! dereference of the resulting pointer must be within the lifetime). +//! +//! #### Reborrows +//! +//! Generally speaking, `regionck` does NOT try to ensure that the data +//! `data` will outlive the pointer `x`. That is the job of borrowck. The +//! one exception is when "re-borrowing" the contents of another borrowed +//! pointer. For example, imagine you have a borrowed pointer `b` with +//! lifetime L1 and you have an expression `&*b`. The result of this +//! expression will be another borrowed pointer with lifetime L2 (which is +//! an inference variable). The borrow checker is going to enforce the +//! constraint that L2 < L1, because otherwise you are re-borrowing data +//! for a lifetime larger than the original loan. However, without the +//! routines in this module, the region inferencer would not know of this +//! dependency and thus it might infer the lifetime of L2 to be greater +//! than L1 (issue #3148). +//! +//! There are a number of troublesome scenarios in the tests +//! `region-dependent-*.rs`, but here is one example: +//! +//! struct Foo { i: int } +//! struct Bar { foo: Foo } +//! fn get_i(x: &'a Bar) -> &'a int { +//! let foo = &x.foo; // Lifetime L1 +//! &foo.i // Lifetime L2 +//! } +//! +//! Note that this comes up either with `&` expressions, `ref` +//! bindings, and `autorefs`, which are the three ways to introduce +//! a borrow. +//! +//! The key point here is that when you are borrowing a value that +//! is "guaranteed" by a borrowed pointer, you must link the +//! lifetime of that borrowed pointer (L1, here) to the lifetime of +//! the borrow itself (L2). What do I mean by "guaranteed" by a +//! borrowed pointer? I mean any data that is reached by first +//! dereferencing a borrowed pointer and then either traversing +//! interior offsets or owned pointers. We say that the guarantor +//! of such data it the region of the borrowed pointer that was +//! traversed. This is essentially the same as the ownership +//! relation, except that a borrowed pointer never owns its +//! contents. +//! +//! ### Inferring borrow kinds for upvars +//! +//! Whenever there is a closure expression, we need to determine how each +//! upvar is used. We do this by initially assigning each upvar an +//! immutable "borrow kind" (see `ty::BorrowKind` for details) and then +//! "escalating" the kind as needed. The borrow kind proceeds according to +//! the following lattice: +//! +//! ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow +//! +//! So, for example, if we see an assignment `x = 5` to an upvar `x`, we +//! will promote its borrow kind to mutable borrow. If we see an `&mut x` +//! we'll do the same. Naturally, this applies not just to the upvar, but +//! to everything owned by `x`, so the result is the same for something +//! like `x.f = 5` and so on (presuming `x` is not a borrowed pointer to a +//! struct). These adjustments are performed in +//! `adjust_upvar_borrow_kind()` (you can trace backwards through the code +//! from there). +//! +//! The fact that we are inferring borrow kinds as we go results in a +//! semi-hacky interaction with mem-categorization. In particular, +//! mem-categorization will query the current borrow kind as it +//! categorizes, and we'll return the *current* value, but this may get +//! adjusted later. Therefore, in this module, we generally ignore the +//! borrow kind (and derived mutabilities) that are returned from +//! mem-categorization, since they may be inaccurate. (Another option +//! would be to use a unification scheme, where instead of returning a +//! concrete borrow kind like `ty::ImmBorrow`, we return a +//! `ty::InferBorrow(upvar_id)` or something like that, but this would +//! then mean that all later passes would have to check for these figments +//! and report an error, and it just seems like more mess in the end.) use middle::def; use middle::mem_categorization as mc; @@ -177,15 +173,11 @@ pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, blk: &ast::Block) { fcx.infcx().resolve_regions_and_report_errors(); } +/// Checks that the types in `component_tys` are well-formed. This will add constraints into the +/// region graph. Does *not* run `resolve_regions_and_report_errors` and so forth. pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, component_tys: &[Ty<'tcx>]) { - /*! - * Checks that the types in `component_tys` are well-formed. - * This will add constraints into the region graph. - * Does *not* run `resolve_regions_and_report_errors` and so forth. - */ - let mut rcx = Rcx::new(fcx, 0); for &component_ty in component_tys.iter() { // Check that each type outlives the empty region. Since the @@ -239,12 +231,8 @@ pub struct Rcx<'a, 'tcx: 'a> { maybe_links: MaybeLinkMap<'tcx> } +/// Returns the validity region of `def` -- that is, how long is `def` valid? fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region { - /*! - * Returns the validity region of `def` -- that is, how long - * is `def` valid? - */ - let tcx = fcx.tcx(); match def { def::DefLocal(node_id) => { @@ -283,35 +271,30 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { old_scope } + /// Try to resolve the type for the given node, returning t_err if an error results. Note that + /// we never care about the details of the error, the same error will be detected and reported + /// in the writeback phase. + /// + /// Note one important point: we do not attempt to resolve *region variables* here. This is + /// because regionck is essentially adding constraints to those region variables and so may yet + /// influence how they are resolved. + /// + /// Consider this silly example: + /// + /// ``` + /// fn borrow(x: &int) -> &int {x} + /// fn foo(x: @int) -> int { // block: B + /// let b = borrow(x); // region: + /// *b + /// } + /// ``` + /// + /// Here, the region of `b` will be ``. `` is constrainted to be some subregion of the + /// block B and some superregion of the call. If we forced it now, we'd choose the smaller + /// region (the call). But that would make the *b illegal. Since we don't resolve, the type + /// of b will be `&.int` and then `*b` will require that `` be bigger than the let and + /// the `*b` expression, so we will effectively resolve `` to be the block B. pub fn resolve_type(&self, unresolved_ty: Ty<'tcx>) -> Ty<'tcx> { - /*! - * Try to resolve the type for the given node, returning - * t_err if an error results. Note that we never care - * about the details of the error, the same error will be - * detected and reported in the writeback phase. - * - * Note one important point: we do not attempt to resolve - * *region variables* here. This is because regionck is - * essentially adding constraints to those region variables - * and so may yet influence how they are resolved. - * - * Consider this silly example: - * - * fn borrow(x: &int) -> &int {x} - * fn foo(x: @int) -> int { // block: B - * let b = borrow(x); // region: - * *b - * } - * - * Here, the region of `b` will be ``. `` is - * constrainted to be some subregion of the block B and some - * superregion of the call. If we forced it now, we'd choose - * the smaller region (the call). But that would make the *b - * illegal. Since we don't resolve, the type of b will be - * `&.int` and then `*b` will require that `` be - * bigger than the let and the `*b` expression, so we will - * effectively resolve `` to be the block B. - */ match resolve_type(self.fcx.infcx(), None, unresolved_ty, resolve_and_force_all_but_regions) { Ok(t) => t, @@ -384,25 +367,19 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { } } + /// This method populates the region map's `free_region_map`. It walks over the transformed + /// argument and return types for each function just before we check the body of that function, + /// looking for types where you have a borrowed pointer to other borrowed data (e.g., `&'a &'b + /// [uint]`. We do not allow references to outlive the things they point at, so we can assume + /// that `'a <= 'b`. This holds for both the argument and return types, basically because, on + /// the caller side, the caller is responsible for checking that the type of every expression + /// (including the actual values for the arguments, as well as the return type of the fn call) + /// is well-formed. + /// + /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` fn relate_free_regions(&mut self, fn_sig_tys: &[Ty<'tcx>], body_id: ast::NodeId) { - /*! - * This method populates the region map's `free_region_map`. - * It walks over the transformed argument and return types for - * each function just before we check the body of that - * function, looking for types where you have a borrowed - * pointer to other borrowed data (e.g., `&'a &'b [uint]`. We - * do not allow references to outlive the things they point - * at, so we can assume that `'a <= 'b`. This holds for both - * the argument and return types, basically because, on the caller - * side, the caller is responsible for checking that the type of - * every expression (including the actual values for the arguments, - * as well as the return type of the fn call) is well-formed. - * - * Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` - */ - debug!("relate_free_regions >>"); let tcx = self.tcx(); @@ -921,19 +898,15 @@ fn check_expr_fn_block(rcx: &mut Rcx, _ => {} } + /// Make sure that the type of all free variables referenced inside a closure/proc outlive the + /// closure/proc's lifetime bound. This is just a special case of the usual rules about closed + /// over values outliving the object's lifetime bound. fn ensure_free_variable_types_outlive_closure_bound( rcx: &mut Rcx, bounds: ty::ExistentialBounds, expr: &ast::Expr, freevars: &[ty::Freevar]) { - /*! - * Make sure that the type of all free variables referenced - * inside a closure/proc outlive the closure/proc's lifetime - * bound. This is just a special case of the usual rules about - * closed over values outliving the object's lifetime bound. - */ - let tcx = rcx.fcx.ccx.tcx; debug!("ensure_free_variable_types_outlive_closure_bound({}, {})", @@ -984,18 +957,14 @@ fn check_expr_fn_block(rcx: &mut Rcx, } } + /// Make sure that all free variables referenced inside the closure outlive the closure's + /// lifetime bound. Also, create an entry in the upvar_borrows map with a region. fn constrain_free_variables_in_by_ref_closure( rcx: &mut Rcx, region_bound: ty::Region, expr: &ast::Expr, freevars: &[ty::Freevar]) { - /*! - * Make sure that all free variables referenced inside the - * closure outlive the closure's lifetime bound. Also, create - * an entry in the upvar_borrows map with a region. - */ - let tcx = rcx.fcx.ccx.tcx; let infcx = rcx.fcx.infcx(); debug!("constrain_free_variables({}, {})", @@ -1183,15 +1152,12 @@ fn constrain_call<'a, I: Iterator<&'a ast::Expr>>(rcx: &mut Rcx, } } +/// Invoked on any auto-dereference that occurs. Checks that if this is a region pointer being +/// dereferenced, the lifetime of the pointer includes the deref expr. fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, deref_expr: &ast::Expr, derefs: uint, mut derefd_ty: Ty<'tcx>) { - /*! - * Invoked on any auto-dereference that occurs. Checks that if - * this is a region pointer being dereferenced, the lifetime of - * the pointer includes the deref expr. - */ let r_deref_expr = ty::ReScope(CodeExtent::from_node_id(deref_expr.id)); for i in range(0u, derefs) { debug!("constrain_autoderefs(deref_expr=?, derefd_ty={}, derefs={}/{}", @@ -1259,16 +1225,12 @@ pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx, } +/// Invoked on any index expression that occurs. Checks that if this is a slice being indexed, the +/// lifetime of the pointer includes the deref expr. fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, index_expr: &ast::Expr, indexed_ty: Ty<'tcx>) { - /*! - * Invoked on any index expression that occurs. Checks that if - * this is a slice being indexed, the lifetime of the pointer - * includes the deref expr. - */ - debug!("constrain_index(index_expr=?, indexed_ty={}", rcx.fcx.infcx().ty_to_string(indexed_ty)); @@ -1286,18 +1248,14 @@ fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, } } +/// Guarantees that any lifetimes which appear in the type of the node `id` (after applying +/// adjustments) are valid for at least `minimum_lifetime` fn type_of_node_must_outlive<'a, 'tcx>( rcx: &mut Rcx<'a, 'tcx>, origin: infer::SubregionOrigin<'tcx>, id: ast::NodeId, minimum_lifetime: ty::Region) { - /*! - * Guarantees that any lifetimes which appear in the type of - * the node `id` (after applying adjustments) are valid for at - * least `minimum_lifetime` - */ - let tcx = rcx.fcx.tcx(); // Try to resolve the type. If we encounter an error, then typeck @@ -1314,14 +1272,10 @@ fn type_of_node_must_outlive<'a, 'tcx>( type_must_outlive(rcx, origin, ty, minimum_lifetime); } +/// Computes the guarantor for an expression `&base` and then ensures that the lifetime of the +/// resulting pointer is linked to the lifetime of its guarantor (if any). fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr, mutability: ast::Mutability, base: &ast::Expr) { - /*! - * Computes the guarantor for an expression `&base` and then - * ensures that the lifetime of the resulting pointer is linked - * to the lifetime of its guarantor (if any). - */ - debug!("link_addr_of(base=?)"); let cmt = { @@ -1331,13 +1285,10 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr, link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt); } +/// Computes the guarantors for any ref bindings in a `let` and +/// then ensures that the lifetime of the resulting pointer is +/// linked to the lifetime of the initialization expression. fn link_local(rcx: &Rcx, local: &ast::Local) { - /*! - * Computes the guarantors for any ref bindings in a `let` and - * then ensures that the lifetime of the resulting pointer is - * linked to the lifetime of the initialization expression. - */ - debug!("regionck::for_local()"); let init_expr = match local.init { None => { return; } @@ -1348,12 +1299,10 @@ fn link_local(rcx: &Rcx, local: &ast::Local) { link_pattern(rcx, mc, discr_cmt, &*local.pat); } +/// Computes the guarantors for any ref bindings in a match and +/// then ensures that the lifetime of the resulting pointer is +/// linked to the lifetime of its guarantor (if any). fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) { - /*! - * Computes the guarantors for any ref bindings in a match and - * then ensures that the lifetime of the resulting pointer is - * linked to the lifetime of its guarantor (if any). - */ debug!("regionck::for_match()"); let mc = mc::MemCategorizationContext::new(rcx); @@ -1366,15 +1315,12 @@ fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) { } } +/// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if +/// needed. fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, mc: mc::MemCategorizationContext>, discr_cmt: mc::cmt<'tcx>, root_pat: &ast::Pat) { - /*! - * Link lifetimes of any ref bindings in `root_pat` to - * the pointers found in the discriminant, if needed. - */ - let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| { match sub_pat.node { // `ref x` pattern @@ -1400,14 +1346,12 @@ fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, }); } +/// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being +/// autoref'd. fn link_autoref(rcx: &Rcx, expr: &ast::Expr, autoderefs: uint, autoref: &ty::AutoRef) { - /*! - * Link lifetime of borrowed pointer resulting from autoref - * to lifetimes in the value being autoref'd. - */ debug!("link_autoref(autoref={})", autoref); let mc = mc::MemCategorizationContext::new(rcx); @@ -1424,15 +1368,11 @@ fn link_autoref(rcx: &Rcx, } } +/// Computes the guarantor for cases where the `expr` is being passed by implicit reference and +/// must outlive `callee_scope`. fn link_by_ref(rcx: &Rcx, expr: &ast::Expr, callee_scope: CodeExtent) { - /*! - * Computes the guarantor for cases where the `expr` is - * being passed by implicit reference and must outlive - * `callee_scope`. - */ - let tcx = rcx.tcx(); debug!("link_by_ref(expr={}, callee_scope={})", expr.repr(tcx), callee_scope); @@ -1442,17 +1382,13 @@ fn link_by_ref(rcx: &Rcx, link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt); } +/// Like `link_region()`, except that the region is extracted from the type of `id`, which must be +/// some reference (`&T`, `&str`, etc). fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, span: Span, id: ast::NodeId, mutbl: ast::Mutability, cmt_borrowed: mc::cmt<'tcx>) { - /*! - * Like `link_region()`, except that the region is - * extracted from the type of `id`, which must be some - * reference (`&T`, `&str`, etc). - */ - let rptr_ty = rcx.resolve_node_type(id); if !ty::type_is_error(rptr_ty) { let tcx = rcx.fcx.ccx.tcx; @@ -1463,19 +1399,14 @@ fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, } } +/// Informs the inference engine that `borrow_cmt` is being borrowed with kind `borrow_kind` and +/// lifetime `borrow_region`. In order to ensure borrowck is satisfied, this may create constraints +/// between regions, as explained in `link_reborrowed_region()`. fn link_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, span: Span, borrow_region: ty::Region, borrow_kind: ty::BorrowKind, borrow_cmt: mc::cmt<'tcx>) { - /*! - * Informs the inference engine that `borrow_cmt` is being - * borrowed with kind `borrow_kind` and lifetime `borrow_region`. - * In order to ensure borrowck is satisfied, this may create - * constraints between regions, as explained in - * `link_reborrowed_region()`. - */ - let mut borrow_cmt = borrow_cmt; let mut borrow_kind = borrow_kind; @@ -1525,6 +1456,46 @@ fn link_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, } } +/// This is the most complicated case: the path being borrowed is +/// itself the referent of a borrowed pointer. Let me give an +/// example fragment of code to make clear(er) the situation: +/// +/// let r: &'a mut T = ...; // the original reference "r" has lifetime 'a +/// ... +/// &'z *r // the reborrow has lifetime 'z +/// +/// Now, in this case, our primary job is to add the inference +/// constraint that `'z <= 'a`. Given this setup, let's clarify the +/// parameters in (roughly) terms of the example: +/// +/// A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T` +/// borrow_region ^~ ref_region ^~ +/// borrow_kind ^~ ref_kind ^~ +/// ref_cmt ^ +/// +/// Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc). +/// +/// Unfortunately, there are some complications beyond the simple +/// scenario I just painted: +/// +/// 1. The reference `r` might in fact be a "by-ref" upvar. In that +/// case, we have two jobs. First, we are inferring whether this reference +/// should be an `&T`, `&mut T`, or `&uniq T` reference, and we must +/// adjust that based on this borrow (e.g., if this is an `&mut` borrow, +/// then `r` must be an `&mut` reference). Second, whenever we link +/// two regions (here, `'z <= 'a`), we supply a *cause*, and in this +/// case we adjust the cause to indicate that the reference being +/// "reborrowed" is itself an upvar. This provides a nicer error message +/// should something go wrong. +/// +/// 2. There may in fact be more levels of reborrowing. In the +/// example, I said the borrow was like `&'z *r`, but it might +/// in fact be a borrow like `&'z **q` where `q` has type `&'a +/// &'b mut T`. In that case, we want to ensure that `'z <= 'a` +/// and `'z <= 'b`. This is explained more below. +/// +/// The return value of this function indicates whether we need to +/// recurse and process `ref_cmt` (see case 2 above). fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, span: Span, borrow_region: ty::Region, @@ -1535,49 +1506,6 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, note: mc::Note) -> Option<(mc::cmt<'tcx>, ty::BorrowKind)> { - /*! - * This is the most complicated case: the path being borrowed is - * itself the referent of a borrowed pointer. Let me give an - * example fragment of code to make clear(er) the situation: - * - * let r: &'a mut T = ...; // the original reference "r" has lifetime 'a - * ... - * &'z *r // the reborrow has lifetime 'z - * - * Now, in this case, our primary job is to add the inference - * constraint that `'z <= 'a`. Given this setup, let's clarify the - * parameters in (roughly) terms of the example: - * - * A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T` - * borrow_region ^~ ref_region ^~ - * borrow_kind ^~ ref_kind ^~ - * ref_cmt ^ - * - * Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc). - * - * Unfortunately, there are some complications beyond the simple - * scenario I just painted: - * - * 1. The reference `r` might in fact be a "by-ref" upvar. In that - * case, we have two jobs. First, we are inferring whether this reference - * should be an `&T`, `&mut T`, or `&uniq T` reference, and we must - * adjust that based on this borrow (e.g., if this is an `&mut` borrow, - * then `r` must be an `&mut` reference). Second, whenever we link - * two regions (here, `'z <= 'a`), we supply a *cause*, and in this - * case we adjust the cause to indicate that the reference being - * "reborrowed" is itself an upvar. This provides a nicer error message - * should something go wrong. - * - * 2. There may in fact be more levels of reborrowing. In the - * example, I said the borrow was like `&'z *r`, but it might - * in fact be a borrow like `&'z **q` where `q` has type `&'a - * &'b mut T`. In that case, we want to ensure that `'z <= 'a` - * and `'z <= 'b`. This is explained more below. - * - * The return value of this function indicates whether we need to - * recurse and process `ref_cmt` (see case 2 above). - */ - // Possible upvar ID we may need later to create an entry in the // maybe link map. @@ -1715,27 +1643,19 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, } } +/// Adjusts the inferred borrow_kind as needed to account for upvars that are assigned to in an +/// assignment expression. fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx, lhs: &ast::Expr) { - /*! - * Adjusts the inferred borrow_kind as needed to account - * for upvars that are assigned to in an assignment - * expression. - */ - let mc = mc::MemCategorizationContext::new(rcx); let cmt = ignore_err!(mc.cat_expr(lhs)); adjust_upvar_borrow_kind_for_mut(rcx, cmt); } +/// Indicates that `cmt` is being directly mutated (e.g., assigned to). If cmt contains any by-ref +/// upvars, this implies that those upvars must be borrowed using an `&mut` borow. fn adjust_upvar_borrow_kind_for_mut<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, cmt: mc::cmt<'tcx>) { - /*! - * Indicates that `cmt` is being directly mutated (e.g., assigned - * to). If cmt contains any by-ref upvars, this implies that - * those upvars must be borrowed using an `&mut` borow. - */ - let mut cmt = cmt; loop { debug!("adjust_upvar_borrow_kind_for_mut(cmt={})", @@ -1834,16 +1754,12 @@ fn adjust_upvar_borrow_kind_for_unique<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, cmt: mc::c } } +/// Indicates that the borrow_kind of `outer_upvar_id` must permit a reborrowing with the +/// borrow_kind of `inner_upvar_id`. This occurs in nested closures, see comment above at the call +/// to this function. fn link_upvar_borrow_kind_for_nested_closures(rcx: &mut Rcx, inner_upvar_id: ty::UpvarId, outer_upvar_id: ty::UpvarId) { - /*! - * Indicates that the borrow_kind of `outer_upvar_id` must - * permit a reborrowing with the borrow_kind of `inner_upvar_id`. - * This occurs in nested closures, see comment above at the call to - * this function. - */ - debug!("link_upvar_borrow_kind: inner_upvar_id={} outer_upvar_id={}", inner_upvar_id, outer_upvar_id); @@ -1867,18 +1783,14 @@ fn adjust_upvar_borrow_kind_for_loan(rcx: &Rcx, adjust_upvar_borrow_kind(rcx, upvar_id, upvar_borrow, kind) } +/// We infer the borrow_kind with which to borrow upvars in a stack closure. The borrow_kind +/// basically follows a lattice of `imm < unique-imm < mut`, moving from left to right as needed +/// (but never right to left). Here the argument `mutbl` is the borrow_kind that is required by +/// some particular use. fn adjust_upvar_borrow_kind(rcx: &Rcx, upvar_id: ty::UpvarId, upvar_borrow: &mut ty::UpvarBorrow, kind: ty::BorrowKind) { - /*! - * We infer the borrow_kind with which to borrow upvars in a stack - * closure. The borrow_kind basically follows a lattice of - * `imm < unique-imm < mut`, moving from left to right as needed (but never - * right to left). Here the argument `mutbl` is the borrow_kind that - * is required by some particular use. - */ - debug!("adjust_upvar_borrow_kind: id={} kind=({} -> {})", upvar_id, upvar_borrow.kind, kind); @@ -1911,15 +1823,12 @@ fn adjust_upvar_borrow_kind(rcx: &Rcx, } } +/// Ensures that all borrowed data reachable via `ty` outlives `region`. fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, origin: infer::SubregionOrigin<'tcx>, ty: Ty<'tcx>, region: ty::Region) { - /*! - * Ensures that all borrowed data reachable via `ty` outlives `region`. - */ - debug!("type_must_outlive(ty={}, region={})", ty.repr(rcx.tcx()), region.repr(rcx.tcx())); diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 9fd24c4ee78..55214618aa9 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -33,18 +33,14 @@ struct Wf<'a, 'tcx: 'a> { out: Vec>, } +/// This routine computes the well-formedness constraints that must hold for the type `ty` to +/// appear in a context with lifetime `outer_region` pub fn region_wf_constraints<'tcx>( tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, outer_region: ty::Region) -> Vec> { - /*! - * This routine computes the well-formedness constraints that must - * hold for the type `ty` to appear in a context with lifetime - * `outer_region` - */ - let mut stack = Vec::new(); stack.push((outer_region, None)); let mut wf = Wf { tcx: tcx, @@ -168,12 +164,9 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { self.stack.pop().unwrap(); } + /// Pushes a constraint that `r_b` must outlive the top region on the stack. fn push_region_constraint_from_top(&mut self, r_b: ty::Region) { - /*! - * Pushes a constraint that `r_b` must outlive the - * top region on the stack. - */ // Indicates that we have found borrowed content with a lifetime // of at least `r_b`. This adds a constraint that `r_b` must @@ -192,30 +185,26 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { self.push_sub_region_constraint(opt_ty, r_a, r_b); } + /// Pushes a constraint that `r_a <= r_b`, due to `opt_ty` fn push_sub_region_constraint(&mut self, opt_ty: Option>, r_a: ty::Region, r_b: ty::Region) { - /*! Pushes a constraint that `r_a <= r_b`, due to `opt_ty` */ self.out.push(RegionSubRegionConstraint(opt_ty, r_a, r_b)); } + /// Pushes a constraint that `param_ty` must outlive the top region on the stack. fn push_param_constraint_from_top(&mut self, param_ty: ty::ParamTy) { - /*! - * Pushes a constraint that `param_ty` must outlive the - * top region on the stack. - */ - let &(region, opt_ty) = self.stack.last().unwrap(); self.push_param_constraint(region, opt_ty, param_ty); } + /// Pushes a constraint that `region <= param_ty`, due to `opt_ty` fn push_param_constraint(&mut self, region: ty::Region, opt_ty: Option>, param_ty: ty::ParamTy) { - /*! Pushes a constraint that `region <= param_ty`, due to `opt_ty` */ self.out.push(RegionSubParamConstraint(opt_ty, region, param_ty)); } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 1619a4224f9..51978a01f71 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -168,17 +168,14 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, } } - // Returns a vec of error messages. If hte vec is empty - no errors! + /// Returns a vec of error messages. If hte vec is empty - no errors! + /// + /// There are some limitations to calling functions through an object, because (a) the self + /// type is not known (that's the whole point of a trait instance, after all, to obscure the + /// self type) and (b) the call must go through a vtable and hence cannot be monomorphized. fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>, method: &ty::Method<'tcx>) -> Vec { - /*! - * There are some limitations to calling functions through an - * object, because (a) the self type is not known - * (that's the whole point of a trait instance, after all, to - * obscure the self type) and (b) the call must go through a - * vtable and hence cannot be monomorphized. - */ let mut msgs = Vec::new(); let method_name = method.name.repr(tcx); @@ -455,8 +452,8 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } +/// Select as many obligations as we can at present. pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) { - /*! Select as many obligations as we can at present. */ match fcx.inh.fulfillment_cx @@ -468,14 +465,10 @@ pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) { } } +/// Try to select any fcx obligation that we haven't tried yet, in an effort to improve inference. +/// You could just call `select_fcx_obligations_where_possible` except that it leads to repeated +/// work. pub fn select_new_fcx_obligations(fcx: &FnCtxt) { - /*! - * Try to select any fcx obligation that we haven't tried yet, - * in an effort to improve inference. You could just call - * `select_fcx_obligations_where_possible` except that it leads - * to repeated work. - */ - match fcx.inh.fulfillment_cx .borrow_mut() diff --git a/src/librustc/middle/typeck/check/wf.rs b/src/librustc/middle/typeck/check/wf.rs index d9c6c3cb626..502e37aa9f3 100644 --- a/src/librustc/middle/typeck/check/wf.rs +++ b/src/librustc/middle/typeck/check/wf.rs @@ -38,24 +38,18 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { CheckTypeWellFormedVisitor { ccx: ccx, cache: HashSet::new() } } + /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are + /// well-formed, meaning that they do not require any constraints not declared in the struct + /// definition itself. For example, this definition would be illegal: + /// + /// struct Ref<'a, T> { x: &'a T } + /// + /// because the type did not declare that `T:'a`. + /// + /// We do this check as a pre-pass before checking fn bodies because if these constraints are + /// not included it frequently leads to confusing errors in fn bodies. So it's better to check + /// the types first. fn check_item_well_formed(&mut self, item: &ast::Item) { - /*! - * Checks that the field types (in a struct def'n) or - * argument types (in an enum def'n) are well-formed, - * meaning that they do not require any constraints not - * declared in the struct definition itself. - * For example, this definition would be illegal: - * - * struct Ref<'a, T> { x: &'a T } - * - * because the type did not declare that `T:'a`. - * - * We do this check as a pre-pass before checking fn bodies - * because if these constraints are not included it frequently - * leads to confusing errors in fn bodies. So it's better to check - * the types first. - */ - let ccx = self.ccx; debug!("check_item_well_formed(it.id={}, it.ident={})", item.id, @@ -107,16 +101,12 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { regionck::regionck_item(&fcx, item); } + /// In a type definition, we check that to ensure that the types of the fields are well-formed. fn check_type_defn(&mut self, item: &ast::Item, lookup_fields: for<'fcx> |&FnCtxt<'fcx, 'tcx>| -> Vec>) { - /*! - * In a type definition, we check that to ensure that the types of the fields are - * well-formed. - */ - self.with_fcx(item, |this, fcx| { let variants = lookup_fields(fcx); let mut bounds_checker = BoundsChecker::new(fcx, @@ -282,22 +272,16 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> { cache: cache, binding_count: 0 } } + /// Given a trait ref like `A : Trait`, where `Trait` is defined as (say): + /// + /// trait Trait : Copy { ... } + /// + /// This routine will check that `B : OtherTrait` and `A : Trait`. It will also recursively + /// check that the types `A` and `B` are well-formed. + /// + /// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated + /// to the point where impl `A : Trait` is implemented). pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) { - /*! - * Given a trait ref like `A : Trait`, where `Trait` is - * defined as (say): - * - * trait Trait : Copy { ... } - * - * This routine will check that `B : OtherTrait` and `A : - * Trait`. It will also recursively check that the types - * `A` and `B` are well-formed. - * - * Note that it does not (currently, at least) - * check that `A : Copy` (that check is delegated to the point - * where impl `A : Trait` is implemented). - */ - let trait_def = ty::lookup_trait_def(self.fcx.tcx(), trait_ref.def_id); let bounds = trait_def.generics.to_bounds(self.tcx(), &trait_ref.substs); diff --git a/src/librustc/middle/typeck/coherence/mod.rs b/src/librustc/middle/typeck/coherence/mod.rs index 1f32110a093..758608b79c2 100644 --- a/src/librustc/middle/typeck/coherence/mod.rs +++ b/src/librustc/middle/typeck/coherence/mod.rs @@ -477,17 +477,13 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } } +/// Substitutes the values for the receiver's type parameters that are found in method, leaving the +/// method's type parameters intact. pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>, method: &ty::Method<'tcx>) -> subst::Substs<'tcx> { - /*! - * Substitutes the values for the receiver's type parameters - * that are found in method, leaving the method's type parameters - * intact. - */ - let meth_tps: Vec = method.generics.types.get_slice(subst::FnSpace) .iter() diff --git a/src/librustc/middle/typeck/coherence/orphan.rs b/src/librustc/middle/typeck/coherence/orphan.rs index 57ce7f79e03..dc3afaae35f 100644 --- a/src/librustc/middle/typeck/coherence/orphan.rs +++ b/src/librustc/middle/typeck/coherence/orphan.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Orphan checker: every impl either implements a trait defined in this - * crate or pertains to a type defined in this crate. - */ +//! Orphan checker: every impl either implements a trait defined in this +//! crate or pertains to a type defined in this crate. use middle::traits; use middle::ty; diff --git a/src/librustc/middle/typeck/coherence/overlap.rs b/src/librustc/middle/typeck/coherence/overlap.rs index 933c2c81ac2..9f10a58f458 100644 --- a/src/librustc/middle/typeck/coherence/overlap.rs +++ b/src/librustc/middle/typeck/coherence/overlap.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Overlap: No two impls for the same trait are implemented for the - * same type. - */ +//! Overlap: No two impls for the same trait are implemented for the +//! same type. use middle::traits; use middle::ty; diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 13a0bf0bdcb..3a62978ed00 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1944,6 +1944,9 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, def } +/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or +/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the +/// built-in trait (formerly known as kind): Send. fn compute_bounds<'tcx,AC>(this: &AC, name_of_bounded_thing: ast::Name, param_ty: ty::ParamTy, @@ -1953,13 +1956,6 @@ fn compute_bounds<'tcx,AC>(this: &AC, where_clause: &ast::WhereClause) -> ty::ParamBounds<'tcx> where AC: AstConv<'tcx> { - /*! - * Translate the AST's notion of ty param bounds (which are an - * enum consisting of a newtyped Ty or a region) to ty's - * notion of ty param bounds, which can either be user-defined - * traits, or the built-in trait (formerly known as kind): Send. - */ - let mut param_bounds = conv_param_bounds(this, span, param_ty, @@ -2040,16 +2036,13 @@ fn conv_param_bounds<'tcx,AC>(this: &AC, } } +/// Merges the bounds declared on a type parameter with those found from where clauses into a +/// single list. fn merge_param_bounds<'a>(tcx: &ty::ctxt, param_ty: ty::ParamTy, ast_bounds: &'a [ast::TyParamBound], where_clause: &'a ast::WhereClause) -> Vec<&'a ast::TyParamBound> { - /*! - * Merges the bounds declared on a type parameter with those - * found from where clauses into a single list. - */ - let mut result = Vec::new(); for ast_bound in ast_bounds.iter() { diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index 49ac7178eb8..51f8668692e 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -8,61 +8,57 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -# Type Coercion - -Under certain circumstances we will coerce from one type to another, -for example by auto-borrowing. This occurs in situations where the -compiler has a firm 'expected type' that was supplied from the user, -and where the actual type is similar to that expected type in purpose -but not in representation (so actual subtyping is inappropriate). - -## Reborrowing - -Note that if we are expecting a reference, we will *reborrow* -even if the argument provided was already a reference. This is -useful for freezing mut/const things (that is, when the expected is &T -but you have &const T or &mut T) and also for avoiding the linearity -of mut things (when the expected is &mut T and you have &mut T). See -the various `src/test/run-pass/coerce-reborrow-*.rs` tests for -examples of where this is useful. - -## Subtle note - -When deciding what type coercions to consider, we do not attempt to -resolve any type variables we may encounter. This is because `b` -represents the expected type "as the user wrote it", meaning that if -the user defined a generic function like - - fn foo(a: A, b: A) { ... } - -and then we wrote `foo(&1, @2)`, we will not auto-borrow -either argument. In older code we went to some lengths to -resolve the `b` variable, which could mean that we'd -auto-borrow later arguments but not earlier ones, which -seems very confusing. - -## Subtler note - -However, right now, if the user manually specifies the -values for the type variables, as so: - - foo::<&int>(@1, @2) - -then we *will* auto-borrow, because we can't distinguish this from a -function that declared `&int`. This is inconsistent but it's easiest -at the moment. The right thing to do, I think, is to consider the -*unsubstituted* type when deciding whether to auto-borrow, but the -*substituted* type when considering the bounds and so forth. But most -of our methods don't give access to the unsubstituted type, and -rightly so because they'd be error-prone. So maybe the thing to do is -to actually determine the kind of coercions that should occur -separately and pass them in. Or maybe it's ok as is. Anyway, it's -sort of a minor point so I've opted to leave it for later---after all -we may want to adjust precisely when coercions occur. - -*/ +//! # Type Coercion +//! +//! Under certain circumstances we will coerce from one type to another, +//! for example by auto-borrowing. This occurs in situations where the +//! compiler has a firm 'expected type' that was supplied from the user, +//! and where the actual type is similar to that expected type in purpose +//! but not in representation (so actual subtyping is inappropriate). +//! +//! ## Reborrowing +//! +//! Note that if we are expecting a reference, we will *reborrow* +//! even if the argument provided was already a reference. This is +//! useful for freezing mut/const things (that is, when the expected is &T +//! but you have &const T or &mut T) and also for avoiding the linearity +//! of mut things (when the expected is &mut T and you have &mut T). See +//! the various `src/test/run-pass/coerce-reborrow-*.rs` tests for +//! examples of where this is useful. +//! +//! ## Subtle note +//! +//! When deciding what type coercions to consider, we do not attempt to +//! resolve any type variables we may encounter. This is because `b` +//! represents the expected type "as the user wrote it", meaning that if +//! the user defined a generic function like +//! +//! fn foo(a: A, b: A) { ... } +//! +//! and then we wrote `foo(&1, @2)`, we will not auto-borrow +//! either argument. In older code we went to some lengths to +//! resolve the `b` variable, which could mean that we'd +//! auto-borrow later arguments but not earlier ones, which +//! seems very confusing. +//! +//! ## Subtler note +//! +//! However, right now, if the user manually specifies the +//! values for the type variables, as so: +//! +//! foo::<&int>(@1, @2) +//! +//! then we *will* auto-borrow, because we can't distinguish this from a +//! function that declared `&int`. This is inconsistent but it's easiest +//! at the moment. The right thing to do, I think, is to consider the +//! *unsubstituted* type when deciding whether to auto-borrow, but the +//! *substituted* type when considering the bounds and so forth. But most +//! of our methods don't give access to the unsubstituted type, and +//! rightly so because they'd be error-prone. So maybe the thing to do is +//! to actually determine the kind of coercions that should occur +//! separately and pass them in. Or maybe it's ok as is. Anyway, it's +//! sort of a minor point so I've opted to leave it for later---after all +//! we may want to adjust precisely when coercions occur. use middle::subst; use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe}; @@ -512,14 +508,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } + /// Attempts to coerce from a bare Rust function (`extern "Rust" fn`) into a closure or a + /// `proc`. fn coerce_from_bare_fn(&self, a: Ty<'tcx>, fn_ty_a: &ty::BareFnTy<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { - /*! - * - * Attempts to coerce from a bare Rust function (`extern - * "Rust" fn`) into a closure or a `proc`. - */ - self.unpack_actual_value(b, |sty_b| { debug!("coerce_from_bare_fn(a={}, b={})", diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 763f204dc98..ba6ae00b667 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -642,21 +642,16 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> { Ok(()) } + /// Attempts to generalize `ty` for the type variable `for_vid`. This checks for cycle -- that + /// is, whether the type `ty` references `for_vid`. If `make_region_vars` is true, it will also + /// replace all regions with fresh variables. Returns `ty_err` in the case of a cycle, `Ok` + /// otherwise. fn generalize(&self, ty: Ty<'tcx>, for_vid: ty::TyVid, make_region_vars: bool) -> cres<'tcx, Ty<'tcx>> { - /*! - * Attempts to generalize `ty` for the type variable - * `for_vid`. This checks for cycle -- that is, whether the - * type `ty` references `for_vid`. If `make_region_vars` is - * true, it will also replace all regions with fresh - * variables. Returns `ty_err` in the case of a cycle, `Ok` - * otherwise. - */ - let mut generalize = Generalizer { infcx: self.infcx, span: self.trace.origin.span(), for_vid: for_vid, diff --git a/src/librustc/middle/typeck/infer/doc.rs b/src/librustc/middle/typeck/infer/doc.rs index 886550a3b24..0e3cc5f68c8 100644 --- a/src/librustc/middle/typeck/infer/doc.rs +++ b/src/librustc/middle/typeck/infer/doc.rs @@ -8,244 +8,240 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -# Type inference engine - -This is loosely based on standard HM-type inference, but with an -extension to try and accommodate subtyping. There is nothing -principled about this extension; it's sound---I hope!---but it's a -heuristic, ultimately, and does not guarantee that it finds a valid -typing even if one exists (in fact, there are known scenarios where it -fails, some of which may eventually become problematic). - -## Key idea - -The main change is that each type variable T is associated with a -lower-bound L and an upper-bound U. L and U begin as bottom and top, -respectively, but gradually narrow in response to new constraints -being introduced. When a variable is finally resolved to a concrete -type, it can (theoretically) select any type that is a supertype of L -and a subtype of U. - -There are several critical invariants which we maintain: - -- the upper-bound of a variable only becomes lower and the lower-bound - only becomes higher over time; -- the lower-bound L is always a subtype of the upper bound U; -- the lower-bound L and upper-bound U never refer to other type variables, - but only to types (though those types may contain type variables). - -> An aside: if the terms upper- and lower-bound confuse you, think of -> "supertype" and "subtype". The upper-bound is a "supertype" -> (super=upper in Latin, or something like that anyway) and the lower-bound -> is a "subtype" (sub=lower in Latin). I find it helps to visualize -> a simple class hierarchy, like Java minus interfaces and -> primitive types. The class Object is at the root (top) and other -> types lie in between. The bottom type is then the Null type. -> So the tree looks like: -> -> ```text -> Object -> / \ -> String Other -> \ / -> (null) -> ``` -> -> So the upper bound type is the "supertype" and the lower bound is the -> "subtype" (also, super and sub mean upper and lower in Latin, or something -> like that anyway). - -## Satisfying constraints - -At a primitive level, there is only one form of constraint that the -inference understands: a subtype relation. So the outside world can -say "make type A a subtype of type B". If there are variables -involved, the inferencer will adjust their upper- and lower-bounds as -needed to ensure that this relation is satisfied. (We also allow "make -type A equal to type B", but this is translated into "A <: B" and "B -<: A") - -As stated above, we always maintain the invariant that type bounds -never refer to other variables. This keeps the inference relatively -simple, avoiding the scenario of having a kind of graph where we have -to pump constraints along and reach a fixed point, but it does impose -some heuristics in the case where the user is relating two type -variables A <: B. - -Combining two variables such that variable A will forever be a subtype -of variable B is the trickiest part of the algorithm because there is -often no right choice---that is, the right choice will depend on -future constraints which we do not yet know. The problem comes about -because both A and B have bounds that can be adjusted in the future. -Let's look at some of the cases that can come up. - -Imagine, to start, the best case, where both A and B have an upper and -lower bound (that is, the bounds are not top nor bot respectively). In -that case, if we're lucky, A.ub <: B.lb, and so we know that whatever -A and B should become, they will forever have the desired subtyping -relation. We can just leave things as they are. - -### Option 1: Unify - -However, suppose that A.ub is *not* a subtype of B.lb. In -that case, we must make a decision. One option is to unify A -and B so that they are one variable whose bounds are: - - UB = GLB(A.ub, B.ub) - LB = LUB(A.lb, B.lb) - -(Note that we will have to verify that LB <: UB; if it does not, the -types are not intersecting and there is an error) In that case, A <: B -holds trivially because A==B. However, we have now lost some -flexibility, because perhaps the user intended for A and B to end up -as different types and not the same type. - -Pictorally, what this does is to take two distinct variables with -(hopefully not completely) distinct type ranges and produce one with -the intersection. - -```text - B.ub B.ub - /\ / - A.ub / \ A.ub / - / \ / \ \ / - / X \ UB - / / \ \ / \ - / / / \ / / - \ \ / / \ / - \ X / LB - \ / \ / / \ - \ / \ / / \ - A.lb B.lb A.lb B.lb -``` - - -### Option 2: Relate UB/LB - -Another option is to keep A and B as distinct variables but set their -bounds in such a way that, whatever happens, we know that A <: B will hold. -This can be achieved by ensuring that A.ub <: B.lb. In practice there -are two ways to do that, depicted pictorally here: - -```text - Before Option #1 Option #2 - - B.ub B.ub B.ub - /\ / \ / \ - A.ub / \ A.ub /(B')\ A.ub /(B')\ - / \ / \ \ / / \ / / - / X \ __UB____/ UB / - / / \ \ / | | / - / / / \ / | | / - \ \ / / /(A')| | / - \ X / / LB ______LB/ - \ / \ / / / \ / (A')/ \ - \ / \ / \ / \ \ / \ - A.lb B.lb A.lb B.lb A.lb B.lb -``` - -In these diagrams, UB and LB are defined as before. As you can see, -the new ranges `A'` and `B'` are quite different from the range that -would be produced by unifying the variables. - -### What we do now - -Our current technique is to *try* (transactionally) to relate the -existing bounds of A and B, if there are any (i.e., if `UB(A) != top -&& LB(B) != bot`). If that succeeds, we're done. If it fails, then -we merge A and B into same variable. - -This is not clearly the correct course. For example, if `UB(A) != -top` but `LB(B) == bot`, we could conceivably set `LB(B)` to `UB(A)` -and leave the variables unmerged. This is sometimes the better -course, it depends on the program. - -The main case which fails today that I would like to support is: - -```text -fn foo(x: T, y: T) { ... } - -fn bar() { - let x: @mut int = @mut 3; - let y: @int = @3; - foo(x, y); -} -``` - -In principle, the inferencer ought to find that the parameter `T` to -`foo(x, y)` is `@const int`. Today, however, it does not; this is -because the type variable `T` is merged with the type variable for -`X`, and thus inherits its UB/LB of `@mut int`. This leaves no -flexibility for `T` to later adjust to accommodate `@int`. - -### What to do when not all bounds are present - -In the prior discussion we assumed that A.ub was not top and B.lb was -not bot. Unfortunately this is rarely the case. Often type variables -have "lopsided" bounds. For example, if a variable in the program has -been initialized but has not been used, then its corresponding type -variable will have a lower bound but no upper bound. When that -variable is then used, we would like to know its upper bound---but we -don't have one! In this case we'll do different things depending on -how the variable is being used. - -## Transactional support - -Whenever we adjust merge variables or adjust their bounds, we always -keep a record of the old value. This allows the changes to be undone. - -## Regions - -I've only talked about type variables here, but region variables -follow the same principle. They have upper- and lower-bounds. A -region A is a subregion of a region B if A being valid implies that B -is valid. This basically corresponds to the block nesting structure: -the regions for outer block scopes are superregions of those for inner -block scopes. - -## Integral and floating-point type variables - -There is a third variety of type variable that we use only for -inferring the types of unsuffixed integer literals. Integral type -variables differ from general-purpose type variables in that there's -no subtyping relationship among the various integral types, so instead -of associating each variable with an upper and lower bound, we just -use simple unification. Each integer variable is associated with at -most one integer type. Floating point types are handled similarly to -integral types. - -## GLB/LUB - -Computing the greatest-lower-bound and least-upper-bound of two -types/regions is generally straightforward except when type variables -are involved. In that case, we follow a similar "try to use the bounds -when possible but otherwise merge the variables" strategy. In other -words, `GLB(A, B)` where `A` and `B` are variables will often result -in `A` and `B` being merged and the result being `A`. - -## Type coercion - -We have a notion of assignability which differs somewhat from -subtyping; in particular it may cause region borrowing to occur. See -the big comment later in this file on Type Coercion for specifics. - -### In conclusion - -I showed you three ways to relate `A` and `B`. There are also more, -of course, though I'm not sure if there are any more sensible options. -The main point is that there are various options, each of which -produce a distinct range of types for `A` and `B`. Depending on what -the correct values for A and B are, one of these options will be the -right choice: but of course we don't know the right values for A and B -yet, that's what we're trying to find! In our code, we opt to unify -(Option #1). - -# Implementation details - -We make use of a trait-like implementation strategy to consolidate -duplicated code between subtypes, GLB, and LUB computations. See the -section on "Type Combining" below for details. - -*/ +//! # Type inference engine +//! +//! This is loosely based on standard HM-type inference, but with an +//! extension to try and accommodate subtyping. There is nothing +//! principled about this extension; it's sound---I hope!---but it's a +//! heuristic, ultimately, and does not guarantee that it finds a valid +//! typing even if one exists (in fact, there are known scenarios where it +//! fails, some of which may eventually become problematic). +//! +//! ## Key idea +//! +//! The main change is that each type variable T is associated with a +//! lower-bound L and an upper-bound U. L and U begin as bottom and top, +//! respectively, but gradually narrow in response to new constraints +//! being introduced. When a variable is finally resolved to a concrete +//! type, it can (theoretically) select any type that is a supertype of L +//! and a subtype of U. +//! +//! There are several critical invariants which we maintain: +//! +//! - the upper-bound of a variable only becomes lower and the lower-bound +//! only becomes higher over time; +//! - the lower-bound L is always a subtype of the upper bound U; +//! - the lower-bound L and upper-bound U never refer to other type variables, +//! but only to types (though those types may contain type variables). +//! +//! > An aside: if the terms upper- and lower-bound confuse you, think of +//! > "supertype" and "subtype". The upper-bound is a "supertype" +//! > (super=upper in Latin, or something like that anyway) and the lower-bound +//! > is a "subtype" (sub=lower in Latin). I find it helps to visualize +//! > a simple class hierarchy, like Java minus interfaces and +//! > primitive types. The class Object is at the root (top) and other +//! > types lie in between. The bottom type is then the Null type. +//! > So the tree looks like: +//! > +//! > ```text +//! > Object +//! > / \ +//! > String Other +//! > \ / +//! > (null) +//! > ``` +//! > +//! > So the upper bound type is the "supertype" and the lower bound is the +//! > "subtype" (also, super and sub mean upper and lower in Latin, or something +//! > like that anyway). +//! +//! ## Satisfying constraints +//! +//! At a primitive level, there is only one form of constraint that the +//! inference understands: a subtype relation. So the outside world can +//! say "make type A a subtype of type B". If there are variables +//! involved, the inferencer will adjust their upper- and lower-bounds as +//! needed to ensure that this relation is satisfied. (We also allow "make +//! type A equal to type B", but this is translated into "A <: B" and "B +//! <: A") +//! +//! As stated above, we always maintain the invariant that type bounds +//! never refer to other variables. This keeps the inference relatively +//! simple, avoiding the scenario of having a kind of graph where we have +//! to pump constraints along and reach a fixed point, but it does impose +//! some heuristics in the case where the user is relating two type +//! variables A <: B. +//! +//! Combining two variables such that variable A will forever be a subtype +//! of variable B is the trickiest part of the algorithm because there is +//! often no right choice---that is, the right choice will depend on +//! future constraints which we do not yet know. The problem comes about +//! because both A and B have bounds that can be adjusted in the future. +//! Let's look at some of the cases that can come up. +//! +//! Imagine, to start, the best case, where both A and B have an upper and +//! lower bound (that is, the bounds are not top nor bot respectively). In +//! that case, if we're lucky, A.ub <: B.lb, and so we know that whatever +//! A and B should become, they will forever have the desired subtyping +//! relation. We can just leave things as they are. +//! +//! ### Option 1: Unify +//! +//! However, suppose that A.ub is *not* a subtype of B.lb. In +//! that case, we must make a decision. One option is to unify A +//! and B so that they are one variable whose bounds are: +//! +//! UB = GLB(A.ub, B.ub) +//! LB = LUB(A.lb, B.lb) +//! +//! (Note that we will have to verify that LB <: UB; if it does not, the +//! types are not intersecting and there is an error) In that case, A <: B +//! holds trivially because A==B. However, we have now lost some +//! flexibility, because perhaps the user intended for A and B to end up +//! as different types and not the same type. +//! +//! Pictorally, what this does is to take two distinct variables with +//! (hopefully not completely) distinct type ranges and produce one with +//! the intersection. +//! +//! ```text +//! B.ub B.ub +//! /\ / +//! A.ub / \ A.ub / +//! / \ / \ \ / +//! / X \ UB +//! / / \ \ / \ +//! / / / \ / / +//! \ \ / / \ / +//! \ X / LB +//! \ / \ / / \ +//! \ / \ / / \ +//! A.lb B.lb A.lb B.lb +//! ``` +//! +//! +//! ### Option 2: Relate UB/LB +//! +//! Another option is to keep A and B as distinct variables but set their +//! bounds in such a way that, whatever happens, we know that A <: B will hold. +//! This can be achieved by ensuring that A.ub <: B.lb. In practice there +//! are two ways to do that, depicted pictorally here: +//! +//! ```text +//! Before Option #1 Option #2 +//! +//! B.ub B.ub B.ub +//! /\ / \ / \ +//! A.ub / \ A.ub /(B')\ A.ub /(B')\ +//! / \ / \ \ / / \ / / +//! / X \ __UB____/ UB / +//! / / \ \ / | | / +//! / / / \ / | | / +//! \ \ / / /(A')| | / +//! \ X / / LB ______LB/ +//! \ / \ / / / \ / (A')/ \ +//! \ / \ / \ / \ \ / \ +//! A.lb B.lb A.lb B.lb A.lb B.lb +//! ``` +//! +//! In these diagrams, UB and LB are defined as before. As you can see, +//! the new ranges `A'` and `B'` are quite different from the range that +//! would be produced by unifying the variables. +//! +//! ### What we do now +//! +//! Our current technique is to *try* (transactionally) to relate the +//! existing bounds of A and B, if there are any (i.e., if `UB(A) != top +//! && LB(B) != bot`). If that succeeds, we're done. If it fails, then +//! we merge A and B into same variable. +//! +//! This is not clearly the correct course. For example, if `UB(A) != +//! top` but `LB(B) == bot`, we could conceivably set `LB(B)` to `UB(A)` +//! and leave the variables unmerged. This is sometimes the better +//! course, it depends on the program. +//! +//! The main case which fails today that I would like to support is: +//! +//! ```text +//! fn foo(x: T, y: T) { ... } +//! +//! fn bar() { +//! let x: @mut int = @mut 3; +//! let y: @int = @3; +//! foo(x, y); +//! } +//! ``` +//! +//! In principle, the inferencer ought to find that the parameter `T` to +//! `foo(x, y)` is `@const int`. Today, however, it does not; this is +//! because the type variable `T` is merged with the type variable for +//! `X`, and thus inherits its UB/LB of `@mut int`. This leaves no +//! flexibility for `T` to later adjust to accommodate `@int`. +//! +//! ### What to do when not all bounds are present +//! +//! In the prior discussion we assumed that A.ub was not top and B.lb was +//! not bot. Unfortunately this is rarely the case. Often type variables +//! have "lopsided" bounds. For example, if a variable in the program has +//! been initialized but has not been used, then its corresponding type +//! variable will have a lower bound but no upper bound. When that +//! variable is then used, we would like to know its upper bound---but we +//! don't have one! In this case we'll do different things depending on +//! how the variable is being used. +//! +//! ## Transactional support +//! +//! Whenever we adjust merge variables or adjust their bounds, we always +//! keep a record of the old value. This allows the changes to be undone. +//! +//! ## Regions +//! +//! I've only talked about type variables here, but region variables +//! follow the same principle. They have upper- and lower-bounds. A +//! region A is a subregion of a region B if A being valid implies that B +//! is valid. This basically corresponds to the block nesting structure: +//! the regions for outer block scopes are superregions of those for inner +//! block scopes. +//! +//! ## Integral and floating-point type variables +//! +//! There is a third variety of type variable that we use only for +//! inferring the types of unsuffixed integer literals. Integral type +//! variables differ from general-purpose type variables in that there's +//! no subtyping relationship among the various integral types, so instead +//! of associating each variable with an upper and lower bound, we just +//! use simple unification. Each integer variable is associated with at +//! most one integer type. Floating point types are handled similarly to +//! integral types. +//! +//! ## GLB/LUB +//! +//! Computing the greatest-lower-bound and least-upper-bound of two +//! types/regions is generally straightforward except when type variables +//! are involved. In that case, we follow a similar "try to use the bounds +//! when possible but otherwise merge the variables" strategy. In other +//! words, `GLB(A, B)` where `A` and `B` are variables will often result +//! in `A` and `B` being merged and the result being `A`. +//! +//! ## Type coercion +//! +//! We have a notion of assignability which differs somewhat from +//! subtyping; in particular it may cause region borrowing to occur. See +//! the big comment later in this file on Type Coercion for specifics. +//! +//! ### In conclusion +//! +//! I showed you three ways to relate `A` and `B`. There are also more, +//! of course, though I'm not sure if there are any more sensible options. +//! The main point is that there are various options, each of which +//! produce a distinct range of types for `A` and `B`. Depending on what +//! the correct values for A and B are, one of these options will be the +//! right choice: but of course we don't know the right values for A and B +//! yet, that's what we're trying to find! In our code, we opt to unify +//! (Option #1). +//! +//! # Implementation details +//! +//! We make use of a trait-like implementation strategy to consolidate +//! duplicated code between subtypes, GLB, and LUB computations. See the +//! section on "Type Combining" below for details. diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index bc36a2bd801..abc68852f4b 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -8,56 +8,53 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Error Reporting Code for the inference engine - -Because of the way inference, and in particular region inference, -works, it often happens that errors are not detected until far after -the relevant line of code has been type-checked. Therefore, there is -an elaborate system to track why a particular constraint in the -inference graph arose so that we can explain to the user what gave -rise to a particular error. - -The basis of the system are the "origin" types. An "origin" is the -reason that a constraint or inference variable arose. There are -different "origin" enums for different kinds of constraints/variables -(e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has -a span, but also more information so that we can generate a meaningful -error message. - -Having a catalogue of all the different reasons an error can arise is -also useful for other reasons, like cross-referencing FAQs etc, though -we are not really taking advantage of this yet. - -# Region Inference - -Region inference is particularly tricky because it always succeeds "in -the moment" and simply registers a constraint. Then, at the end, we -can compute the full graph and report errors, so we need to be able to -store and later report what gave rise to the conflicting constraints. - -# Subtype Trace - -Determing whether `T1 <: T2` often involves a number of subtypes and -subconstraints along the way. A "TypeTrace" is an extended version -of an origin that traces the types and other values that were being -compared. It is not necessarily comprehensive (in fact, at the time of -this writing it only tracks the root values being compared) but I'd -like to extend it to include significant "waypoints". For example, if -you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2 -<: T4` fails, I'd like the trace to include enough information to say -"in the 2nd element of the tuple". Similarly, failures when comparing -arguments or return types in fn types should be able to cite the -specific position, etc. - -# Reality vs plan - -Of course, there is still a LOT of code in typeck that has yet to be -ported to this system, and which relies on string concatenation at the -time of error detection. - -*/ +//! Error Reporting Code for the inference engine +//! +//! Because of the way inference, and in particular region inference, +//! works, it often happens that errors are not detected until far after +//! the relevant line of code has been type-checked. Therefore, there is +//! an elaborate system to track why a particular constraint in the +//! inference graph arose so that we can explain to the user what gave +//! rise to a particular error. +//! +//! The basis of the system are the "origin" types. An "origin" is the +//! reason that a constraint or inference variable arose. There are +//! different "origin" enums for different kinds of constraints/variables +//! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has +//! a span, but also more information so that we can generate a meaningful +//! error message. +//! +//! Having a catalogue of all the different reasons an error can arise is +//! also useful for other reasons, like cross-referencing FAQs etc, though +//! we are not really taking advantage of this yet. +//! +//! # Region Inference +//! +//! Region inference is particularly tricky because it always succeeds "in +//! the moment" and simply registers a constraint. Then, at the end, we +//! can compute the full graph and report errors, so we need to be able to +//! store and later report what gave rise to the conflicting constraints. +//! +//! # Subtype Trace +//! +//! Determing whether `T1 <: T2` often involves a number of subtypes and +//! subconstraints along the way. A "TypeTrace" is an extended version +//! of an origin that traces the types and other values that were being +//! compared. It is not necessarily comprehensive (in fact, at the time of +//! this writing it only tracks the root values being compared) but I'd +//! like to extend it to include significant "waypoints". For example, if +//! you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2 +//! <: T4` fails, I'd like the trace to include enough information to say +//! "in the 2nd element of the tuple". Similarly, failures when comparing +//! arguments or return types in fn types should be able to cite the +//! specific position, etc. +//! +//! # Reality vs plan +//! +//! Of course, there is still a LOT of code in typeck that has yet to be +//! ported to this system, and which relies on string concatenation at the +//! time of error detection. + use self::FreshOrKept::*; use std::collections::HashSet; @@ -391,11 +388,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ty::note_and_explain_type_err(self.tcx, terr); } + /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived + /// error. fn values_str(&self, values: &ValuePairs<'tcx>) -> Option { - /*! - * Returns a string of the form "expected `{}`, found `{}`", - * or None if this is a derived error. - */ match *values { infer::Types(ref exp_found) => self.expected_found_str(exp_found), infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found) diff --git a/src/librustc/middle/typeck/infer/higher_ranked/doc.rs b/src/librustc/middle/typeck/infer/higher_ranked/doc.rs index 4c4452ac892..2bad3616a05 100644 --- a/src/librustc/middle/typeck/infer/higher_ranked/doc.rs +++ b/src/librustc/middle/typeck/infer/higher_ranked/doc.rs @@ -8,408 +8,404 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -# Skolemization and functions - -One of the trickiest and most subtle aspects of regions is dealing -with higher-ranked things which include bound region variables, such -as function types. I strongly suggest that if you want to understand -the situation, you read this paper (which is, admittedly, very long, -but you don't have to read the whole thing): - -http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/ - -Although my explanation will never compete with SPJ's (for one thing, -his is approximately 100 pages), I will attempt to explain the basic -problem and also how we solve it. Note that the paper only discusses -subtyping, not the computation of LUB/GLB. - -The problem we are addressing is that there is a kind of subtyping -between functions with bound region parameters. Consider, for -example, whether the following relation holds: - - for<'a> fn(&'a int) <: for<'b> fn(&'b int)? (Yes, a => b) - -The answer is that of course it does. These two types are basically -the same, except that in one we used the name `a` and one we used -the name `b`. - -In the examples that follow, it becomes very important to know whether -a lifetime is bound in a function type (that is, is a lifetime -parameter) or appears free (is defined in some outer scope). -Therefore, from now on I will always write the bindings explicitly, -using the Rust syntax `for<'a> fn(&'a int)` to indicate that `a` is a -lifetime parameter. - -Now let's consider two more function types. Here, we assume that the -`'b` lifetime is defined somewhere outside and hence is not a lifetime -parameter bound by the function type (it "appears free"): - - for<'a> fn(&'a int) <: fn(&'b int)? (Yes, a => b) - -This subtyping relation does in fact hold. To see why, you have to -consider what subtyping means. One way to look at `T1 <: T2` is to -say that it means that it is always ok to treat an instance of `T1` as -if it had the type `T2`. So, with our functions, it is always ok to -treat a function that can take pointers with any lifetime as if it -were a function that can only take a pointer with the specific -lifetime `'b`. After all, `'b` is a lifetime, after all, and -the function can take values of any lifetime. - -You can also look at subtyping as the *is a* relationship. This amounts -to the same thing: a function that accepts pointers with any lifetime -*is a* function that accepts pointers with some specific lifetime. - -So, what if we reverse the order of the two function types, like this: - - fn(&'b int) <: for<'a> fn(&'a int)? (No) - -Does the subtyping relationship still hold? The answer of course is -no. In this case, the function accepts *only the lifetime `'b`*, -so it is not reasonable to treat it as if it were a function that -accepted any lifetime. - -What about these two examples: - - for<'a,'b> fn(&'a int, &'b int) <: for<'a> fn(&'a int, &'a int)? (Yes) - for<'a> fn(&'a int, &'a int) <: for<'a,'b> fn(&'a int, &'b int)? (No) - -Here, it is true that functions which take two pointers with any two -lifetimes can be treated as if they only accepted two pointers with -the same lifetime, but not the reverse. - -## The algorithm - -Here is the algorithm we use to perform the subtyping check: - -1. Replace all bound regions in the subtype with new variables -2. Replace all bound regions in the supertype with skolemized - equivalents. A "skolemized" region is just a new fresh region - name. -3. Check that the parameter and return types match as normal -4. Ensure that no skolemized regions 'leak' into region variables - visible from "the outside" - -Let's walk through some examples and see how this algorithm plays out. - -#### First example - -We'll start with the first example, which was: - - 1. for<'a> fn(&'a T) <: for<'b> fn(&'b T)? Yes: a -> b - -After steps 1 and 2 of the algorithm we will have replaced the types -like so: - - 1. fn(&'A T) <: fn(&'x T)? - -Here the upper case `&A` indicates a *region variable*, that is, a -region whose value is being inferred by the system. I also replaced -`&b` with `&x`---I'll use letters late in the alphabet (`x`, `y`, `z`) -to indicate skolemized region names. We can assume they don't appear -elsewhere. Note that neither the sub- nor the supertype bind any -region names anymore (as indicated by the absence of `<` and `>`). - -The next step is to check that the parameter types match. Because -parameters are contravariant, this means that we check whether: - - &'x T <: &'A T - -Region pointers are contravariant so this implies that - - &A <= &x - -must hold, where `<=` is the subregion relationship. Processing -*this* constrain simply adds a constraint into our graph that `&A <= -&x` and is considered successful (it can, for example, be satisfied by -choosing the value `&x` for `&A`). - -So far we have encountered no error, so the subtype check succeeds. - -#### The third example - -Now let's look first at the third example, which was: - - 3. fn(&'a T) <: for<'b> fn(&'b T)? No! - -After steps 1 and 2 of the algorithm we will have replaced the types -like so: - - 3. fn(&'a T) <: fn(&'x T)? - -This looks pretty much the same as before, except that on the LHS -`'a` was not bound, and hence was left as-is and not replaced with -a variable. The next step is again to check that the parameter types -match. This will ultimately require (as before) that `'a` <= `&x` -must hold: but this does not hold. `self` and `x` are both distinct -free regions. So the subtype check fails. - -#### Checking for skolemization leaks - -You may be wondering about that mysterious last step in the algorithm. -So far it has not been relevant. The purpose of that last step is to -catch something like *this*: - - for<'a> fn() -> fn(&'a T) <: fn() -> for<'b> fn(&'b T)? No. - -Here the function types are the same but for where the binding occurs. -The subtype returns a function that expects a value in precisely one -region. The supertype returns a function that expects a value in any -region. If we allow an instance of the subtype to be used where the -supertype is expected, then, someone could call the fn and think that -the return value has type `fn(&'b T)` when it really has type -`fn(&'a T)` (this is case #3, above). Bad. - -So let's step through what happens when we perform this subtype check. -We first replace the bound regions in the subtype (the supertype has -no bound regions). This gives us: - - fn() -> fn(&'A T) <: fn() -> for<'b> fn(&'b T)? - -Now we compare the return types, which are covariant, and hence we have: - - fn(&'A T) <: for<'b> fn(&'b T)? - -Here we skolemize the bound region in the supertype to yield: - - fn(&'A T) <: fn(&'x T)? - -And then proceed to compare the argument types: - - &'x T <: &'A T - 'A <= 'x - -Finally, this is where it gets interesting! This is where an error -*should* be reported. But in fact this will not happen. The reason why -is that `A` is a variable: we will infer that its value is the fresh -region `x` and think that everything is happy. In fact, this behavior -is *necessary*, it was key to the first example we walked through. - -The difference between this example and the first one is that the variable -`A` already existed at the point where the skolemization occurred. In -the first example, you had two functions: - - for<'a> fn(&'a T) <: for<'b> fn(&'b T) - -and hence `&A` and `&x` were created "together". In general, the -intention of the skolemized names is that they are supposed to be -fresh names that could never be equal to anything from the outside. -But when inference comes into play, we might not be respecting this -rule. - -So the way we solve this is to add a fourth step that examines the -constraints that refer to skolemized names. Basically, consider a -non-directed verison of the constraint graph. Let `Tainted(x)` be the -set of all things reachable from a skolemized variable `x`. -`Tainted(x)` should not contain any regions that existed before the -step at which the skolemization was performed. So this case here -would fail because `&x` was created alone, but is relatable to `&A`. - -## Computing the LUB and GLB - -The paper I pointed you at is written for Haskell. It does not -therefore considering subtyping and in particular does not consider -LUB or GLB computation. We have to consider this. Here is the -algorithm I implemented. - -First though, let's discuss what we are trying to compute in more -detail. The LUB is basically the "common supertype" and the GLB is -"common subtype"; one catch is that the LUB should be the -*most-specific* common supertype and the GLB should be *most general* -common subtype (as opposed to any common supertype or any common -subtype). - -Anyway, to help clarify, here is a table containing some function -pairs and their LUB/GLB (for conciseness, in this table, I'm just -including the lifetimes here, not the rest of the types, and I'm -writing `fn<>` instead of `for<> fn`): - -``` -Type 1 Type 2 LUB GLB -fn<'a>('a) fn('X) fn('X) fn<'a>('a) -fn('a) fn('X) -- fn<'a>('a) -fn<'a,'b>('a, 'b) fn<'x>('x, 'x) fn<'a>('a, 'a) fn<'a,'b>('a, 'b) -fn<'a,'b>('a, 'b, 'a) fn<'x,'y>('x, 'y, 'y) fn<'a>('a, 'a, 'a) fn<'a,'b,'c>('a,'b,'c) -``` - -### Conventions - -I use lower-case letters (e.g., `&a`) for bound regions and upper-case -letters for free regions (`&A`). Region variables written with a -dollar-sign (e.g., `$a`). I will try to remember to enumerate the -bound-regions on the fn type as well (e.g., `for<'a> fn(&a)`). - -### High-level summary - -Both the LUB and the GLB algorithms work in a similar fashion. They -begin by replacing all bound regions (on both sides) with fresh region -inference variables. Therefore, both functions are converted to types -that contain only free regions. We can then compute the LUB/GLB in a -straightforward way, as described in `combine.rs`. This results in an -interim type T. The algorithms then examine the regions that appear -in T and try to, in some cases, replace them with bound regions to -yield the final result. - -To decide whether to replace a region `R` that appears in `T` with a -bound region, the algorithms make use of two bits of information. -First is a set `V` that contains all region variables created as part -of the LUB/GLB computation. `V` will contain the region variables -created to replace the bound regions in the input types, but it also -contains 'intermediate' variables created to represent the LUB/GLB of -individual regions. Basically, when asked to compute the LUB/GLB of a -region variable with another region, the inferencer cannot oblige -immediately since the values of that variables are not known. -Therefore, it creates a new variable that is related to the two -regions. For example, the LUB of two variables `$x` and `$y` is a -fresh variable `$z` that is constrained such that `$x <= $z` and `$y -<= $z`. So `V` will contain these intermediate variables as well. - -The other important factor in deciding how to replace a region in T is -the function `Tainted($r)` which, for a region variable, identifies -all regions that the region variable is related to in some way -(`Tainted()` made an appearance in the subtype computation as well). - -### LUB - -The LUB algorithm proceeds in three steps: - -1. Replace all bound regions (on both sides) with fresh region - inference variables. -2. Compute the LUB "as normal", meaning compute the GLB of each - pair of argument types and the LUB of the return types and - so forth. Combine those to a new function type `F`. -3. Replace each region `R` that appears in `F` as follows: - - Let `V` be the set of variables created during the LUB - computational steps 1 and 2, as described in the previous section. - - If `R` is not in `V`, replace `R` with itself. - - If `Tainted(R)` contains a region that is not in `V`, - replace `R` with itself. - - Otherwise, select the earliest variable in `Tainted(R)` that originates - from the left-hand side and replace `R` with the bound region that - this variable was a replacement for. - -So, let's work through the simplest example: `fn(&A)` and `for<'a> fn(&a)`. -In this case, `&a` will be replaced with `$a` and the interim LUB type -`fn($b)` will be computed, where `$b=GLB(&A,$a)`. Therefore, `V = -{$a, $b}` and `Tainted($b) = { $b, $a, &A }`. When we go to replace -`$b`, we find that since `&A \in Tainted($b)` is not a member of `V`, -we leave `$b` as is. When region inference happens, `$b` will be -resolved to `&A`, as we wanted. - -Let's look at a more complex one: `fn(&a, &b)` and `fn(&x, &x)`. In -this case, we'll end up with a (pre-replacement) LUB type of `fn(&g, -&h)` and a graph that looks like: - -``` - $a $b *--$x - \ \ / / - \ $h-* / - $g-----------* -``` - -Here `$g` and `$h` are fresh variables that are created to represent -the LUB/GLB of things requiring inference. This means that `V` and -`Tainted` will look like: - -``` -V = {$a, $b, $g, $h, $x} -Tainted($g) = Tainted($h) = { $a, $b, $h, $g, $x } -``` - -Therefore we replace both `$g` and `$h` with `$a`, and end up -with the type `fn(&a, &a)`. - -### GLB - -The procedure for computing the GLB is similar. The difference lies -in computing the replacements for the various variables. For each -region `R` that appears in the type `F`, we again compute `Tainted(R)` -and examine the results: - -1. If `R` is not in `V`, it is not replaced. -2. Else, if `Tainted(R)` contains only variables in `V`, and it - contains exactly one variable from the LHS and one variable from - the RHS, then `R` can be mapped to the bound version of the - variable from the LHS. -3. Else, if `Tainted(R)` contains no variable from the LHS and no - variable from the RHS, then `R` can be mapped to itself. -4. Else, `R` is mapped to a fresh bound variable. - -These rules are pretty complex. Let's look at some examples to see -how they play out. - -Out first example was `fn(&a)` and `fn(&X)`. In this case, `&a` will -be replaced with `$a` and we will ultimately compute a -(pre-replacement) GLB type of `fn($g)` where `$g=LUB($a,&X)`. -Therefore, `V={$a,$g}` and `Tainted($g)={$g,$a,&X}. To find the -replacement for `$g` we consult the rules above: -- Rule (1) does not apply because `$g \in V` -- Rule (2) does not apply because `&X \in Tainted($g)` -- Rule (3) does not apply because `$a \in Tainted($g)` -- Hence, by rule (4), we replace `$g` with a fresh bound variable `&z`. -So our final result is `fn(&z)`, which is correct. - -The next example is `fn(&A)` and `fn(&Z)`. In this case, we will again -have a (pre-replacement) GLB of `fn(&g)`, where `$g = LUB(&A,&Z)`. -Therefore, `V={$g}` and `Tainted($g) = {$g, &A, &Z}`. In this case, -by rule (3), `$g` is mapped to itself, and hence the result is -`fn($g)`. This result is correct (in this case, at least), but it is -indicative of a case that *can* lead us into concluding that there is -no GLB when in fact a GLB does exist. See the section "Questionable -Results" below for more details. - -The next example is `fn(&a, &b)` and `fn(&c, &c)`. In this case, as -before, we'll end up with `F=fn($g, $h)` where `Tainted($g) = -Tainted($h) = {$g, $h, $a, $b, $c}`. Only rule (4) applies and hence -we'll select fresh bound variables `y` and `z` and wind up with -`fn(&y, &z)`. - -For the last example, let's consider what may seem trivial, but is -not: `fn(&a, &a)` and `fn(&b, &b)`. In this case, we'll get `F=fn($g, -$h)` where `Tainted($g) = {$g, $a, $x}` and `Tainted($h) = {$h, $a, -$x}`. Both of these sets contain exactly one bound variable from each -side, so we'll map them both to `&a`, resulting in `fn(&a, &a)`, which -is the desired result. - -### Shortcomings and correctness - -You may be wondering whether this algorithm is correct. The answer is -"sort of". There are definitely cases where they fail to compute a -result even though a correct result exists. I believe, though, that -if they succeed, then the result is valid, and I will attempt to -convince you. The basic argument is that the "pre-replacement" step -computes a set of constraints. The replacements, then, attempt to -satisfy those constraints, using bound identifiers where needed. - -For now I will briefly go over the cases for LUB/GLB and identify -their intent: - -- LUB: - - The region variables that are substituted in place of bound regions - are intended to collect constraints on those bound regions. - - If Tainted(R) contains only values in V, then this region is unconstrained - and can therefore be generalized, otherwise it cannot. -- GLB: - - The region variables that are substituted in place of bound regions - are intended to collect constraints on those bound regions. - - If Tainted(R) contains exactly one variable from each side, and - only variables in V, that indicates that those two bound regions - must be equated. - - Otherwise, if Tainted(R) references any variables from left or right - side, then it is trying to combine a bound region with a free one or - multiple bound regions, so we need to select fresh bound regions. - -Sorry this is more of a shorthand to myself. I will try to write up something -more convincing in the future. - -#### Where are the algorithms wrong? - -- The pre-replacement computation can fail even though using a - bound-region would have succeeded. -- We will compute GLB(fn(fn($a)), fn(fn($b))) as fn($c) where $c is the - GLB of $a and $b. But if inference finds that $a and $b must be mapped - to regions without a GLB, then this is effectively a failure to compute - the GLB. However, the result `fn<$c>(fn($c))` is a valid GLB. - - */ +//! # Skolemization and functions +//! +//! One of the trickiest and most subtle aspects of regions is dealing +//! with higher-ranked things which include bound region variables, such +//! as function types. I strongly suggest that if you want to understand +//! the situation, you read this paper (which is, admittedly, very long, +//! but you don't have to read the whole thing): +//! +//! http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/ +//! +//! Although my explanation will never compete with SPJ's (for one thing, +//! his is approximately 100 pages), I will attempt to explain the basic +//! problem and also how we solve it. Note that the paper only discusses +//! subtyping, not the computation of LUB/GLB. +//! +//! The problem we are addressing is that there is a kind of subtyping +//! between functions with bound region parameters. Consider, for +//! example, whether the following relation holds: +//! +//! for<'a> fn(&'a int) <: for<'b> fn(&'b int)? (Yes, a => b) +//! +//! The answer is that of course it does. These two types are basically +//! the same, except that in one we used the name `a` and one we used +//! the name `b`. +//! +//! In the examples that follow, it becomes very important to know whether +//! a lifetime is bound in a function type (that is, is a lifetime +//! parameter) or appears free (is defined in some outer scope). +//! Therefore, from now on I will always write the bindings explicitly, +//! using the Rust syntax `for<'a> fn(&'a int)` to indicate that `a` is a +//! lifetime parameter. +//! +//! Now let's consider two more function types. Here, we assume that the +//! `'b` lifetime is defined somewhere outside and hence is not a lifetime +//! parameter bound by the function type (it "appears free"): +//! +//! for<'a> fn(&'a int) <: fn(&'b int)? (Yes, a => b) +//! +//! This subtyping relation does in fact hold. To see why, you have to +//! consider what subtyping means. One way to look at `T1 <: T2` is to +//! say that it means that it is always ok to treat an instance of `T1` as +//! if it had the type `T2`. So, with our functions, it is always ok to +//! treat a function that can take pointers with any lifetime as if it +//! were a function that can only take a pointer with the specific +//! lifetime `'b`. After all, `'b` is a lifetime, after all, and +//! the function can take values of any lifetime. +//! +//! You can also look at subtyping as the *is a* relationship. This amounts +//! to the same thing: a function that accepts pointers with any lifetime +//! *is a* function that accepts pointers with some specific lifetime. +//! +//! So, what if we reverse the order of the two function types, like this: +//! +//! fn(&'b int) <: for<'a> fn(&'a int)? (No) +//! +//! Does the subtyping relationship still hold? The answer of course is +//! no. In this case, the function accepts *only the lifetime `'b`*, +//! so it is not reasonable to treat it as if it were a function that +//! accepted any lifetime. +//! +//! What about these two examples: +//! +//! for<'a,'b> fn(&'a int, &'b int) <: for<'a> fn(&'a int, &'a int)? (Yes) +//! for<'a> fn(&'a int, &'a int) <: for<'a,'b> fn(&'a int, &'b int)? (No) +//! +//! Here, it is true that functions which take two pointers with any two +//! lifetimes can be treated as if they only accepted two pointers with +//! the same lifetime, but not the reverse. +//! +//! ## The algorithm +//! +//! Here is the algorithm we use to perform the subtyping check: +//! +//! 1. Replace all bound regions in the subtype with new variables +//! 2. Replace all bound regions in the supertype with skolemized +//! equivalents. A "skolemized" region is just a new fresh region +//! name. +//! 3. Check that the parameter and return types match as normal +//! 4. Ensure that no skolemized regions 'leak' into region variables +//! visible from "the outside" +//! +//! Let's walk through some examples and see how this algorithm plays out. +//! +//! #### First example +//! +//! We'll start with the first example, which was: +//! +//! 1. for<'a> fn(&'a T) <: for<'b> fn(&'b T)? Yes: a -> b +//! +//! After steps 1 and 2 of the algorithm we will have replaced the types +//! like so: +//! +//! 1. fn(&'A T) <: fn(&'x T)? +//! +//! Here the upper case `&A` indicates a *region variable*, that is, a +//! region whose value is being inferred by the system. I also replaced +//! `&b` with `&x`---I'll use letters late in the alphabet (`x`, `y`, `z`) +//! to indicate skolemized region names. We can assume they don't appear +//! elsewhere. Note that neither the sub- nor the supertype bind any +//! region names anymore (as indicated by the absence of `<` and `>`). +//! +//! The next step is to check that the parameter types match. Because +//! parameters are contravariant, this means that we check whether: +//! +//! &'x T <: &'A T +//! +//! Region pointers are contravariant so this implies that +//! +//! &A <= &x +//! +//! must hold, where `<=` is the subregion relationship. Processing +//! *this* constrain simply adds a constraint into our graph that `&A <= +//! &x` and is considered successful (it can, for example, be satisfied by +//! choosing the value `&x` for `&A`). +//! +//! So far we have encountered no error, so the subtype check succeeds. +//! +//! #### The third example +//! +//! Now let's look first at the third example, which was: +//! +//! 3. fn(&'a T) <: for<'b> fn(&'b T)? No! +//! +//! After steps 1 and 2 of the algorithm we will have replaced the types +//! like so: +//! +//! 3. fn(&'a T) <: fn(&'x T)? +//! +//! This looks pretty much the same as before, except that on the LHS +//! `'a` was not bound, and hence was left as-is and not replaced with +//! a variable. The next step is again to check that the parameter types +//! match. This will ultimately require (as before) that `'a` <= `&x` +//! must hold: but this does not hold. `self` and `x` are both distinct +//! free regions. So the subtype check fails. +//! +//! #### Checking for skolemization leaks +//! +//! You may be wondering about that mysterious last step in the algorithm. +//! So far it has not been relevant. The purpose of that last step is to +//! catch something like *this*: +//! +//! for<'a> fn() -> fn(&'a T) <: fn() -> for<'b> fn(&'b T)? No. +//! +//! Here the function types are the same but for where the binding occurs. +//! The subtype returns a function that expects a value in precisely one +//! region. The supertype returns a function that expects a value in any +//! region. If we allow an instance of the subtype to be used where the +//! supertype is expected, then, someone could call the fn and think that +//! the return value has type `fn(&'b T)` when it really has type +//! `fn(&'a T)` (this is case #3, above). Bad. +//! +//! So let's step through what happens when we perform this subtype check. +//! We first replace the bound regions in the subtype (the supertype has +//! no bound regions). This gives us: +//! +//! fn() -> fn(&'A T) <: fn() -> for<'b> fn(&'b T)? +//! +//! Now we compare the return types, which are covariant, and hence we have: +//! +//! fn(&'A T) <: for<'b> fn(&'b T)? +//! +//! Here we skolemize the bound region in the supertype to yield: +//! +//! fn(&'A T) <: fn(&'x T)? +//! +//! And then proceed to compare the argument types: +//! +//! &'x T <: &'A T +//! 'A <= 'x +//! +//! Finally, this is where it gets interesting! This is where an error +//! *should* be reported. But in fact this will not happen. The reason why +//! is that `A` is a variable: we will infer that its value is the fresh +//! region `x` and think that everything is happy. In fact, this behavior +//! is *necessary*, it was key to the first example we walked through. +//! +//! The difference between this example and the first one is that the variable +//! `A` already existed at the point where the skolemization occurred. In +//! the first example, you had two functions: +//! +//! for<'a> fn(&'a T) <: for<'b> fn(&'b T) +//! +//! and hence `&A` and `&x` were created "together". In general, the +//! intention of the skolemized names is that they are supposed to be +//! fresh names that could never be equal to anything from the outside. +//! But when inference comes into play, we might not be respecting this +//! rule. +//! +//! So the way we solve this is to add a fourth step that examines the +//! constraints that refer to skolemized names. Basically, consider a +//! non-directed verison of the constraint graph. Let `Tainted(x)` be the +//! set of all things reachable from a skolemized variable `x`. +//! `Tainted(x)` should not contain any regions that existed before the +//! step at which the skolemization was performed. So this case here +//! would fail because `&x` was created alone, but is relatable to `&A`. +//! +//! ## Computing the LUB and GLB +//! +//! The paper I pointed you at is written for Haskell. It does not +//! therefore considering subtyping and in particular does not consider +//! LUB or GLB computation. We have to consider this. Here is the +//! algorithm I implemented. +//! +//! First though, let's discuss what we are trying to compute in more +//! detail. The LUB is basically the "common supertype" and the GLB is +//! "common subtype"; one catch is that the LUB should be the +//! *most-specific* common supertype and the GLB should be *most general* +//! common subtype (as opposed to any common supertype or any common +//! subtype). +//! +//! Anyway, to help clarify, here is a table containing some function +//! pairs and their LUB/GLB (for conciseness, in this table, I'm just +//! including the lifetimes here, not the rest of the types, and I'm +//! writing `fn<>` instead of `for<> fn`): +//! +//! ``` +//! Type 1 Type 2 LUB GLB +//! fn<'a>('a) fn('X) fn('X) fn<'a>('a) +//! fn('a) fn('X) -- fn<'a>('a) +//! fn<'a,'b>('a, 'b) fn<'x>('x, 'x) fn<'a>('a, 'a) fn<'a,'b>('a, 'b) +//! fn<'a,'b>('a, 'b, 'a) fn<'x,'y>('x, 'y, 'y) fn<'a>('a, 'a, 'a) fn<'a,'b,'c>('a,'b,'c) +//! ``` +//! +//! ### Conventions +//! +//! I use lower-case letters (e.g., `&a`) for bound regions and upper-case +//! letters for free regions (`&A`). Region variables written with a +//! dollar-sign (e.g., `$a`). I will try to remember to enumerate the +//! bound-regions on the fn type as well (e.g., `for<'a> fn(&a)`). +//! +//! ### High-level summary +//! +//! Both the LUB and the GLB algorithms work in a similar fashion. They +//! begin by replacing all bound regions (on both sides) with fresh region +//! inference variables. Therefore, both functions are converted to types +//! that contain only free regions. We can then compute the LUB/GLB in a +//! straightforward way, as described in `combine.rs`. This results in an +//! interim type T. The algorithms then examine the regions that appear +//! in T and try to, in some cases, replace them with bound regions to +//! yield the final result. +//! +//! To decide whether to replace a region `R` that appears in `T` with a +//! bound region, the algorithms make use of two bits of information. +//! First is a set `V` that contains all region variables created as part +//! of the LUB/GLB computation. `V` will contain the region variables +//! created to replace the bound regions in the input types, but it also +//! contains 'intermediate' variables created to represent the LUB/GLB of +//! individual regions. Basically, when asked to compute the LUB/GLB of a +//! region variable with another region, the inferencer cannot oblige +//! immediately since the values of that variables are not known. +//! Therefore, it creates a new variable that is related to the two +//! regions. For example, the LUB of two variables `$x` and `$y` is a +//! fresh variable `$z` that is constrained such that `$x <= $z` and `$y +//! <= $z`. So `V` will contain these intermediate variables as well. +//! +//! The other important factor in deciding how to replace a region in T is +//! the function `Tainted($r)` which, for a region variable, identifies +//! all regions that the region variable is related to in some way +//! (`Tainted()` made an appearance in the subtype computation as well). +//! +//! ### LUB +//! +//! The LUB algorithm proceeds in three steps: +//! +//! 1. Replace all bound regions (on both sides) with fresh region +//! inference variables. +//! 2. Compute the LUB "as normal", meaning compute the GLB of each +//! pair of argument types and the LUB of the return types and +//! so forth. Combine those to a new function type `F`. +//! 3. Replace each region `R` that appears in `F` as follows: +//! - Let `V` be the set of variables created during the LUB +//! computational steps 1 and 2, as described in the previous section. +//! - If `R` is not in `V`, replace `R` with itself. +//! - If `Tainted(R)` contains a region that is not in `V`, +//! replace `R` with itself. +//! - Otherwise, select the earliest variable in `Tainted(R)` that originates +//! from the left-hand side and replace `R` with the bound region that +//! this variable was a replacement for. +//! +//! So, let's work through the simplest example: `fn(&A)` and `for<'a> fn(&a)`. +//! In this case, `&a` will be replaced with `$a` and the interim LUB type +//! `fn($b)` will be computed, where `$b=GLB(&A,$a)`. Therefore, `V = +//! {$a, $b}` and `Tainted($b) = { $b, $a, &A }`. When we go to replace +//! `$b`, we find that since `&A \in Tainted($b)` is not a member of `V`, +//! we leave `$b` as is. When region inference happens, `$b` will be +//! resolved to `&A`, as we wanted. +//! +//! Let's look at a more complex one: `fn(&a, &b)` and `fn(&x, &x)`. In +//! this case, we'll end up with a (pre-replacement) LUB type of `fn(&g, +//! &h)` and a graph that looks like: +//! +//! ``` +//! $a $b *--$x +//! \ \ / / +//! \ $h-* / +//! $g-----------* +//! ``` +//! +//! Here `$g` and `$h` are fresh variables that are created to represent +//! the LUB/GLB of things requiring inference. This means that `V` and +//! `Tainted` will look like: +//! +//! ``` +//! V = {$a, $b, $g, $h, $x} +//! Tainted($g) = Tainted($h) = { $a, $b, $h, $g, $x } +//! ``` +//! +//! Therefore we replace both `$g` and `$h` with `$a`, and end up +//! with the type `fn(&a, &a)`. +//! +//! ### GLB +//! +//! The procedure for computing the GLB is similar. The difference lies +//! in computing the replacements for the various variables. For each +//! region `R` that appears in the type `F`, we again compute `Tainted(R)` +//! and examine the results: +//! +//! 1. If `R` is not in `V`, it is not replaced. +//! 2. Else, if `Tainted(R)` contains only variables in `V`, and it +//! contains exactly one variable from the LHS and one variable from +//! the RHS, then `R` can be mapped to the bound version of the +//! variable from the LHS. +//! 3. Else, if `Tainted(R)` contains no variable from the LHS and no +//! variable from the RHS, then `R` can be mapped to itself. +//! 4. Else, `R` is mapped to a fresh bound variable. +//! +//! These rules are pretty complex. Let's look at some examples to see +//! how they play out. +//! +//! Out first example was `fn(&a)` and `fn(&X)`. In this case, `&a` will +//! be replaced with `$a` and we will ultimately compute a +//! (pre-replacement) GLB type of `fn($g)` where `$g=LUB($a,&X)`. +//! Therefore, `V={$a,$g}` and `Tainted($g)={$g,$a,&X}. To find the +//! replacement for `$g` we consult the rules above: +//! - Rule (1) does not apply because `$g \in V` +//! - Rule (2) does not apply because `&X \in Tainted($g)` +//! - Rule (3) does not apply because `$a \in Tainted($g)` +//! - Hence, by rule (4), we replace `$g` with a fresh bound variable `&z`. +//! So our final result is `fn(&z)`, which is correct. +//! +//! The next example is `fn(&A)` and `fn(&Z)`. In this case, we will again +//! have a (pre-replacement) GLB of `fn(&g)`, where `$g = LUB(&A,&Z)`. +//! Therefore, `V={$g}` and `Tainted($g) = {$g, &A, &Z}`. In this case, +//! by rule (3), `$g` is mapped to itself, and hence the result is +//! `fn($g)`. This result is correct (in this case, at least), but it is +//! indicative of a case that *can* lead us into concluding that there is +//! no GLB when in fact a GLB does exist. See the section "Questionable +//! Results" below for more details. +//! +//! The next example is `fn(&a, &b)` and `fn(&c, &c)`. In this case, as +//! before, we'll end up with `F=fn($g, $h)` where `Tainted($g) = +//! Tainted($h) = {$g, $h, $a, $b, $c}`. Only rule (4) applies and hence +//! we'll select fresh bound variables `y` and `z` and wind up with +//! `fn(&y, &z)`. +//! +//! For the last example, let's consider what may seem trivial, but is +//! not: `fn(&a, &a)` and `fn(&b, &b)`. In this case, we'll get `F=fn($g, +//! $h)` where `Tainted($g) = {$g, $a, $x}` and `Tainted($h) = {$h, $a, +//! $x}`. Both of these sets contain exactly one bound variable from each +//! side, so we'll map them both to `&a`, resulting in `fn(&a, &a)`, which +//! is the desired result. +//! +//! ### Shortcomings and correctness +//! +//! You may be wondering whether this algorithm is correct. The answer is +//! "sort of". There are definitely cases where they fail to compute a +//! result even though a correct result exists. I believe, though, that +//! if they succeed, then the result is valid, and I will attempt to +//! convince you. The basic argument is that the "pre-replacement" step +//! computes a set of constraints. The replacements, then, attempt to +//! satisfy those constraints, using bound identifiers where needed. +//! +//! For now I will briefly go over the cases for LUB/GLB and identify +//! their intent: +//! +//! - LUB: +//! - The region variables that are substituted in place of bound regions +//! are intended to collect constraints on those bound regions. +//! - If Tainted(R) contains only values in V, then this region is unconstrained +//! and can therefore be generalized, otherwise it cannot. +//! - GLB: +//! - The region variables that are substituted in place of bound regions +//! are intended to collect constraints on those bound regions. +//! - If Tainted(R) contains exactly one variable from each side, and +//! only variables in V, that indicates that those two bound regions +//! must be equated. +//! - Otherwise, if Tainted(R) references any variables from left or right +//! side, then it is trying to combine a bound region with a free one or +//! multiple bound regions, so we need to select fresh bound regions. +//! +//! Sorry this is more of a shorthand to myself. I will try to write up something +//! more convincing in the future. +//! +//! #### Where are the algorithms wrong? +//! +//! - The pre-replacement computation can fail even though using a +//! bound-region would have succeeded. +//! - We will compute GLB(fn(fn($a)), fn(fn($b))) as fn($c) where $c is the +//! GLB of $a and $b. But if inference finds that $a and $b must be mapped +//! to regions without a GLB, then this is effectively a failure to compute +//! the GLB. However, the result `fn<$c>(fn($c))` is a valid GLB. diff --git a/src/librustc/middle/typeck/infer/higher_ranked/mod.rs b/src/librustc/middle/typeck/infer/higher_ranked/mod.rs index 812aa5c5557..2f80a574bb1 100644 --- a/src/librustc/middle/typeck/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/typeck/infer/higher_ranked/mod.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Helper routines for higher-ranked things. See the `doc` module at - * the end of the file for details. - */ +//! Helper routines for higher-ranked things. See the `doc` module at +//! the end of the file for details. use middle::ty::{mod, Ty, replace_late_bound_regions}; use middle::typeck::infer::{mod, combine, cres, InferCtxt}; diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index 6e6c631f007..daec959d11c 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -8,28 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * # Lattice Variables - * - * This file contains generic code for operating on inference variables - * that are characterized by an upper- and lower-bound. The logic and - * reasoning is explained in detail in the large comment in `infer.rs`. - * - * The code in here is defined quite generically so that it can be - * applied both to type variables, which represent types being inferred, - * and fn variables, which represent function types being inferred. - * It may eventually be applied to their types as well, who knows. - * In some cases, the functions are also generic with respect to the - * operation on the lattice (GLB vs LUB). - * - * Although all the functions are generic, we generally write the - * comments in a way that is specific to type variables and the LUB - * operation. It's just easier that way. - * - * In general all of the functions are defined parametrically - * over a `LatticeValue`, which is a value defined with respect to - * a lattice. - */ +//! # Lattice Variables +//! +//! This file contains generic code for operating on inference variables +//! that are characterized by an upper- and lower-bound. The logic and +//! reasoning is explained in detail in the large comment in `infer.rs`. +//! +//! The code in here is defined quite generically so that it can be +//! applied both to type variables, which represent types being inferred, +//! and fn variables, which represent function types being inferred. +//! It may eventually be applied to their types as well, who knows. +//! In some cases, the functions are also generic with respect to the +//! operation on the lattice (GLB vs LUB). +//! +//! Although all the functions are generic, we generally write the +//! comments in a way that is specific to type variables and the LUB +//! operation. It's just easier that way. +//! +//! In general all of the functions are defined parametrically +//! over a `LatticeValue`, which is a value defined with respect to +//! a lattice. use middle::ty::{TyVar}; use middle::ty::{mod, Ty}; diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 93c11693091..c5845b143af 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! See doc.rs for documentation */ +//! See doc.rs for documentation #![allow(non_camel_case_types)] @@ -305,6 +305,8 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>) } } +/// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and +/// returns ty::err. pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin, a_is_expected: bool, @@ -312,11 +314,6 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, b: Ty<'tcx>) -> Ty<'tcx> { - /*! - * Computes the least upper-bound of `a` and `b`. If this is - * not possible, reports an error and returns ty::err. - */ - debug!("common_supertype({}, {})", a.repr(cx.tcx), b.repr(cx.tcx)); @@ -754,17 +751,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .collect() } + /// Given a set of generics defined on a type or impl, returns a substitution mapping each + /// type/region parameter to a fresh inference variable. pub fn fresh_substs_for_generics(&self, span: Span, generics: &ty::Generics<'tcx>) -> subst::Substs<'tcx> { - /*! - * Given a set of generics defined on a type or impl, returns - * a substitution mapping each type/region parameter to a - * fresh inference variable. - */ - let type_params = generics.types.map( |_| self.next_ty_var()); @@ -774,18 +767,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { subst::Substs::new(type_params, region_params) } + /// Given a set of generics defined on a trait, returns a substitution mapping each output + /// type/region parameter to a fresh inference variable, and mapping the self type to + /// `self_ty`. pub fn fresh_substs_for_trait(&self, span: Span, generics: &ty::Generics<'tcx>, self_ty: Ty<'tcx>) -> subst::Substs<'tcx> { - /*! - * Given a set of generics defined on a trait, returns a - * substitution mapping each output type/region parameter to a - * fresh inference variable, and mapping the self type to - * `self_ty`. - */ assert!(generics.types.len(subst::SelfSpace) == 1); assert!(generics.types.len(subst::FnSpace) == 0); diff --git a/src/librustc/middle/typeck/infer/region_inference/doc.rs b/src/librustc/middle/typeck/infer/region_inference/doc.rs index 40b41deeb2b..b4eac4c0026 100644 --- a/src/librustc/middle/typeck/infer/region_inference/doc.rs +++ b/src/librustc/middle/typeck/infer/region_inference/doc.rs @@ -8,371 +8,367 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Region inference module. - -# Terminology - -Note that we use the terms region and lifetime interchangeably, -though the term `lifetime` is preferred. - -# Introduction - -Region inference uses a somewhat more involved algorithm than type -inference. It is not the most efficient thing ever written though it -seems to work well enough in practice (famous last words). The reason -that we use a different algorithm is because, unlike with types, it is -impractical to hand-annotate with regions (in some cases, there aren't -even the requisite syntactic forms). So we have to get it right, and -it's worth spending more time on a more involved analysis. Moreover, -regions are a simpler case than types: they don't have aggregate -structure, for example. - -Unlike normal type inference, which is similar in spirit to H-M and thus -works progressively, the region type inference works by accumulating -constraints over the course of a function. Finally, at the end of -processing a function, we process and solve the constraints all at -once. - -The constraints are always of one of three possible forms: - -- ConstrainVarSubVar(R_i, R_j) states that region variable R_i - must be a subregion of R_j -- ConstrainRegSubVar(R, R_i) states that the concrete region R - (which must not be a variable) must be a subregion of the varibale R_i -- ConstrainVarSubReg(R_i, R) is the inverse - -# Building up the constraints - -Variables and constraints are created using the following methods: - -- `new_region_var()` creates a new, unconstrained region variable; -- `make_subregion(R_i, R_j)` states that R_i is a subregion of R_j -- `lub_regions(R_i, R_j) -> R_k` returns a region R_k which is - the smallest region that is greater than both R_i and R_j -- `glb_regions(R_i, R_j) -> R_k` returns a region R_k which is - the greatest region that is smaller than both R_i and R_j - -The actual region resolution algorithm is not entirely -obvious, though it is also not overly complex. - -## Snapshotting - -It is also permitted to try (and rollback) changes to the graph. This -is done by invoking `start_snapshot()`, which returns a value. Then -later you can call `rollback_to()` which undoes the work. -Alternatively, you can call `commit()` which ends all snapshots. -Snapshots can be recursive---so you can start a snapshot when another -is in progress, but only the root snapshot can "commit". - -# Resolving constraints - -The constraint resolution algorithm is not super complex but also not -entirely obvious. Here I describe the problem somewhat abstractly, -then describe how the current code works. There may be other, smarter -ways of doing this with which I am unfamiliar and can't be bothered to -research at the moment. - NDM - -## The problem - -Basically our input is a directed graph where nodes can be divided -into two categories: region variables and concrete regions. Each edge -`R -> S` in the graph represents a constraint that the region `R` is a -subregion of the region `S`. - -Region variable nodes can have arbitrary degree. There is one region -variable node per region variable. - -Each concrete region node is associated with some, well, concrete -region: e.g., a free lifetime, or the region for a particular scope. -Note that there may be more than one concrete region node for a -particular region value. Moreover, because of how the graph is built, -we know that all concrete region nodes have either in-degree 1 or -out-degree 1. - -Before resolution begins, we build up the constraints in a hashmap -that maps `Constraint` keys to spans. During resolution, we construct -the actual `Graph` structure that we describe here. - -## Our current algorithm - -We divide region variables into two groups: Expanding and Contracting. -Expanding region variables are those that have a concrete region -predecessor (direct or indirect). Contracting region variables are -all others. - -We first resolve the values of Expanding region variables and then -process Contracting ones. We currently use an iterative, fixed-point -procedure (but read on, I believe this could be replaced with a linear -walk). Basically we iterate over the edges in the graph, ensuring -that, if the source of the edge has a value, then this value is a -subregion of the target value. If the target does not yet have a -value, it takes the value from the source. If the target already had -a value, then the resulting value is Least Upper Bound of the old and -new values. When we are done, each Expanding node will have the -smallest region that it could possibly have and still satisfy the -constraints. - -We next process the Contracting nodes. Here we again iterate over the -edges, only this time we move values from target to source (if the -source is a Contracting node). For each contracting node, we compute -its value as the GLB of all its successors. Basically contracting -nodes ensure that there is overlap between their successors; we will -ultimately infer the largest overlap possible. - -# The Region Hierarchy - -## Without closures - -Let's first consider the region hierarchy without thinking about -closures, because they add a lot of complications. The region -hierarchy *basically* mirrors the lexical structure of the code. -There is a region for every piece of 'evaluation' that occurs, meaning -every expression, block, and pattern (patterns are considered to -"execute" by testing the value they are applied to and creating any -relevant bindings). So, for example: - - fn foo(x: int, y: int) { // -+ - // +------------+ // | - // | +-----+ // | - // | +-+ +-+ +-+ // | - // | | | | | | | // | - // v v v v v v v // | - let z = x + y; // | - ... // | - } // -+ - - fn bar() { ... } - -In this example, there is a region for the fn body block as a whole, -and then a subregion for the declaration of the local variable. -Within that, there are sublifetimes for the assignment pattern and -also the expression `x + y`. The expression itself has sublifetimes -for evaluating `x` and `y`. - -## Function calls - -Function calls are a bit tricky. I will describe how we handle them -*now* and then a bit about how we can improve them (Issue #6268). - -Consider a function call like `func(expr1, expr2)`, where `func`, -`arg1`, and `arg2` are all arbitrary expressions. Currently, -we construct a region hierarchy like: - - +----------------+ - | | - +--+ +---+ +---+| - v v v v v vv - func(expr1, expr2) - -Here you can see that the call as a whole has a region and the -function plus arguments are subregions of that. As a side-effect of -this, we get a lot of spurious errors around nested calls, in -particular when combined with `&mut` functions. For example, a call -like this one - - self.foo(self.bar()) - -where both `foo` and `bar` are `&mut self` functions will always yield -an error. - -Here is a more involved example (which is safe) so we can see what's -going on: - - struct Foo { f: uint, g: uint } - ... - fn add(p: &mut uint, v: uint) { - *p += v; - } - ... - fn inc(p: &mut uint) -> uint { - *p += 1; *p - } - fn weird() { - let mut x: Box = box Foo { ... }; - 'a: add(&mut (*x).f, - 'b: inc(&mut (*x).f)) // (..) - } - -The important part is the line marked `(..)` which contains a call to -`add()`. The first argument is a mutable borrow of the field `f`. The -second argument also borrows the field `f`. Now, in the current borrow -checker, the first borrow is given the lifetime of the call to -`add()`, `'a`. The second borrow is given the lifetime of `'b` of the -call to `inc()`. Because `'b` is considered to be a sublifetime of -`'a`, an error is reported since there are two co-existing mutable -borrows of the same data. - -However, if we were to examine the lifetimes a bit more carefully, we -can see that this error is unnecessary. Let's examine the lifetimes -involved with `'a` in detail. We'll break apart all the steps involved -in a call expression: - - 'a: { - 'a_arg1: let a_temp1: ... = add; - 'a_arg2: let a_temp2: &'a mut uint = &'a mut (*x).f; - 'a_arg3: let a_temp3: uint = { - let b_temp1: ... = inc; - let b_temp2: &'b = &'b mut (*x).f; - 'b_call: b_temp1(b_temp2) - }; - 'a_call: a_temp1(a_temp2, a_temp3) // (**) - } - -Here we see that the lifetime `'a` includes a number of substatements. -In particular, there is this lifetime I've called `'a_call` that -corresponds to the *actual execution of the function `add()`*, after -all arguments have been evaluated. There is a corresponding lifetime -`'b_call` for the execution of `inc()`. If we wanted to be precise -about it, the lifetime of the two borrows should be `'a_call` and -`'b_call` respectively, since the references that were created -will not be dereferenced except during the execution itself. - -However, this model by itself is not sound. The reason is that -while the two references that are created will never be used -simultaneously, it is still true that the first reference is -*created* before the second argument is evaluated, and so even though -it will not be *dereferenced* during the evaluation of the second -argument, it can still be *invalidated* by that evaluation. Consider -this similar but unsound example: - - struct Foo { f: uint, g: uint } - ... - fn add(p: &mut uint, v: uint) { - *p += v; - } - ... - fn consume(x: Box) -> uint { - x.f + x.g - } - fn weird() { - let mut x: Box = box Foo { ... }; - 'a: add(&mut (*x).f, consume(x)) // (..) - } - -In this case, the second argument to `add` actually consumes `x`, thus -invalidating the first argument. - -So, for now, we exclude the `call` lifetimes from our model. -Eventually I would like to include them, but we will have to make the -borrow checker handle this situation correctly. In particular, if -there is a reference created whose lifetime does not enclose -the borrow expression, we must issue sufficient restrictions to ensure -that the pointee remains valid. - -## Adding closures - -The other significant complication to the region hierarchy is -closures. I will describe here how closures should work, though some -of the work to implement this model is ongoing at the time of this -writing. - -The body of closures are type-checked along with the function that -creates them. However, unlike other expressions that appear within the -function body, it is not entirely obvious when a closure body executes -with respect to the other expressions. This is because the closure -body will execute whenever the closure is called; however, we can -never know precisely when the closure will be called, especially -without some sort of alias analysis. - -However, we can place some sort of limits on when the closure -executes. In particular, the type of every closure `fn:'r K` includes -a region bound `'r`. This bound indicates the maximum lifetime of that -closure; once we exit that region, the closure cannot be called -anymore. Therefore, we say that the lifetime of the closure body is a -sublifetime of the closure bound, but the closure body itself is unordered -with respect to other parts of the code. - -For example, consider the following fragment of code: - - 'a: { - let closure: fn:'a() = || 'b: { - 'c: ... - }; - 'd: ... - } - -Here we have four lifetimes, `'a`, `'b`, `'c`, and `'d`. The closure -`closure` is bounded by the lifetime `'a`. The lifetime `'b` is the -lifetime of the closure body, and `'c` is some statement within the -closure body. Finally, `'d` is a statement within the outer block that -created the closure. - -We can say that the closure body `'b` is a sublifetime of `'a` due to -the closure bound. By the usual lexical scoping conventions, the -statement `'c` is clearly a sublifetime of `'b`, and `'d` is a -sublifetime of `'d`. However, there is no ordering between `'c` and -`'d` per se (this kind of ordering between statements is actually only -an issue for dataflow; passes like the borrow checker must assume that -closures could execute at any time from the moment they are created -until they go out of scope). - -### Complications due to closure bound inference - -There is only one problem with the above model: in general, we do not -actually *know* the closure bounds during region inference! In fact, -closure bounds are almost always region variables! This is very tricky -because the inference system implicitly assumes that we can do things -like compute the LUB of two scoped lifetimes without needing to know -the values of any variables. - -Here is an example to illustrate the problem: - - fn identify(x: T) -> T { x } - - fn foo() { // 'foo is the function body - 'a: { - let closure = identity(|| 'b: { - 'c: ... - }); - 'd: closure(); - } - 'e: ...; - } - -In this example, the closure bound is not explicit. At compile time, -we will create a region variable (let's call it `V0`) to represent the -closure bound. - -The primary difficulty arises during the constraint propagation phase. -Imagine there is some variable with incoming edges from `'c` and `'d`. -This means that the value of the variable must be `LUB('c, -'d)`. However, without knowing what the closure bound `V0` is, we -can't compute the LUB of `'c` and `'d`! Any we don't know the closure -bound until inference is done. - -The solution is to rely on the fixed point nature of inference. -Basically, when we must compute `LUB('c, 'd)`, we just use the current -value for `V0` as the closure's bound. If `V0`'s binding should -change, then we will do another round of inference, and the result of -`LUB('c, 'd)` will change. - -One minor implication of this is that the graph does not in fact track -the full set of dependencies between edges. We cannot easily know -whether the result of a LUB computation will change, since there may -be indirect dependencies on other variables that are not reflected on -the graph. Therefore, we must *always* iterate over all edges when -doing the fixed point calculation, not just those adjacent to nodes -whose values have changed. - -Were it not for this requirement, we could in fact avoid fixed-point -iteration altogether. In that universe, we could instead first -identify and remove strongly connected components (SCC) in the graph. -Note that such components must consist solely of region variables; all -of these variables can effectively be unified into a single variable. -Once SCCs are removed, we are left with a DAG. At this point, we -could walk the DAG in topological order once to compute the expanding -nodes, and again in reverse topological order to compute the -contracting nodes. However, as I said, this does not work given the -current treatment of closure bounds, but perhaps in the future we can -address this problem somehow and make region inference somewhat more -efficient. Note that this is solely a matter of performance, not -expressiveness. - -### Skolemization - -For a discussion on skolemization and higher-ranked subtyping, please -see the module `middle::typeck::infer::higher_ranked::doc`. - -*/ +//! Region inference module. +//! +//! # Terminology +//! +//! Note that we use the terms region and lifetime interchangeably, +//! though the term `lifetime` is preferred. +//! +//! # Introduction +//! +//! Region inference uses a somewhat more involved algorithm than type +//! inference. It is not the most efficient thing ever written though it +//! seems to work well enough in practice (famous last words). The reason +//! that we use a different algorithm is because, unlike with types, it is +//! impractical to hand-annotate with regions (in some cases, there aren't +//! even the requisite syntactic forms). So we have to get it right, and +//! it's worth spending more time on a more involved analysis. Moreover, +//! regions are a simpler case than types: they don't have aggregate +//! structure, for example. +//! +//! Unlike normal type inference, which is similar in spirit to H-M and thus +//! works progressively, the region type inference works by accumulating +//! constraints over the course of a function. Finally, at the end of +//! processing a function, we process and solve the constraints all at +//! once. +//! +//! The constraints are always of one of three possible forms: +//! +//! - ConstrainVarSubVar(R_i, R_j) states that region variable R_i +//! must be a subregion of R_j +//! - ConstrainRegSubVar(R, R_i) states that the concrete region R +//! (which must not be a variable) must be a subregion of the varibale R_i +//! - ConstrainVarSubReg(R_i, R) is the inverse +//! +//! # Building up the constraints +//! +//! Variables and constraints are created using the following methods: +//! +//! - `new_region_var()` creates a new, unconstrained region variable; +//! - `make_subregion(R_i, R_j)` states that R_i is a subregion of R_j +//! - `lub_regions(R_i, R_j) -> R_k` returns a region R_k which is +//! the smallest region that is greater than both R_i and R_j +//! - `glb_regions(R_i, R_j) -> R_k` returns a region R_k which is +//! the greatest region that is smaller than both R_i and R_j +//! +//! The actual region resolution algorithm is not entirely +//! obvious, though it is also not overly complex. +//! +//! ## Snapshotting +//! +//! It is also permitted to try (and rollback) changes to the graph. This +//! is done by invoking `start_snapshot()`, which returns a value. Then +//! later you can call `rollback_to()` which undoes the work. +//! Alternatively, you can call `commit()` which ends all snapshots. +//! Snapshots can be recursive---so you can start a snapshot when another +//! is in progress, but only the root snapshot can "commit". +//! +//! # Resolving constraints +//! +//! The constraint resolution algorithm is not super complex but also not +//! entirely obvious. Here I describe the problem somewhat abstractly, +//! then describe how the current code works. There may be other, smarter +//! ways of doing this with which I am unfamiliar and can't be bothered to +//! research at the moment. - NDM +//! +//! ## The problem +//! +//! Basically our input is a directed graph where nodes can be divided +//! into two categories: region variables and concrete regions. Each edge +//! `R -> S` in the graph represents a constraint that the region `R` is a +//! subregion of the region `S`. +//! +//! Region variable nodes can have arbitrary degree. There is one region +//! variable node per region variable. +//! +//! Each concrete region node is associated with some, well, concrete +//! region: e.g., a free lifetime, or the region for a particular scope. +//! Note that there may be more than one concrete region node for a +//! particular region value. Moreover, because of how the graph is built, +//! we know that all concrete region nodes have either in-degree 1 or +//! out-degree 1. +//! +//! Before resolution begins, we build up the constraints in a hashmap +//! that maps `Constraint` keys to spans. During resolution, we construct +//! the actual `Graph` structure that we describe here. +//! +//! ## Our current algorithm +//! +//! We divide region variables into two groups: Expanding and Contracting. +//! Expanding region variables are those that have a concrete region +//! predecessor (direct or indirect). Contracting region variables are +//! all others. +//! +//! We first resolve the values of Expanding region variables and then +//! process Contracting ones. We currently use an iterative, fixed-point +//! procedure (but read on, I believe this could be replaced with a linear +//! walk). Basically we iterate over the edges in the graph, ensuring +//! that, if the source of the edge has a value, then this value is a +//! subregion of the target value. If the target does not yet have a +//! value, it takes the value from the source. If the target already had +//! a value, then the resulting value is Least Upper Bound of the old and +//! new values. When we are done, each Expanding node will have the +//! smallest region that it could possibly have and still satisfy the +//! constraints. +//! +//! We next process the Contracting nodes. Here we again iterate over the +//! edges, only this time we move values from target to source (if the +//! source is a Contracting node). For each contracting node, we compute +//! its value as the GLB of all its successors. Basically contracting +//! nodes ensure that there is overlap between their successors; we will +//! ultimately infer the largest overlap possible. +//! +//! # The Region Hierarchy +//! +//! ## Without closures +//! +//! Let's first consider the region hierarchy without thinking about +//! closures, because they add a lot of complications. The region +//! hierarchy *basically* mirrors the lexical structure of the code. +//! There is a region for every piece of 'evaluation' that occurs, meaning +//! every expression, block, and pattern (patterns are considered to +//! "execute" by testing the value they are applied to and creating any +//! relevant bindings). So, for example: +//! +//! fn foo(x: int, y: int) { // -+ +//! // +------------+ // | +//! // | +-----+ // | +//! // | +-+ +-+ +-+ // | +//! // | | | | | | | // | +//! // v v v v v v v // | +//! let z = x + y; // | +//! ... // | +//! } // -+ +//! +//! fn bar() { ... } +//! +//! In this example, there is a region for the fn body block as a whole, +//! and then a subregion for the declaration of the local variable. +//! Within that, there are sublifetimes for the assignment pattern and +//! also the expression `x + y`. The expression itself has sublifetimes +//! for evaluating `x` and `y`. +//! +//! ## Function calls +//! +//! Function calls are a bit tricky. I will describe how we handle them +//! *now* and then a bit about how we can improve them (Issue #6268). +//! +//! Consider a function call like `func(expr1, expr2)`, where `func`, +//! `arg1`, and `arg2` are all arbitrary expressions. Currently, +//! we construct a region hierarchy like: +//! +//! +----------------+ +//! | | +//! +--+ +---+ +---+| +//! v v v v v vv +//! func(expr1, expr2) +//! +//! Here you can see that the call as a whole has a region and the +//! function plus arguments are subregions of that. As a side-effect of +//! this, we get a lot of spurious errors around nested calls, in +//! particular when combined with `&mut` functions. For example, a call +//! like this one +//! +//! self.foo(self.bar()) +//! +//! where both `foo` and `bar` are `&mut self` functions will always yield +//! an error. +//! +//! Here is a more involved example (which is safe) so we can see what's +//! going on: +//! +//! struct Foo { f: uint, g: uint } +//! ... +//! fn add(p: &mut uint, v: uint) { +//! *p += v; +//! } +//! ... +//! fn inc(p: &mut uint) -> uint { +//! *p += 1; *p +//! } +//! fn weird() { +//! let mut x: Box = box Foo { ... }; +//! 'a: add(&mut (*x).f, +//! 'b: inc(&mut (*x).f)) // (..) +//! } +//! +//! The important part is the line marked `(..)` which contains a call to +//! `add()`. The first argument is a mutable borrow of the field `f`. The +//! second argument also borrows the field `f`. Now, in the current borrow +//! checker, the first borrow is given the lifetime of the call to +//! `add()`, `'a`. The second borrow is given the lifetime of `'b` of the +//! call to `inc()`. Because `'b` is considered to be a sublifetime of +//! `'a`, an error is reported since there are two co-existing mutable +//! borrows of the same data. +//! +//! However, if we were to examine the lifetimes a bit more carefully, we +//! can see that this error is unnecessary. Let's examine the lifetimes +//! involved with `'a` in detail. We'll break apart all the steps involved +//! in a call expression: +//! +//! 'a: { +//! 'a_arg1: let a_temp1: ... = add; +//! 'a_arg2: let a_temp2: &'a mut uint = &'a mut (*x).f; +//! 'a_arg3: let a_temp3: uint = { +//! let b_temp1: ... = inc; +//! let b_temp2: &'b = &'b mut (*x).f; +//! 'b_call: b_temp1(b_temp2) +//! }; +//! 'a_call: a_temp1(a_temp2, a_temp3) // (**) +//! } +//! +//! Here we see that the lifetime `'a` includes a number of substatements. +//! In particular, there is this lifetime I've called `'a_call` that +//! corresponds to the *actual execution of the function `add()`*, after +//! all arguments have been evaluated. There is a corresponding lifetime +//! `'b_call` for the execution of `inc()`. If we wanted to be precise +//! about it, the lifetime of the two borrows should be `'a_call` and +//! `'b_call` respectively, since the references that were created +//! will not be dereferenced except during the execution itself. +//! +//! However, this model by itself is not sound. The reason is that +//! while the two references that are created will never be used +//! simultaneously, it is still true that the first reference is +//! *created* before the second argument is evaluated, and so even though +//! it will not be *dereferenced* during the evaluation of the second +//! argument, it can still be *invalidated* by that evaluation. Consider +//! this similar but unsound example: +//! +//! struct Foo { f: uint, g: uint } +//! ... +//! fn add(p: &mut uint, v: uint) { +//! *p += v; +//! } +//! ... +//! fn consume(x: Box) -> uint { +//! x.f + x.g +//! } +//! fn weird() { +//! let mut x: Box = box Foo { ... }; +//! 'a: add(&mut (*x).f, consume(x)) // (..) +//! } +//! +//! In this case, the second argument to `add` actually consumes `x`, thus +//! invalidating the first argument. +//! +//! So, for now, we exclude the `call` lifetimes from our model. +//! Eventually I would like to include them, but we will have to make the +//! borrow checker handle this situation correctly. In particular, if +//! there is a reference created whose lifetime does not enclose +//! the borrow expression, we must issue sufficient restrictions to ensure +//! that the pointee remains valid. +//! +//! ## Adding closures +//! +//! The other significant complication to the region hierarchy is +//! closures. I will describe here how closures should work, though some +//! of the work to implement this model is ongoing at the time of this +//! writing. +//! +//! The body of closures are type-checked along with the function that +//! creates them. However, unlike other expressions that appear within the +//! function body, it is not entirely obvious when a closure body executes +//! with respect to the other expressions. This is because the closure +//! body will execute whenever the closure is called; however, we can +//! never know precisely when the closure will be called, especially +//! without some sort of alias analysis. +//! +//! However, we can place some sort of limits on when the closure +//! executes. In particular, the type of every closure `fn:'r K` includes +//! a region bound `'r`. This bound indicates the maximum lifetime of that +//! closure; once we exit that region, the closure cannot be called +//! anymore. Therefore, we say that the lifetime of the closure body is a +//! sublifetime of the closure bound, but the closure body itself is unordered +//! with respect to other parts of the code. +//! +//! For example, consider the following fragment of code: +//! +//! 'a: { +//! let closure: fn:'a() = || 'b: { +//! 'c: ... +//! }; +//! 'd: ... +//! } +//! +//! Here we have four lifetimes, `'a`, `'b`, `'c`, and `'d`. The closure +//! `closure` is bounded by the lifetime `'a`. The lifetime `'b` is the +//! lifetime of the closure body, and `'c` is some statement within the +//! closure body. Finally, `'d` is a statement within the outer block that +//! created the closure. +//! +//! We can say that the closure body `'b` is a sublifetime of `'a` due to +//! the closure bound. By the usual lexical scoping conventions, the +//! statement `'c` is clearly a sublifetime of `'b`, and `'d` is a +//! sublifetime of `'d`. However, there is no ordering between `'c` and +//! `'d` per se (this kind of ordering between statements is actually only +//! an issue for dataflow; passes like the borrow checker must assume that +//! closures could execute at any time from the moment they are created +//! until they go out of scope). +//! +//! ### Complications due to closure bound inference +//! +//! There is only one problem with the above model: in general, we do not +//! actually *know* the closure bounds during region inference! In fact, +//! closure bounds are almost always region variables! This is very tricky +//! because the inference system implicitly assumes that we can do things +//! like compute the LUB of two scoped lifetimes without needing to know +//! the values of any variables. +//! +//! Here is an example to illustrate the problem: +//! +//! fn identify(x: T) -> T { x } +//! +//! fn foo() { // 'foo is the function body +//! 'a: { +//! let closure = identity(|| 'b: { +//! 'c: ... +//! }); +//! 'd: closure(); +//! } +//! 'e: ...; +//! } +//! +//! In this example, the closure bound is not explicit. At compile time, +//! we will create a region variable (let's call it `V0`) to represent the +//! closure bound. +//! +//! The primary difficulty arises during the constraint propagation phase. +//! Imagine there is some variable with incoming edges from `'c` and `'d`. +//! This means that the value of the variable must be `LUB('c, +//! 'd)`. However, without knowing what the closure bound `V0` is, we +//! can't compute the LUB of `'c` and `'d`! Any we don't know the closure +//! bound until inference is done. +//! +//! The solution is to rely on the fixed point nature of inference. +//! Basically, when we must compute `LUB('c, 'd)`, we just use the current +//! value for `V0` as the closure's bound. If `V0`'s binding should +//! change, then we will do another round of inference, and the result of +//! `LUB('c, 'd)` will change. +//! +//! One minor implication of this is that the graph does not in fact track +//! the full set of dependencies between edges. We cannot easily know +//! whether the result of a LUB computation will change, since there may +//! be indirect dependencies on other variables that are not reflected on +//! the graph. Therefore, we must *always* iterate over all edges when +//! doing the fixed point calculation, not just those adjacent to nodes +//! whose values have changed. +//! +//! Were it not for this requirement, we could in fact avoid fixed-point +//! iteration altogether. In that universe, we could instead first +//! identify and remove strongly connected components (SCC) in the graph. +//! Note that such components must consist solely of region variables; all +//! of these variables can effectively be unified into a single variable. +//! Once SCCs are removed, we are left with a DAG. At this point, we +//! could walk the DAG in topological order once to compute the expanding +//! nodes, and again in reverse topological order to compute the +//! contracting nodes. However, as I said, this does not work given the +//! current treatment of closure bounds, but perhaps in the future we can +//! address this problem somehow and make region inference somewhat more +//! efficient. Note that this is solely a matter of performance, not +//! expressiveness. +//! +//! ### Skolemization +//! +//! For a discussion on skolemization and higher-ranked subtyping, please +//! see the module `middle::typeck::infer::higher_ranked::doc`. diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index 6a447d467cf..01533cba7ab 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! See doc.rs */ +//! See doc.rs pub use self::Constraint::*; pub use self::Verify::*; @@ -597,15 +597,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { .collect() } + /// Computes all regions that have been related to `r0` in any way since the mark `mark` was + /// made---`r0` itself will be the first entry. This is used when checking whether skolemized + /// regions are being improperly related to other regions. pub fn tainted(&self, mark: RegionMark, r0: Region) -> Vec { - /*! - * Computes all regions that have been related to `r0` in any - * way since the mark `mark` was made---`r0` itself will be - * the first entry. This is used when checking whether - * skolemized regions are being improperly related to other - * regions. - */ - debug!("tainted(mark={}, r0={})", mark, r0.repr(self.tcx)); let _indenter = indenter(); @@ -783,16 +778,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } } + /// Computes a region that encloses both free region arguments. Guarantee that if the same two + /// regions are given as argument, in any order, a consistent result is returned. fn lub_free_regions(&self, a: &FreeRegion, b: &FreeRegion) -> ty::Region { - /*! - * Computes a region that encloses both free region arguments. - * Guarantee that if the same two regions are given as argument, - * in any order, a consistent result is returned. - */ - return match a.cmp(b) { Less => helper(self, a, b), Greater => helper(self, b, a), @@ -884,16 +875,13 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } } + /// Computes a region that is enclosed by both free region arguments, if any. Guarantees that + /// if the same two regions are given as argument, in any order, a consistent result is + /// returned. fn glb_free_regions(&self, a: &FreeRegion, b: &FreeRegion) -> cres<'tcx, ty::Region> { - /*! - * Computes a region that is enclosed by both free region arguments, - * if any. Guarantees that if the same two regions are given as argument, - * in any order, a consistent result is returned. - */ - return match a.cmp(b) { Less => helper(self, a, b), Greater => helper(self, b, a), diff --git a/src/librustc/middle/typeck/infer/skolemize.rs b/src/librustc/middle/typeck/infer/skolemize.rs index 5907a2bb9b6..62bf1d0126a 100644 --- a/src/librustc/middle/typeck/infer/skolemize.rs +++ b/src/librustc/middle/typeck/infer/skolemize.rs @@ -8,37 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Skolemization is the process of replacing unknown variables with - * fresh types. The idea is that the type, after skolemization, - * contains no inference variables but instead contains either a value - * for each variable or fresh "arbitrary" types wherever a variable - * would have been. - * - * Skolemization is used primarily to get a good type for inserting - * into a cache. The result summarizes what the type inferencer knows - * "so far". The primary place it is used right now is in the trait - * matching algorithm, which needs to be able to cache whether an - * `impl` self type matches some other type X -- *without* affecting - * `X`. That means if that if the type `X` is in fact an unbound type - * variable, we want the match to be regarded as ambiguous, because - * depending on what type that type variable is ultimately assigned, - * the match may or may not succeed. - * - * Note that you should be careful not to allow the output of - * skolemization to leak to the user in error messages or in any other - * form. Skolemization is only really useful as an internal detail. - * - * __An important detail concerning regions.__ The skolemizer also - * replaces *all* regions with 'static. The reason behind this is - * that, in general, we do not take region relationships into account - * when making type-overloaded decisions. This is important because of - * the design of the region inferencer, which is not based on - * unification but rather on accumulating and then solving a set of - * constraints. In contrast, the type inferencer assigns a value to - * each type variable only once, and it does so as soon as it can, so - * it is reasonable to ask what the type inferencer knows "so far". - */ +//! Skolemization is the process of replacing unknown variables with fresh types. The idea is that +//! the type, after skolemization, contains no inference variables but instead contains either a +//! value for each variable or fresh "arbitrary" types wherever a variable would have been. +//! +//! Skolemization is used primarily to get a good type for inserting into a cache. The result +//! summarizes what the type inferencer knows "so far". The primary place it is used right now is +//! in the trait matching algorithm, which needs to be able to cache whether an `impl` self type +//! matches some other type X -- *without* affecting `X`. That means if that if the type `X` is in +//! fact an unbound type variable, we want the match to be regarded as ambiguous, because depending +//! on what type that type variable is ultimately assigned, the match may or may not succeed. +//! +//! Note that you should be careful not to allow the output of skolemization to leak to the user in +//! error messages or in any other form. Skolemization is only really useful as an internal detail. +//! +//! __An important detail concerning regions.__ The skolemizer also replaces *all* regions with +//! 'static. The reason behind this is that, in general, we do not take region relationships into +//! account when making type-overloaded decisions. This is important because of the design of the +//! region inferencer, which is not based on unification but rather on accumulating and then +//! solving a set of constraints. In contrast, the type inferencer assigns a value to each type +//! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type +//! inferencer knows "so far". use middle::ty::{mod, Ty}; use middle::ty_fold; diff --git a/src/librustc/middle/typeck/infer/type_variable.rs b/src/librustc/middle/typeck/infer/type_variable.rs index f7f7389602f..3058f09a83a 100644 --- a/src/librustc/middle/typeck/infer/type_variable.rs +++ b/src/librustc/middle/typeck/infer/type_variable.rs @@ -72,12 +72,10 @@ impl<'tcx> TypeVariableTable<'tcx> { self.values.get(vid.index).diverging } + /// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`. + /// + /// Precondition: neither `a` nor `b` are known. pub fn relate_vars(&mut self, a: ty::TyVid, dir: RelationDir, b: ty::TyVid) { - /*! - * Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`. - * - * Precondition: neither `a` nor `b` are known. - */ if a != b { self.relations(a).push((dir, b)); @@ -86,19 +84,15 @@ impl<'tcx> TypeVariableTable<'tcx> { } } + /// Instantiates `vid` with the type `ty` and then pushes an entry onto `stack` for each of the + /// relations of `vid` to other variables. The relations will have the form `(ty, dir, vid1)` + /// where `vid1` is some other variable id. pub fn instantiate_and_push( &mut self, vid: ty::TyVid, ty: Ty<'tcx>, stack: &mut Vec<(Ty<'tcx>, RelationDir, ty::TyVid)>) { - /*! - * Instantiates `vid` with the type `ty` and then pushes an - * entry onto `stack` for each of the relations of `vid` to - * other variables. The relations will have the form `(ty, - * dir, vid1)` where `vid1` is some other variable id. - */ - let old_value = { let value_ptr = &mut self.values.get_mut(vid.index).value; mem::replace(value_ptr, Known(ty)) diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index fcf042b3f8b..38f55cc3f46 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -157,13 +157,9 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable Node { - /*! - * Find the root node for `vid`. This uses the standard - * union-find algorithm with path compression: - * http://en.wikipedia.org/wiki/Disjoint-set_data_structure - */ - let index = vid.index(); let value = (*self.values.get(index)).clone(); match value { @@ -188,16 +184,13 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable, key: K, new_value: VarValue) { - /*! - * Sets the value for `vid` to `new_value`. `vid` MUST be a - * root node! Also, we must be in the middle of a snapshot. - */ - assert!(self.is_root(&key)); debug!("Updating variable {} to {}", @@ -207,19 +200,15 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable, node_a: &Node, node_b: &Node) -> (K, uint) { - /*! - * Either redirects node_a to node_b or vice versa, depending - * on the relative rank. Returns the new root and rank. You - * should then update the value of the new root to something - * suitable. - */ - debug!("unify(node_a(id={}, rank={}), node_b(id={}, rank={}))", node_a.key.repr(tcx), node_a.rank, @@ -295,19 +284,15 @@ pub trait InferCtxtMethodsForSimplyUnifiableTypes<'tcx, V:SimplyUnifiable<'tcx>, impl<'a,'tcx,V:SimplyUnifiable<'tcx>,K:UnifyKey<'tcx, Option>> InferCtxtMethodsForSimplyUnifiableTypes<'tcx, V, K> for InferCtxt<'a, 'tcx> { + /// Unifies two simple keys. Because simple keys do not have any subtyping relationships, if + /// both keys have already been associated with a value, then those two values must be the + /// same. fn simple_vars(&self, a_is_expected: bool, a_id: K, b_id: K) -> ures<'tcx> { - /*! - * Unifies two simple keys. Because simple keys do - * not have any subtyping relationships, if both keys - * have already been associated with a value, then those two - * values must be the same. - */ - let tcx = self.tcx; let table = UnifyKey::unification_table(self); let node_a = table.borrow_mut().get(tcx, a_id); @@ -341,19 +326,14 @@ impl<'a,'tcx,V:SimplyUnifiable<'tcx>,K:UnifyKey<'tcx, Option>> return Ok(()) } + /// Sets the value of the key `a_id` to `b`. Because simple keys do not have any subtyping + /// relationships, if `a_id` already has a value, it must be the same as `b`. fn simple_var_t(&self, a_is_expected: bool, a_id: K, b: V) -> ures<'tcx> { - /*! - * Sets the value of the key `a_id` to `b`. Because - * simple keys do not have any subtyping relationships, - * if `a_id` already has a value, it must be the same as - * `b`. - */ - let tcx = self.tcx; let table = UnifyKey::unification_table(self); let node_a = table.borrow_mut().get(tcx, a_id); diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index 51b610dccce..fa001f0434f 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -8,189 +8,186 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -This file infers the variance of type and lifetime parameters. The -algorithm is taken from Section 4 of the paper "Taming the Wildcards: -Combining Definition- and Use-Site Variance" published in PLDI'11 and -written by Altidor et al., and hereafter referred to as The Paper. - -This inference is explicitly designed *not* to consider the uses of -types within code. To determine the variance of type parameters -defined on type `X`, we only consider the definition of the type `X` -and the definitions of any types it references. - -We only infer variance for type parameters found on *types*: structs, -enums, and traits. We do not infer variance for type parameters found -on fns or impls. This is because those things are not type definitions -and variance doesn't really make sense in that context. - -It is worth covering what variance means in each case. For structs and -enums, I think it is fairly straightforward. The variance of the type -or lifetime parameters defines whether `T` is a subtype of `T` -(resp. `T<'a>` and `T<'b>`) based on the relationship of `A` and `B` -(resp. `'a` and `'b`). (FIXME #3598 -- we do not currently make use of -the variances we compute for type parameters.) - -### Variance on traits - -The meaning of variance for trait parameters is more subtle and worth -expanding upon. There are in fact two uses of the variance values we -compute. - -#### Trait variance and object types - -The first is for object types. Just as with structs and enums, we can -decide the subtyping relationship between two object types `&Trait` -and `&Trait` based on the relationship of `A` and `B`. Note that -for object types we ignore the `Self` type parameter -- it is unknown, -and the nature of dynamic dispatch ensures that we will always call a -function that is expected the appropriate `Self` type. However, we -must be careful with the other type parameters, or else we could end -up calling a function that is expecting one type but provided another. - -To see what I mean, consider a trait like so: - - trait ConvertTo { - fn convertTo(&self) -> A; - } - -Intuitively, If we had one object `O=&ConvertTo` and another -`S=&ConvertTo`, then `S <: O` because `String <: Object` -(presuming Java-like "string" and "object" types, my go to examples -for subtyping). The actual algorithm would be to compare the -(explicit) type parameters pairwise respecting their variance: here, -the type parameter A is covariant (it appears only in a return -position), and hence we require that `String <: Object`. - -You'll note though that we did not consider the binding for the -(implicit) `Self` type parameter: in fact, it is unknown, so that's -good. The reason we can ignore that parameter is precisely because we -don't need to know its value until a call occurs, and at that time (as -you said) the dynamic nature of virtual dispatch means the code we run -will be correct for whatever value `Self` happens to be bound to for -the particular object whose method we called. `Self` is thus different -from `A`, because the caller requires that `A` be known in order to -know the return type of the method `convertTo()`. (As an aside, we -have rules preventing methods where `Self` appears outside of the -receiver position from being called via an object.) - -#### Trait variance and vtable resolution - -But traits aren't only used with objects. They're also used when -deciding whether a given impl satisfies a given trait bound. To set the -scene here, imagine I had a function: - - fn convertAll>(v: &[T]) { - ... - } - -Now imagine that I have an implementation of `ConvertTo` for `Object`: - - impl ConvertTo for Object { ... } - -And I want to call `convertAll` on an array of strings. Suppose -further that for whatever reason I specifically supply the value of -`String` for the type parameter `T`: - - let mut vector = ~["string", ...]; - convertAll::(v); - -Is this legal? To put another way, can we apply the `impl` for -`Object` to the type `String`? The answer is yes, but to see why -we have to expand out what will happen: - -- `convertAll` will create a pointer to one of the entries in the - vector, which will have type `&String` -- It will then call the impl of `convertTo()` that is intended - for use with objects. This has the type: - - fn(self: &Object) -> int - - It is ok to provide a value for `self` of type `&String` because - `&String <: &Object`. - -OK, so intuitively we want this to be legal, so let's bring this back -to variance and see whether we are computing the correct result. We -must first figure out how to phrase the question "is an impl for -`Object,int` usable where an impl for `String,int` is expected?" - -Maybe it's helpful to think of a dictionary-passing implementation of -type classes. In that case, `convertAll()` takes an implicit parameter -representing the impl. In short, we *have* an impl of type: - - V_O = ConvertTo for Object - -and the function prototype expects an impl of type: - - V_S = ConvertTo for String - -As with any argument, this is legal if the type of the value given -(`V_O`) is a subtype of the type expected (`V_S`). So is `V_O <: V_S`? -The answer will depend on the variance of the various parameters. In -this case, because the `Self` parameter is contravariant and `A` is -covariant, it means that: +//! This file infers the variance of type and lifetime parameters. The +//! algorithm is taken from Section 4 of the paper "Taming the Wildcards: +//! Combining Definition- and Use-Site Variance" published in PLDI'11 and +//! written by Altidor et al., and hereafter referred to as The Paper. +//! +//! This inference is explicitly designed *not* to consider the uses of +//! types within code. To determine the variance of type parameters +//! defined on type `X`, we only consider the definition of the type `X` +//! and the definitions of any types it references. +//! +//! We only infer variance for type parameters found on *types*: structs, +//! enums, and traits. We do not infer variance for type parameters found +//! on fns or impls. This is because those things are not type definitions +//! and variance doesn't really make sense in that context. +//! +//! It is worth covering what variance means in each case. For structs and +//! enums, I think it is fairly straightforward. The variance of the type +//! or lifetime parameters defines whether `T` is a subtype of `T` +//! (resp. `T<'a>` and `T<'b>`) based on the relationship of `A` and `B` +//! (resp. `'a` and `'b`). (FIXME #3598 -- we do not currently make use of +//! the variances we compute for type parameters.) +//! +//! ### Variance on traits +//! +//! The meaning of variance for trait parameters is more subtle and worth +//! expanding upon. There are in fact two uses of the variance values we +//! compute. +//! +//! #### Trait variance and object types +//! +//! The first is for object types. Just as with structs and enums, we can +//! decide the subtyping relationship between two object types `&Trait` +//! and `&Trait` based on the relationship of `A` and `B`. Note that +//! for object types we ignore the `Self` type parameter -- it is unknown, +//! and the nature of dynamic dispatch ensures that we will always call a +//! function that is expected the appropriate `Self` type. However, we +//! must be careful with the other type parameters, or else we could end +//! up calling a function that is expecting one type but provided another. +//! +//! To see what I mean, consider a trait like so: +//! +//! trait ConvertTo { +//! fn convertTo(&self) -> A; +//! } +//! +//! Intuitively, If we had one object `O=&ConvertTo` and another +//! `S=&ConvertTo`, then `S <: O` because `String <: Object` +//! (presuming Java-like "string" and "object" types, my go to examples +//! for subtyping). The actual algorithm would be to compare the +//! (explicit) type parameters pairwise respecting their variance: here, +//! the type parameter A is covariant (it appears only in a return +//! position), and hence we require that `String <: Object`. +//! +//! You'll note though that we did not consider the binding for the +//! (implicit) `Self` type parameter: in fact, it is unknown, so that's +//! good. The reason we can ignore that parameter is precisely because we +//! don't need to know its value until a call occurs, and at that time (as +//! you said) the dynamic nature of virtual dispatch means the code we run +//! will be correct for whatever value `Self` happens to be bound to for +//! the particular object whose method we called. `Self` is thus different +//! from `A`, because the caller requires that `A` be known in order to +//! know the return type of the method `convertTo()`. (As an aside, we +//! have rules preventing methods where `Self` appears outside of the +//! receiver position from being called via an object.) +//! +//! #### Trait variance and vtable resolution +//! +//! But traits aren't only used with objects. They're also used when +//! deciding whether a given impl satisfies a given trait bound. To set the +//! scene here, imagine I had a function: +//! +//! fn convertAll>(v: &[T]) { +//! ... +//! } +//! +//! Now imagine that I have an implementation of `ConvertTo` for `Object`: +//! +//! impl ConvertTo for Object { ... } +//! +//! And I want to call `convertAll` on an array of strings. Suppose +//! further that for whatever reason I specifically supply the value of +//! `String` for the type parameter `T`: +//! +//! let mut vector = ~["string", ...]; +//! convertAll::(v); +//! +//! Is this legal? To put another way, can we apply the `impl` for +//! `Object` to the type `String`? The answer is yes, but to see why +//! we have to expand out what will happen: +//! +//! - `convertAll` will create a pointer to one of the entries in the +//! vector, which will have type `&String` +//! - It will then call the impl of `convertTo()` that is intended +//! for use with objects. This has the type: +//! +//! fn(self: &Object) -> int +//! +//! It is ok to provide a value for `self` of type `&String` because +//! `&String <: &Object`. +//! +//! OK, so intuitively we want this to be legal, so let's bring this back +//! to variance and see whether we are computing the correct result. We +//! must first figure out how to phrase the question "is an impl for +//! `Object,int` usable where an impl for `String,int` is expected?" +//! +//! Maybe it's helpful to think of a dictionary-passing implementation of +//! type classes. In that case, `convertAll()` takes an implicit parameter +//! representing the impl. In short, we *have* an impl of type: +//! +//! V_O = ConvertTo for Object +//! +//! and the function prototype expects an impl of type: +//! +//! V_S = ConvertTo for String +//! +//! As with any argument, this is legal if the type of the value given +//! (`V_O`) is a subtype of the type expected (`V_S`). So is `V_O <: V_S`? +//! The answer will depend on the variance of the various parameters. In +//! this case, because the `Self` parameter is contravariant and `A` is +//! covariant, it means that: +//! +//! V_O <: V_S iff +//! int <: int +//! String <: Object +//! +//! These conditions are satisfied and so we are happy. +//! +//! ### The algorithm +//! +//! The basic idea is quite straightforward. We iterate over the types +//! defined and, for each use of a type parameter X, accumulate a +//! constraint indicating that the variance of X must be valid for the +//! variance of that use site. We then iteratively refine the variance of +//! X until all constraints are met. There is *always* a sol'n, because at +//! the limit we can declare all type parameters to be invariant and all +//! constraints will be satisfied. +//! +//! As a simple example, consider: +//! +//! enum Option { Some(A), None } +//! enum OptionalFn { Some(|B|), None } +//! enum OptionalMap { Some(|C| -> C), None } +//! +//! Here, we will generate the constraints: +//! +//! 1. V(A) <= + +//! 2. V(B) <= - +//! 3. V(C) <= + +//! 4. V(C) <= - +//! +//! These indicate that (1) the variance of A must be at most covariant; +//! (2) the variance of B must be at most contravariant; and (3, 4) the +//! variance of C must be at most covariant *and* contravariant. All of these +//! results are based on a variance lattice defined as follows: +//! +//! * Top (bivariant) +//! - + +//! o Bottom (invariant) +//! +//! Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the +//! optimal solution. Note that there is always a naive solution which +//! just declares all variables to be invariant. +//! +//! You may be wondering why fixed-point iteration is required. The reason +//! is that the variance of a use site may itself be a function of the +//! variance of other type parameters. In full generality, our constraints +//! take the form: +//! +//! V(X) <= Term +//! Term := + | - | * | o | V(X) | Term x Term +//! +//! Here the notation V(X) indicates the variance of a type/region +//! parameter `X` with respect to its defining class. `Term x Term` +//! represents the "variance transform" as defined in the paper: +//! +//! If the variance of a type variable `X` in type expression `E` is `V2` +//! and the definition-site variance of the [corresponding] type parameter +//! of a class `C` is `V1`, then the variance of `X` in the type expression +//! `C` is `V3 = V1.xform(V2)`. - V_O <: V_S iff - int <: int - String <: Object - -These conditions are satisfied and so we are happy. - -### The algorithm - -The basic idea is quite straightforward. We iterate over the types -defined and, for each use of a type parameter X, accumulate a -constraint indicating that the variance of X must be valid for the -variance of that use site. We then iteratively refine the variance of -X until all constraints are met. There is *always* a sol'n, because at -the limit we can declare all type parameters to be invariant and all -constraints will be satisfied. - -As a simple example, consider: - - enum Option { Some(A), None } - enum OptionalFn { Some(|B|), None } - enum OptionalMap { Some(|C| -> C), None } - -Here, we will generate the constraints: - - 1. V(A) <= + - 2. V(B) <= - - 3. V(C) <= + - 4. V(C) <= - - -These indicate that (1) the variance of A must be at most covariant; -(2) the variance of B must be at most contravariant; and (3, 4) the -variance of C must be at most covariant *and* contravariant. All of these -results are based on a variance lattice defined as follows: - - * Top (bivariant) - - + - o Bottom (invariant) - -Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the -optimal solution. Note that there is always a naive solution which -just declares all variables to be invariant. - -You may be wondering why fixed-point iteration is required. The reason -is that the variance of a use site may itself be a function of the -variance of other type parameters. In full generality, our constraints -take the form: - - V(X) <= Term - Term := + | - | * | o | V(X) | Term x Term - -Here the notation V(X) indicates the variance of a type/region -parameter `X` with respect to its defining class. `Term x Term` -represents the "variance transform" as defined in the paper: - - If the variance of a type variable `X` in type expression `E` is `V2` - and the definition-site variance of the [corresponding] type parameter - of a class `C` is `V1`, then the variance of `X` in the type expression - `C` is `V3 = V1.xform(V2)`. - -*/ use self::VarianceTerm::*; use self::ParamKind::*; @@ -632,6 +629,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { return result; } + /// Returns a variance term representing the declared variance of the type/region parameter + /// with the given id. fn declared_variance(&self, param_def_id: ast::DefId, item_def_id: ast::DefId, @@ -639,11 +638,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { space: ParamSpace, index: uint) -> VarianceTermPtr<'a> { - /*! - * Returns a variance term representing the declared variance of - * the type/region parameter with the given id. - */ - assert_eq!(param_def_id.krate, item_def_id.krate); if self.invariant_lang_items[kind as uint] == Some(item_def_id) { diff --git a/src/librustc/plugin/mod.rs b/src/librustc/plugin/mod.rs index a03ee471be6..8dd60880cdd 100644 --- a/src/librustc/plugin/mod.rs +++ b/src/librustc/plugin/mod.rs @@ -8,54 +8,52 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Infrastructure for compiler plugins. - * - * Plugins are Rust libraries which extend the behavior of `rustc` - * in various ways. - * - * Plugin authors will use the `Registry` type re-exported by - * this module, along with its methods. The rest of the module - * is for use by `rustc` itself. - * - * To define a plugin, build a dylib crate with a - * `#[plugin_registrar]` function: - * - * ```rust,ignore - * #![crate_name = "myplugin"] - * #![crate_type = "dylib"] - * #![feature(plugin_registrar)] - * - * extern crate rustc; - * - * use rustc::plugin::Registry; - * - * #[plugin_registrar] - * pub fn plugin_registrar(reg: &mut Registry) { - * reg.register_macro("mymacro", expand_mymacro); - * } - * - * fn expand_mymacro(...) { // details elided - * ``` - * - * WARNING: We currently don't check that the registrar function - * has the appropriate type! - * - * To use a plugin while compiling another crate: - * - * ```rust - * #![feature(phase)] - * - * #[phase(plugin)] - * extern crate myplugin; - * ``` - * - * If you also need the plugin crate available at runtime, use - * `phase(plugin, link)`. - * - * See [the compiler plugin guide](../../guide-plugin.html) - * for more examples. - */ +//! Infrastructure for compiler plugins. +//! +//! Plugins are Rust libraries which extend the behavior of `rustc` +//! in various ways. +//! +//! Plugin authors will use the `Registry` type re-exported by +//! this module, along with its methods. The rest of the module +//! is for use by `rustc` itself. +//! +//! To define a plugin, build a dylib crate with a +//! `#[plugin_registrar]` function: +//! +//! ```rust,ignore +//! #![crate_name = "myplugin"] +//! #![crate_type = "dylib"] +//! #![feature(plugin_registrar)] +//! +//! extern crate rustc; +//! +//! use rustc::plugin::Registry; +//! +//! #[plugin_registrar] +//! pub fn plugin_registrar(reg: &mut Registry) { +//! reg.register_macro("mymacro", expand_mymacro); +//! } +//! +//! fn expand_mymacro(...) { // details elided +//! ``` +//! +//! WARNING: We currently don't check that the registrar function +//! has the appropriate type! +//! +//! To use a plugin while compiling another crate: +//! +//! ```rust +//! #![feature(phase)] +//! +//! #[phase(plugin)] +//! extern crate myplugin; +//! ``` +//! +//! If you also need the plugin crate available at runtime, use +//! `phase(plugin, link)`. +//! +//! See [the compiler plugin guide](../../guide-plugin.html) +//! for more examples. pub use self::registry::Registry; diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 7973004d515..ea252d9fd20 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -122,24 +122,20 @@ pub fn block_query(b: &ast::Block, p: |&ast::Expr| -> bool) -> bool { return v.flag; } -// K: Eq + Hash, V, S, H: Hasher +/// K: Eq + Hash, V, S, H: Hasher +/// +/// Determines whether there exists a path from `source` to `destination`. The graph is defined by +/// the `edges_map`, which maps from a node `S` to a list of its adjacent nodes `T`. +/// +/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on +/// very small graphs. If the graphs become larger, a more efficient graph representation and +/// algorithm would probably be advised. pub fn can_reach,T:Eq+Clone+Hash>( edges_map: &HashMap,H>, source: T, destination: T) -> bool { - /*! - * Determines whether there exists a path from `source` to - * `destination`. The graph is defined by the `edges_map`, which - * maps from a node `S` to a list of its adjacent nodes `T`. - * - * Efficiency note: This is implemented in an inefficient way - * because it is typically invoked on very small graphs. If the graphs - * become larger, a more efficient graph representation and algorithm - * would probably be advised. - */ - if source == destination { return true; } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 761a1f66501..b739a97f734 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -65,12 +65,9 @@ pub fn note_and_explain_region(cx: &ctxt, } } +/// When a free region is associated with `item`, how should we describe the item in the error +/// message. fn item_scope_tag(item: &ast::Item) -> &'static str { - /*! - * When a free region is associated with `item`, how should we describe - * the item in the error message. - */ - match item.node { ast::ItemImpl(..) => "impl", ast::ItemStruct(..) => "struct", diff --git a/src/librustc/util/snapshot_vec.rs b/src/librustc/util/snapshot_vec.rs index 91e67bbacc3..64e67a1f4bf 100644 --- a/src/librustc/util/snapshot_vec.rs +++ b/src/librustc/util/snapshot_vec.rs @@ -8,21 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * A utility class for implementing "snapshottable" things; a - * snapshottable data structure permits you to take a snapshot (via - * `start_snapshot`) and then, after making some changes, elect either - * to rollback to the start of the snapshot or commit those changes. - * - * This vector is intended to be used as part of an abstraction, not - * serve as a complete abstraction on its own. As such, while it will - * roll back most changes on its own, it also supports a `get_mut` - * operation that gives you an abitrary mutable pointer into the - * vector. To ensure that any changes you make this with this pointer - * are rolled back, you must invoke `record` to record any changes you - * make and also supplying a delegate capable of reversing those - * changes. - */ +//! A utility class for implementing "snapshottable" things; a snapshottable data structure permits +//! you to take a snapshot (via `start_snapshot`) and then, after making some changes, elect either +//! to rollback to the start of the snapshot or commit those changes. +//! +//! This vector is intended to be used as part of an abstraction, not serve as a complete +//! abstraction on its own. As such, while it will roll back most changes on its own, it also +//! supports a `get_mut` operation that gives you an abitrary mutable pointer into the vector. To +//! ensure that any changes you make this with this pointer are rolled back, you must invoke +//! `record` to record any changes you make and also supplying a delegate capable of reversing +//! those changes. use self::UndoLog::*; use std::kinds::marker; @@ -98,23 +93,16 @@ impl> SnapshotVec { &self.values[index] } + /// Returns a mutable pointer into the vec; whatever changes you make here cannot be undone + /// automatically, so you should be sure call `record()` with some sort of suitable undo + /// action. pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T { - /*! - * Returns a mutable pointer into the vec; whatever changes - * you make here cannot be undone automatically, so you should - * be sure call `record()` with some sort of suitable undo - * action. - */ - &mut self.values[index] } + /// Updates the element at the given index. The old value will saved (and perhaps restored) if + /// a snapshot is active. pub fn set(&mut self, index: uint, new_elem: T) { - /*! - * Updates the element at the given index. The old value will - * saved (and perhaps restored) if a snapshot is active. - */ - let old_elem = mem::replace(&mut self.values[index], new_elem); if self.in_snapshot() { self.undo_log.push(SetElem(index, old_elem)); diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index f89580b768e..4186f479fcc 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -8,15 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -The Rust compiler. - -# Note - -This API is completely unstable and subject to change. - -*/ +//! The Rust compiler. +//! +//! # Note +//! +//! This API is completely unstable and subject to change. #![crate_name = "rustc_trans"] #![experimental] diff --git a/src/librustc_trans/test.rs b/src/librustc_trans/test.rs index 1e8c1fd1478..41fbe855769 100644 --- a/src/librustc_trans/test.rs +++ b/src/librustc_trans/test.rs @@ -8,11 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -# Standalone Tests for the Inference Module - -*/ +//! # Standalone Tests for the Inference Module use driver::diagnostic; use driver::diagnostic::Emitter; @@ -537,12 +533,10 @@ fn glb_bound_static() { }) } +/// Test substituting a bound region into a function, which introduces another level of binding. +/// This requires adjusting the Debruijn index. #[test] fn subst_ty_renumber_bound() { - /*! - * Test substituting a bound region into a function, which introduces another - * level of binding. This requires adjusting the Debruijn index. - */ test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { // Situation: @@ -575,13 +569,10 @@ fn subst_ty_renumber_bound() { }) } +/// Test substituting a bound region into a function, which introduces another level of binding. +/// This requires adjusting the Debruijn index. #[test] fn subst_ty_renumber_some_bounds() { - /*! - * Test substituting a bound region into a function, which introduces another - * level of binding. This requires adjusting the Debruijn index. - */ - test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { // Situation: // Theta = [A -> &'a foo] @@ -615,12 +606,9 @@ fn subst_ty_renumber_some_bounds() { }) } +/// Test that we correctly compute whether a type has escaping regions or not. #[test] fn escaping() { - /*! - * Test that we correctly compute whether a type has escaping - * regions or not. - */ test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { // Situation: @@ -658,12 +646,10 @@ fn escaping() { }) } +/// Test applying a substitution where the value being substituted for an early-bound region is a +/// late-bound region. #[test] fn subst_region_renumber_region() { - /*! - * Test applying a substitution where the value being substituted - * for an early-bound region is a late-bound region. - */ test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let re_bound1 = env.re_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1)); diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 381220d587c..d83eeadc7b9 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -8,183 +8,179 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * - * # Compilation of match statements - * - * I will endeavor to explain the code as best I can. I have only a loose - * understanding of some parts of it. - * - * ## Matching - * - * The basic state of the code is maintained in an array `m` of `Match` - * objects. Each `Match` describes some list of patterns, all of which must - * match against the current list of values. If those patterns match, then - * the arm listed in the match is the correct arm. A given arm may have - * multiple corresponding match entries, one for each alternative that - * remains. As we proceed these sets of matches are adjusted by the various - * `enter_XXX()` functions, each of which adjusts the set of options given - * some information about the value which has been matched. - * - * So, initially, there is one value and N matches, each of which have one - * constituent pattern. N here is usually the number of arms but may be - * greater, if some arms have multiple alternatives. For example, here: - * - * enum Foo { A, B(int), C(uint, uint) } - * match foo { - * A => ..., - * B(x) => ..., - * C(1u, 2) => ..., - * C(_) => ... - * } - * - * The value would be `foo`. There would be four matches, each of which - * contains one pattern (and, in one case, a guard). We could collect the - * various options and then compile the code for the case where `foo` is an - * `A`, a `B`, and a `C`. When we generate the code for `C`, we would (1) - * drop the two matches that do not match a `C` and (2) expand the other two - * into two patterns each. In the first case, the two patterns would be `1u` - * and `2`, and the in the second case the _ pattern would be expanded into - * `_` and `_`. The two values are of course the arguments to `C`. - * - * Here is a quick guide to the various functions: - * - * - `compile_submatch()`: The main workhouse. It takes a list of values and - * a list of matches and finds the various possibilities that could occur. - * - * - `enter_XXX()`: modifies the list of matches based on some information - * about the value that has been matched. For example, - * `enter_rec_or_struct()` adjusts the values given that a record or struct - * has been matched. This is an infallible pattern, so *all* of the matches - * must be either wildcards or record/struct patterns. `enter_opt()` - * handles the fallible cases, and it is correspondingly more complex. - * - * ## Bindings - * - * We store information about the bound variables for each arm as part of the - * per-arm `ArmData` struct. There is a mapping from identifiers to - * `BindingInfo` structs. These structs contain the mode/id/type of the - * binding, but they also contain an LLVM value which points at an alloca - * called `llmatch`. For by value bindings that are Copy, we also create - * an extra alloca that we copy the matched value to so that any changes - * we do to our copy is not reflected in the original and vice-versa. - * We don't do this if it's a move since the original value can't be used - * and thus allowing us to cheat in not creating an extra alloca. - * - * The `llmatch` binding always stores a pointer into the value being matched - * which points at the data for the binding. If the value being matched has - * type `T`, then, `llmatch` will point at an alloca of type `T*` (and hence - * `llmatch` has type `T**`). So, if you have a pattern like: - * - * let a: A = ...; - * let b: B = ...; - * match (a, b) { (ref c, d) => { ... } } - * - * For `c` and `d`, we would generate allocas of type `C*` and `D*` - * respectively. These are called the `llmatch`. As we match, when we come - * up against an identifier, we store the current pointer into the - * corresponding alloca. - * - * Once a pattern is completely matched, and assuming that there is no guard - * pattern, we will branch to a block that leads to the body itself. For any - * by-value bindings, this block will first load the ptr from `llmatch` (the - * one of type `D*`) and then load a second time to get the actual value (the - * one of type `D`). For by ref bindings, the value of the local variable is - * simply the first alloca. - * - * So, for the example above, we would generate a setup kind of like this: - * - * +-------+ - * | Entry | - * +-------+ - * | - * +--------------------------------------------+ - * | llmatch_c = (addr of first half of tuple) | - * | llmatch_d = (addr of second half of tuple) | - * +--------------------------------------------+ - * | - * +--------------------------------------+ - * | *llbinding_d = **llmatch_d | - * +--------------------------------------+ - * - * If there is a guard, the situation is slightly different, because we must - * execute the guard code. Moreover, we need to do so once for each of the - * alternatives that lead to the arm, because if the guard fails, they may - * have different points from which to continue the search. Therefore, in that - * case, we generate code that looks more like: - * - * +-------+ - * | Entry | - * +-------+ - * | - * +-------------------------------------------+ - * | llmatch_c = (addr of first half of tuple) | - * | llmatch_d = (addr of first half of tuple) | - * +-------------------------------------------+ - * | - * +-------------------------------------------------+ - * | *llbinding_d = **llmatch_d | - * | check condition | - * | if false { goto next case } | - * | if true { goto body } | - * +-------------------------------------------------+ - * - * The handling for the cleanups is a bit... sensitive. Basically, the body - * is the one that invokes `add_clean()` for each binding. During the guard - * evaluation, we add temporary cleanups and revoke them after the guard is - * evaluated (it could fail, after all). Note that guards and moves are - * just plain incompatible. - * - * Some relevant helper functions that manage bindings: - * - `create_bindings_map()` - * - `insert_lllocals()` - * - * - * ## Notes on vector pattern matching. - * - * Vector pattern matching is surprisingly tricky. The problem is that - * the structure of the vector isn't fully known, and slice matches - * can be done on subparts of it. - * - * The way that vector pattern matches are dealt with, then, is as - * follows. First, we make the actual condition associated with a - * vector pattern simply a vector length comparison. So the pattern - * [1, .. x] gets the condition "vec len >= 1", and the pattern - * [.. x] gets the condition "vec len >= 0". The problem here is that - * having the condition "vec len >= 1" hold clearly does not mean that - * only a pattern that has exactly that condition will match. This - * means that it may well be the case that a condition holds, but none - * of the patterns matching that condition match; to deal with this, - * when doing vector length matches, we have match failures proceed to - * the next condition to check. - * - * There are a couple more subtleties to deal with. While the "actual" - * condition associated with vector length tests is simply a test on - * the vector length, the actual vec_len Opt entry contains more - * information used to restrict which matches are associated with it. - * So that all matches in a submatch are matching against the same - * values from inside the vector, they are split up by how many - * elements they match at the front and at the back of the vector. In - * order to make sure that arms are properly checked in order, even - * with the overmatching conditions, each vec_len Opt entry is - * associated with a range of matches. - * Consider the following: - * - * match &[1, 2, 3] { - * [1, 1, .. _] => 0, - * [1, 2, 2, .. _] => 1, - * [1, 2, 3, .. _] => 2, - * [1, 2, .. _] => 3, - * _ => 4 - * } - * The proper arm to match is arm 2, but arms 0 and 3 both have the - * condition "len >= 2". If arm 3 was lumped in with arm 0, then the - * wrong branch would be taken. Instead, vec_len Opts are associated - * with a contiguous range of matches that have the same "shape". - * This is sort of ugly and requires a bunch of special handling of - * vec_len options. - * - */ +//! # Compilation of match statements +//! +//! I will endeavor to explain the code as best I can. I have only a loose +//! understanding of some parts of it. +//! +//! ## Matching +//! +//! The basic state of the code is maintained in an array `m` of `Match` +//! objects. Each `Match` describes some list of patterns, all of which must +//! match against the current list of values. If those patterns match, then +//! the arm listed in the match is the correct arm. A given arm may have +//! multiple corresponding match entries, one for each alternative that +//! remains. As we proceed these sets of matches are adjusted by the various +//! `enter_XXX()` functions, each of which adjusts the set of options given +//! some information about the value which has been matched. +//! +//! So, initially, there is one value and N matches, each of which have one +//! constituent pattern. N here is usually the number of arms but may be +//! greater, if some arms have multiple alternatives. For example, here: +//! +//! enum Foo { A, B(int), C(uint, uint) } +//! match foo { +//! A => ..., +//! B(x) => ..., +//! C(1u, 2) => ..., +//! C(_) => ... +//! } +//! +//! The value would be `foo`. There would be four matches, each of which +//! contains one pattern (and, in one case, a guard). We could collect the +//! various options and then compile the code for the case where `foo` is an +//! `A`, a `B`, and a `C`. When we generate the code for `C`, we would (1) +//! drop the two matches that do not match a `C` and (2) expand the other two +//! into two patterns each. In the first case, the two patterns would be `1u` +//! and `2`, and the in the second case the _ pattern would be expanded into +//! `_` and `_`. The two values are of course the arguments to `C`. +//! +//! Here is a quick guide to the various functions: +//! +//! - `compile_submatch()`: The main workhouse. It takes a list of values and +//! a list of matches and finds the various possibilities that could occur. +//! +//! - `enter_XXX()`: modifies the list of matches based on some information +//! about the value that has been matched. For example, +//! `enter_rec_or_struct()` adjusts the values given that a record or struct +//! has been matched. This is an infallible pattern, so *all* of the matches +//! must be either wildcards or record/struct patterns. `enter_opt()` +//! handles the fallible cases, and it is correspondingly more complex. +//! +//! ## Bindings +//! +//! We store information about the bound variables for each arm as part of the +//! per-arm `ArmData` struct. There is a mapping from identifiers to +//! `BindingInfo` structs. These structs contain the mode/id/type of the +//! binding, but they also contain an LLVM value which points at an alloca +//! called `llmatch`. For by value bindings that are Copy, we also create +//! an extra alloca that we copy the matched value to so that any changes +//! we do to our copy is not reflected in the original and vice-versa. +//! We don't do this if it's a move since the original value can't be used +//! and thus allowing us to cheat in not creating an extra alloca. +//! +//! The `llmatch` binding always stores a pointer into the value being matched +//! which points at the data for the binding. If the value being matched has +//! type `T`, then, `llmatch` will point at an alloca of type `T*` (and hence +//! `llmatch` has type `T**`). So, if you have a pattern like: +//! +//! let a: A = ...; +//! let b: B = ...; +//! match (a, b) { (ref c, d) => { ... } } +//! +//! For `c` and `d`, we would generate allocas of type `C*` and `D*` +//! respectively. These are called the `llmatch`. As we match, when we come +//! up against an identifier, we store the current pointer into the +//! corresponding alloca. +//! +//! Once a pattern is completely matched, and assuming that there is no guard +//! pattern, we will branch to a block that leads to the body itself. For any +//! by-value bindings, this block will first load the ptr from `llmatch` (the +//! one of type `D*`) and then load a second time to get the actual value (the +//! one of type `D`). For by ref bindings, the value of the local variable is +//! simply the first alloca. +//! +//! So, for the example above, we would generate a setup kind of like this: +//! +//! +-------+ +//! | Entry | +//! +-------+ +//! | +//! +--------------------------------------------+ +//! | llmatch_c = (addr of first half of tuple) | +//! | llmatch_d = (addr of second half of tuple) | +//! +--------------------------------------------+ +//! | +//! +--------------------------------------+ +//! | *llbinding_d = **llmatch_d | +//! +--------------------------------------+ +//! +//! If there is a guard, the situation is slightly different, because we must +//! execute the guard code. Moreover, we need to do so once for each of the +//! alternatives that lead to the arm, because if the guard fails, they may +//! have different points from which to continue the search. Therefore, in that +//! case, we generate code that looks more like: +//! +//! +-------+ +//! | Entry | +//! +-------+ +//! | +//! +-------------------------------------------+ +//! | llmatch_c = (addr of first half of tuple) | +//! | llmatch_d = (addr of first half of tuple) | +//! +-------------------------------------------+ +//! | +//! +-------------------------------------------------+ +//! | *llbinding_d = **llmatch_d | +//! | check condition | +//! | if false { goto next case } | +//! | if true { goto body } | +//! +-------------------------------------------------+ +//! +//! The handling for the cleanups is a bit... sensitive. Basically, the body +//! is the one that invokes `add_clean()` for each binding. During the guard +//! evaluation, we add temporary cleanups and revoke them after the guard is +//! evaluated (it could fail, after all). Note that guards and moves are +//! just plain incompatible. +//! +//! Some relevant helper functions that manage bindings: +//! - `create_bindings_map()` +//! - `insert_lllocals()` +//! +//! +//! ## Notes on vector pattern matching. +//! +//! Vector pattern matching is surprisingly tricky. The problem is that +//! the structure of the vector isn't fully known, and slice matches +//! can be done on subparts of it. +//! +//! The way that vector pattern matches are dealt with, then, is as +//! follows. First, we make the actual condition associated with a +//! vector pattern simply a vector length comparison. So the pattern +//! [1, .. x] gets the condition "vec len >= 1", and the pattern +//! [.. x] gets the condition "vec len >= 0". The problem here is that +//! having the condition "vec len >= 1" hold clearly does not mean that +//! only a pattern that has exactly that condition will match. This +//! means that it may well be the case that a condition holds, but none +//! of the patterns matching that condition match; to deal with this, +//! when doing vector length matches, we have match failures proceed to +//! the next condition to check. +//! +//! There are a couple more subtleties to deal with. While the "actual" +//! condition associated with vector length tests is simply a test on +//! the vector length, the actual vec_len Opt entry contains more +//! information used to restrict which matches are associated with it. +//! So that all matches in a submatch are matching against the same +//! values from inside the vector, they are split up by how many +//! elements they match at the front and at the back of the vector. In +//! order to make sure that arms are properly checked in order, even +//! with the overmatching conditions, each vec_len Opt entry is +//! associated with a range of matches. +//! Consider the following: +//! +//! match &[1, 2, 3] { +//! [1, 1, .. _] => 0, +//! [1, 2, 2, .. _] => 1, +//! [1, 2, 3, .. _] => 2, +//! [1, 2, .. _] => 3, +//! _ => 4 +//! } +//! The proper arm to match is arm 2, but arms 0 and 3 both have the +//! condition "len >= 2". If arm 3 was lumped in with arm 0, then the +//! wrong branch would be taken. Instead, vec_len Opts are associated +//! with a contiguous range of matches that have the same "shape". +//! This is sort of ugly and requires a bunch of special handling of +//! vec_len options. pub use self::BranchKind::*; pub use self::OptResult::*; @@ -620,12 +616,9 @@ fn extract_variant_args<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ExtractedBlock { vals: args, bcx: bcx } } +/// Helper for converting from the ValueRef that we pass around in the match code, which is always +/// an lvalue, into a Datum. Eventually we should just pass around a Datum and be done with it. fn match_datum<'tcx>(val: ValueRef, left_ty: Ty<'tcx>) -> Datum<'tcx, Lvalue> { - /*! - * Helper for converting from the ValueRef that we pass around in - * the match code, which is always an lvalue, into a Datum. Eventually - * we should just pass around a Datum and be done with it. - */ Datum::new(val, left_ty, Lvalue) } @@ -831,15 +824,11 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, } } +/// For each binding in `data.bindings_map`, adds an appropriate entry into the `fcx.lllocals` map fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, bindings_map: &BindingsMap<'tcx>, cs: Option) -> Block<'blk, 'tcx> { - /*! - * For each binding in `data.bindings_map`, adds an appropriate entry into - * the `fcx.lllocals` map - */ - for (&ident, &binding_info) in bindings_map.iter() { let llval = match binding_info.trmode { // By value mut binding for a copy type: load from the ptr @@ -1416,13 +1405,11 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, return bcx; } +/// Generates code for a local variable declaration like `let ;` or `let = +/// `. pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, local: &ast::Local) -> Block<'blk, 'tcx> { - /*! - * Generates code for a local variable declaration like - * `let ;` or `let = `. - */ let _icx = push_ctxt("match::store_local"); let mut bcx = bcx; let tcx = bcx.tcx(); @@ -1482,24 +1469,21 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } +/// Generates code for argument patterns like `fn foo(: T)`. +/// Creates entries in the `lllocals` map for each of the bindings +/// in `pat`. +/// +/// # Arguments +/// +/// - `pat` is the argument pattern +/// - `llval` is a pointer to the argument value (in other words, +/// if the argument type is `T`, then `llval` is a `T*`). In some +/// cases, this code may zero out the memory `llval` points at. pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, pat: &ast::Pat, arg: Datum<'tcx, Rvalue>, arg_scope: cleanup::ScopeId) -> Block<'blk, 'tcx> { - /*! - * Generates code for argument patterns like `fn foo(: T)`. - * Creates entries in the `lllocals` map for each of the bindings - * in `pat`. - * - * # Arguments - * - * - `pat` is the argument pattern - * - `llval` is a pointer to the argument value (in other words, - * if the argument type is `T`, then `llval` is a `T*`). In some - * cases, this code may zero out the memory `llval` points at. - */ - let _icx = push_ctxt("match::store_arg"); match simple_identifier(&*pat) { @@ -1583,26 +1567,23 @@ fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, bcx } +/// A simple version of the pattern matching code that only handles +/// irrefutable patterns. This is used in let/argument patterns, +/// not in match statements. Unifying this code with the code above +/// sounds nice, but in practice it produces very inefficient code, +/// since the match code is so much more general. In most cases, +/// LLVM is able to optimize the code, but it causes longer compile +/// times and makes the generated code nigh impossible to read. +/// +/// # Arguments +/// - bcx: starting basic block context +/// - pat: the irrefutable pattern being matched. +/// - val: the value being matched -- must be an lvalue (by ref, with cleanup) fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, val: ValueRef, cleanup_scope: cleanup::ScopeId) -> Block<'blk, 'tcx> { - /*! - * A simple version of the pattern matching code that only handles - * irrefutable patterns. This is used in let/argument patterns, - * not in match statements. Unifying this code with the code above - * sounds nice, but in practice it produces very inefficient code, - * since the match code is so much more general. In most cases, - * LLVM is able to optimize the code, but it causes longer compile - * times and makes the generated code nigh impossible to read. - * - * # Arguments - * - bcx: starting basic block context - * - pat: the irrefutable pattern being matched. - * - val: the value being matched -- must be an lvalue (by ref, with cleanup) - */ - debug!("bind_irrefutable_pat(bcx={}, pat={})", bcx.to_str(), pat.repr(bcx.tcx())); diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index e7d1b9726a1..568805bee40 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -8,40 +8,38 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * # Representation of Algebraic Data Types - * - * This module determines how to represent enums, structs, and tuples - * based on their monomorphized types; it is responsible both for - * choosing a representation and translating basic operations on - * values of those types. (Note: exporting the representations for - * debuggers is handled in debuginfo.rs, not here.) - * - * Note that the interface treats everything as a general case of an - * enum, so structs/tuples/etc. have one pseudo-variant with - * discriminant 0; i.e., as if they were a univariant enum. - * - * Having everything in one place will enable improvements to data - * structure representation; possibilities include: - * - * - User-specified alignment (e.g., cacheline-aligning parts of - * concurrently accessed data structures); LLVM can't represent this - * directly, so we'd have to insert padding fields in any structure - * that might contain one and adjust GEP indices accordingly. See - * issue #4578. - * - * - Store nested enums' discriminants in the same word. Rather, if - * some variants start with enums, and those enums representations - * have unused alignment padding between discriminant and body, the - * outer enum's discriminant can be stored there and those variants - * can start at offset 0. Kind of fancy, and might need work to - * make copies of the inner enum type cooperate, but it could help - * with `Option` or `Result` wrapped around another enum. - * - * - Tagged pointers would be neat, but given that any type can be - * used unboxed and any field can have pointers (including mutable) - * taken to it, implementing them for Rust seems difficult. - */ +//! # Representation of Algebraic Data Types +//! +//! This module determines how to represent enums, structs, and tuples +//! based on their monomorphized types; it is responsible both for +//! choosing a representation and translating basic operations on +//! values of those types. (Note: exporting the representations for +//! debuggers is handled in debuginfo.rs, not here.) +//! +//! Note that the interface treats everything as a general case of an +//! enum, so structs/tuples/etc. have one pseudo-variant with +//! discriminant 0; i.e., as if they were a univariant enum. +//! +//! Having everything in one place will enable improvements to data +//! structure representation; possibilities include: +//! +//! - User-specified alignment (e.g., cacheline-aligning parts of +//! concurrently accessed data structures); LLVM can't represent this +//! directly, so we'd have to insert padding fields in any structure +//! that might contain one and adjust GEP indices accordingly. See +//! issue #4578. +//! +//! - Store nested enums' discriminants in the same word. Rather, if +//! some variants start with enums, and those enums representations +//! have unused alignment padding between discriminant and body, the +//! outer enum's discriminant can be stored there and those variants +//! can start at offset 0. Kind of fancy, and might need work to +//! make copies of the inner enum type cooperate, but it could help +//! with `Option` or `Result` wrapped around another enum. +//! +//! - Tagged pointers would be neat, but given that any type can be +//! used unboxed and any field can have pointers (including mutable) +//! taken to it, implementing them for Rust seems difficult. #![allow(unsigned_negation)] diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index 9b499b6d1a1..024df2a63ad 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -# Translation of inline assembly. -*/ +//! # Translation of inline assembly. use llvm; use trans::build::*; diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 6fe5298393e..52e54a4a261 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -1050,14 +1050,11 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, return v; } +/// Helper for loading values from memory. Does the necessary conversion if the in-memory type +/// differs from the type used for SSA values. Also handles various special cases where the type +/// gives us better information about what we are loading. pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) -> ValueRef { - /*! - * Helper for loading values from memory. Does the necessary conversion if - * the in-memory type differs from the type used for SSA values. Also - * handles various special cases where the type gives us better information - * about what we are loading. - */ if type_is_zero_size(cx.ccx(), t) { C_undef(type_of::type_of(cx.ccx(), t)) } else if ty::type_is_bool(t) { @@ -1071,11 +1068,9 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, } } +/// Helper for storing values in memory. Does the necessary conversion if the in-memory type +/// differs from the type used for SSA values. pub fn store_ty(cx: Block, v: ValueRef, dst: ValueRef, t: Ty) { - /*! - * Helper for storing values in memory. Does the necessary conversion if - * the in-memory type differs from the type used for SSA values. - */ if ty::type_is_bool(t) { Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst); } else { diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 6d0f5980442..5d713526a3d 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Handles translation of callees as well as other call-related - * things. Callees are a superset of normal rust values and sometimes - * have different representations. In particular, top-level fn items - * and methods are represented as just a fn ptr and not a full - * closure. - */ +//! Handles translation of callees as well as other call-related +//! things. Callees are a superset of normal rust values and sometimes +//! have different representations. In particular, top-level fn items +//! and methods are represented as just a fn ptr and not a full +//! closure. pub use self::AutorefArg::*; pub use self::CalleeData::*; @@ -220,13 +218,9 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } } +/// Translates a reference (with id `ref_id`) to the fn/method with id `def_id` into a function +/// pointer. This may require monomorphization or inlining. pub fn trans_fn_ref(bcx: Block, def_id: ast::DefId, node: ExprOrMethodCall) -> ValueRef { - /*! - * Translates a reference (with id `ref_id`) to the fn/method - * with id `def_id` into a function pointer. This may require - * monomorphization or inlining. - */ - let _icx = push_ctxt("trans_fn_ref"); let substs = node_id_substs(bcx, node); @@ -398,6 +392,17 @@ pub fn trans_unboxing_shim<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llfn } +/// Translates a reference to a fn/method item, monomorphizing and +/// inlining as it goes. +/// +/// # Parameters +/// +/// - `bcx`: the current block where the reference to the fn occurs +/// - `def_id`: def id of the fn or method item being referenced +/// - `node`: node id of the reference to the fn/method, if applicable. +/// This parameter may be zero; but, if so, the resulting value may not +/// have the right type, so it must be cast before being used. +/// - `substs`: values for each of the fn/method's parameters pub fn trans_fn_ref_with_substs<'blk, 'tcx>( bcx: Block<'blk, 'tcx>, // def_id: ast::DefId, // def id of fn @@ -405,20 +410,6 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>( substs: subst::Substs<'tcx>) // vtables for the call -> ValueRef { - /*! - * Translates a reference to a fn/method item, monomorphizing and - * inlining as it goes. - * - * # Parameters - * - * - `bcx`: the current block where the reference to the fn occurs - * - `def_id`: def id of the fn or method item being referenced - * - `node`: node id of the reference to the fn/method, if applicable. - * This parameter may be zero; but, if so, the resulting value may not - * have the right type, so it must be cast before being used. - * - `substs`: values for each of the fn/method's parameters - */ - let _icx = push_ctxt("trans_fn_ref_with_substs"); let ccx = bcx.ccx(); let tcx = bcx.tcx(); @@ -668,6 +659,16 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dest) } +/// This behemoth of a function translates function calls. Unfortunately, in order to generate more +/// efficient LLVM output at -O0, it has quite a complex signature (refactoring this into two +/// functions seems like a good idea). +/// +/// In particular, for lang items, it is invoked with a dest of None, and in that case the return +/// value contains the result of the fn. The lang item must not return a structural type or else +/// all heck breaks loose. +/// +/// For non-lang items, `dest` is always Some, and hence the result is written into memory +/// somewhere. Nonetheless we return the actual return value of the function. pub fn trans_call_inner<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, call_info: Option, callee_ty: Ty<'tcx>, @@ -677,22 +678,6 @@ pub fn trans_call_inner<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, args: CallArgs<'a, 'tcx>, dest: Option) -> Result<'blk, 'tcx> { - /*! - * This behemoth of a function translates function calls. - * Unfortunately, in order to generate more efficient LLVM - * output at -O0, it has quite a complex signature (refactoring - * this into two functions seems like a good idea). - * - * In particular, for lang items, it is invoked with a dest of - * None, and in that case the return value contains the result of - * the fn. The lang item must not return a structural type or else - * all heck breaks loose. - * - * For non-lang items, `dest` is always Some, and hence the result - * is written into memory somewhere. Nonetheless we return the - * actual return value of the function. - */ - // Introduce a temporary cleanup scope that will contain cleanups // for the arguments while they are being evaluated. The purpose // this cleanup is to ensure that, should a panic occur while diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index b0235be7497..d7da83ddb0d 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Code pertaining to cleanup of temporaries as well as execution of - * drop glue. See discussion in `doc.rs` for a high-level summary. - */ +//! Code pertaining to cleanup of temporaries as well as execution of +//! drop glue. See discussion in `doc.rs` for a high-level summary. pub use self::ScopeId::*; pub use self::CleanupScopeKind::*; @@ -114,12 +112,8 @@ pub enum ScopeId { } impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { + /// Invoked when we start to trans the code contained within a new cleanup scope. fn push_ast_cleanup_scope(&self, debug_loc: NodeInfo) { - /*! - * Invoked when we start to trans the code contained - * within a new cleanup scope. - */ - debug!("push_ast_cleanup_scope({})", self.ccx.tcx().map.node_to_string(debug_loc.id)); @@ -189,16 +183,12 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { CustomScopeIndex { index: index } } + /// Removes the cleanup scope for id `cleanup_scope`, which must be at the top of the cleanup + /// stack, and generates the code to do its cleanups for normal exit. fn pop_and_trans_ast_cleanup_scope(&self, bcx: Block<'blk, 'tcx>, cleanup_scope: ast::NodeId) -> Block<'blk, 'tcx> { - /*! - * Removes the cleanup scope for id `cleanup_scope`, which - * must be at the top of the cleanup stack, and generates the - * code to do its cleanups for normal exit. - */ - debug!("pop_and_trans_ast_cleanup_scope({})", self.ccx.tcx().map.node_to_string(cleanup_scope)); @@ -208,15 +198,11 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.trans_scope_cleanups(bcx, &scope) } + /// Removes the loop cleanup scope for id `cleanup_scope`, which must be at the top of the + /// cleanup stack. Does not generate any cleanup code, since loop scopes should exit by + /// branching to a block generated by `normal_exit_block`. fn pop_loop_cleanup_scope(&self, cleanup_scope: ast::NodeId) { - /*! - * Removes the loop cleanup scope for id `cleanup_scope`, which - * must be at the top of the cleanup stack. Does not generate - * any cleanup code, since loop scopes should exit by - * branching to a block generated by `normal_exit_block`. - */ - debug!("pop_loop_cleanup_scope({})", self.ccx.tcx().map.node_to_string(cleanup_scope)); @@ -225,29 +211,21 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { let _ = self.pop_scope(); } + /// Removes the top cleanup scope from the stack without executing its cleanups. The top + /// cleanup scope must be the temporary scope `custom_scope`. fn pop_custom_cleanup_scope(&self, custom_scope: CustomScopeIndex) { - /*! - * Removes the top cleanup scope from the stack without - * executing its cleanups. The top cleanup scope must - * be the temporary scope `custom_scope`. - */ - debug!("pop_custom_cleanup_scope({})", custom_scope.index); assert!(self.is_valid_to_pop_custom_scope(custom_scope)); let _ = self.pop_scope(); } + /// Removes the top cleanup scope from the stack, which must be a temporary scope, and + /// generates the code to do its cleanups for normal exit. fn pop_and_trans_custom_cleanup_scope(&self, bcx: Block<'blk, 'tcx>, custom_scope: CustomScopeIndex) -> Block<'blk, 'tcx> { - /*! - * Removes the top cleanup scope from the stack, which must be - * a temporary scope, and generates the code to do its - * cleanups for normal exit. - */ - debug!("pop_and_trans_custom_cleanup_scope({})", custom_scope); assert!(self.is_valid_to_pop_custom_scope(custom_scope)); @@ -255,11 +233,8 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.trans_scope_cleanups(bcx, &scope) } + /// Returns the id of the top-most loop scope fn top_loop_scope(&self) -> ast::NodeId { - /*! - * Returns the id of the top-most loop scope - */ - for scope in self.scopes.borrow().iter().rev() { match scope.kind { LoopScopeKind(id, _) => { @@ -271,24 +246,17 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.ccx.sess().bug("no loop scope found"); } + /// Returns a block to branch to which will perform all pending cleanups and then + /// break/continue (depending on `exit`) out of the loop with id `cleanup_scope` fn normal_exit_block(&'blk self, cleanup_scope: ast::NodeId, exit: uint) -> BasicBlockRef { - /*! - * Returns a block to branch to which will perform all pending - * cleanups and then break/continue (depending on `exit`) out - * of the loop with id `cleanup_scope` - */ - self.trans_cleanups_to_exit_scope(LoopExit(cleanup_scope, exit)) } + /// Returns a block to branch to which will perform all pending cleanups and then return from + /// this function fn return_exit_block(&'blk self) -> BasicBlockRef { - /*! - * Returns a block to branch to which will perform all pending - * cleanups and then return from this function - */ - self.trans_cleanups_to_exit_scope(ReturnExit) } @@ -306,15 +274,11 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.schedule_clean(cleanup_scope, drop as CleanupObj); } + /// Schedules a (deep) drop of `val`, which is a pointer to an instance of `ty` fn schedule_drop_mem(&self, cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - /*! - * Schedules a (deep) drop of `val`, which is a pointer to an - * instance of `ty` - */ - if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { is_immediate: false, @@ -332,15 +296,11 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.schedule_clean(cleanup_scope, drop as CleanupObj); } + /// Schedules a (deep) drop and zero-ing of `val`, which is a pointer to an instance of `ty` fn schedule_drop_and_zero_mem(&self, cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - /*! - * Schedules a (deep) drop and zero-ing of `val`, which is a pointer - * to an instance of `ty` - */ - if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { is_immediate: false, @@ -359,13 +319,11 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.schedule_clean(cleanup_scope, drop as CleanupObj); } + /// Schedules a (deep) drop of `val`, which is an instance of `ty` fn schedule_drop_immediate(&self, cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - /*! - * Schedules a (deep) drop of `val`, which is an instance of `ty` - */ if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; } let drop = box DropValue { @@ -384,16 +342,12 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.schedule_clean(cleanup_scope, drop as CleanupObj); } + /// Schedules a call to `free(val)`. Note that this is a shallow operation. fn schedule_free_value(&self, cleanup_scope: ScopeId, val: ValueRef, heap: Heap, content_ty: Ty<'tcx>) { - /*! - * Schedules a call to `free(val)`. Note that this is a shallow - * operation. - */ - let drop = box FreeValue { ptr: val, heap: heap, content_ty: content_ty }; debug!("schedule_free_value({}, val={}, heap={})", @@ -404,17 +358,13 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.schedule_clean(cleanup_scope, drop as CleanupObj); } + /// Schedules a call to `free(val)`. Note that this is a shallow operation. fn schedule_free_slice(&self, cleanup_scope: ScopeId, val: ValueRef, size: ValueRef, align: ValueRef, heap: Heap) { - /*! - * Schedules a call to `free(val)`. Note that this is a shallow - * operation. - */ - let drop = box FreeSlice { ptr: val, size: size, align: align, heap: heap }; debug!("schedule_free_slice({}, val={}, heap={})", @@ -434,15 +384,12 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { } } + /// Schedules a cleanup to occur upon exit from `cleanup_scope`. If `cleanup_scope` is not + /// provided, then the cleanup is scheduled in the topmost scope, which must be a temporary + /// scope. fn schedule_clean_in_ast_scope(&self, cleanup_scope: ast::NodeId, cleanup: CleanupObj<'tcx>) { - /*! - * Schedules a cleanup to occur upon exit from `cleanup_scope`. - * If `cleanup_scope` is not provided, then the cleanup is scheduled - * in the topmost scope, which must be a temporary scope. - */ - debug!("schedule_clean_in_ast_scope(cleanup_scope={})", cleanup_scope); @@ -462,14 +409,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.ccx.tcx().map.node_to_string(cleanup_scope)).as_slice()); } + /// Schedules a cleanup to occur in the top-most scope, which must be a temporary scope. fn schedule_clean_in_custom_scope(&self, custom_scope: CustomScopeIndex, cleanup: CleanupObj<'tcx>) { - /*! - * Schedules a cleanup to occur in the top-most scope, - * which must be a temporary scope. - */ - debug!("schedule_clean_in_custom_scope(custom_scope={})", custom_scope.index); @@ -481,22 +424,14 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { scope.clear_cached_exits(); } + /// Returns true if there are pending cleanups that should execute on panic. fn needs_invoke(&self) -> bool { - /*! - * Returns true if there are pending cleanups that should - * execute on panic. - */ - self.scopes.borrow().iter().rev().any(|s| s.needs_invoke()) } + /// Returns a basic block to branch to in the event of a panic. This block will run the panic + /// cleanups and eventually invoke the LLVM `Resume` instruction. fn get_landing_pad(&'blk self) -> BasicBlockRef { - /*! - * Returns a basic block to branch to in the event of a panic. - * This block will run the panic cleanups and eventually - * invoke the LLVM `Resume` instruction. - */ - let _icx = base::push_ctxt("get_landing_pad"); debug!("get_landing_pad"); @@ -529,10 +464,8 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { } impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { + /// Returns the id of the current top-most AST scope, if any. fn top_ast_scope(&self) -> Option { - /*! - * Returns the id of the current top-most AST scope, if any. - */ for scope in self.scopes.borrow().iter().rev() { match scope.kind { CustomScopeKind | LoopScopeKind(..) => {} @@ -559,10 +492,10 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx (*scopes)[custom_scope.index].kind.is_temp() } + /// Generates the cleanups for `scope` into `bcx` fn trans_scope_cleanups(&self, // cannot borrow self, will recurse bcx: Block<'blk, 'tcx>, scope: &CleanupScope<'blk, 'tcx>) -> Block<'blk, 'tcx> { - /*! Generates the cleanups for `scope` into `bcx` */ let mut bcx = bcx; if !bcx.unreachable.get() { @@ -593,37 +526,31 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx f(self.scopes.borrow().last().unwrap()) } + /// Used when the caller wishes to jump to an early exit, such as a return, break, continue, or + /// unwind. This function will generate all cleanups between the top of the stack and the exit + /// `label` and return a basic block that the caller can branch to. + /// + /// For example, if the current stack of cleanups were as follows: + /// + /// AST 22 + /// Custom 1 + /// AST 23 + /// Loop 23 + /// Custom 2 + /// AST 24 + /// + /// and the `label` specifies a break from `Loop 23`, then this function would generate a + /// series of basic blocks as follows: + /// + /// Cleanup(AST 24) -> Cleanup(Custom 2) -> break_blk + /// + /// where `break_blk` is the block specified in `Loop 23` as the target for breaks. The return + /// value would be the first basic block in that sequence (`Cleanup(AST 24)`). The caller could + /// then branch to `Cleanup(AST 24)` and it will perform all cleanups and finally branch to the + /// `break_blk`. fn trans_cleanups_to_exit_scope(&'blk self, label: EarlyExitLabel) -> BasicBlockRef { - /*! - * Used when the caller wishes to jump to an early exit, such - * as a return, break, continue, or unwind. This function will - * generate all cleanups between the top of the stack and the - * exit `label` and return a basic block that the caller can - * branch to. - * - * For example, if the current stack of cleanups were as follows: - * - * AST 22 - * Custom 1 - * AST 23 - * Loop 23 - * Custom 2 - * AST 24 - * - * and the `label` specifies a break from `Loop 23`, then this - * function would generate a series of basic blocks as follows: - * - * Cleanup(AST 24) -> Cleanup(Custom 2) -> break_blk - * - * where `break_blk` is the block specified in `Loop 23` as - * the target for breaks. The return value would be the first - * basic block in that sequence (`Cleanup(AST 24)`). The - * caller could then branch to `Cleanup(AST 24)` and it will - * perform all cleanups and finally branch to the `break_blk`. - */ - debug!("trans_cleanups_to_exit_scope label={} scopes={}", label, self.scopes_len()); @@ -756,20 +683,15 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx prev_llbb } + /// Creates a landing pad for the top scope, if one does not exist. The landing pad will + /// perform all cleanups necessary for an unwind and then `resume` to continue error + /// propagation: + /// + /// landing_pad -> ... cleanups ... -> [resume] + /// + /// (The cleanups and resume instruction are created by `trans_cleanups_to_exit_scope()`, not + /// in this function itself.) fn get_or_create_landing_pad(&'blk self) -> BasicBlockRef { - /*! - * Creates a landing pad for the top scope, if one does not - * exist. The landing pad will perform all cleanups necessary - * for an unwind and then `resume` to continue error - * propagation: - * - * landing_pad -> ... cleanups ... -> [resume] - * - * (The cleanups and resume instruction are created by - * `trans_cleanups_to_exit_scope()`, not in this function - * itself.) - */ - let pad_bcx; debug!("get_or_create_landing_pad"); @@ -883,19 +805,15 @@ impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> { cleanup_block: blk }); } + /// True if this scope has cleanups that need unwinding fn needs_invoke(&self) -> bool { - /*! True if this scope has cleanups that need unwinding */ self.cached_landing_pad.is_some() || self.cleanups.iter().any(|c| c.must_unwind()) } + /// Returns a suitable name to use for the basic block that handles this cleanup scope fn block_name(&self, prefix: &str) -> String { - /*! - * Returns a suitable name to use for the basic block that - * handles this cleanup scope - */ - match self.kind { CustomScopeKind => format!("{}_custom_", prefix), AstScopeKind(id) => format!("{}_ast_{}_", prefix, id), @@ -930,14 +848,10 @@ impl<'blk, 'tcx> CleanupScopeKind<'blk, 'tcx> { } } + /// If this is a loop scope with id `id`, return the early exit block `exit`, else `None` fn early_exit_block(&self, id: ast::NodeId, exit: uint) -> Option { - /*! - * If this is a loop scope with id `id`, return the early - * exit block `exit`, else `None` - */ - match *self { LoopScopeKind(i, ref exits) if id == i => Some(exits[exit].llbb), _ => None, diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index ca955975dfb..2f82b8286c2 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -386,6 +386,15 @@ impl<'a, 'tcx> ClosureEnv<'a, 'tcx> { } } +/// Translates the body of a closure expression. +/// +/// - `store` +/// - `decl` +/// - `body` +/// - `id`: The id of the closure expression. +/// - `cap_clause`: information about captured variables, if any. +/// - `dest`: where to write the closure value, which must be a +/// (fn ptr, env) pair pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, store: ty::TraitStore, decl: &ast::FnDecl, @@ -393,19 +402,6 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, id: ast::NodeId, dest: expr::Dest) -> Block<'blk, 'tcx> { - /*! - * - * Translates the body of a closure expression. - * - * - `store` - * - `decl` - * - `body` - * - `id`: The id of the closure expression. - * - `cap_clause`: information about captured variables, if any. - * - `dest`: where to write the closure value, which must be a - (fn ptr, env) pair - */ - let _icx = push_ctxt("closure::trans_expr_fn"); let dest_addr = match dest { diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 235805a7c83..febb33f6c54 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -95,26 +95,19 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) - } } +/// Identify types which have size zero at runtime. pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - /*! - * Identify types which have size zero at runtime. - */ - use trans::machine::llsize_of_alloc; use trans::type_of::sizing_type_of; let llty = sizing_type_of(ccx, ty); llsize_of_alloc(ccx, llty) == 0 } +/// Identifies types which we declare to be equivalent to `void` in C for the purpose of function +/// return types. These are `()`, bot, and uninhabited enums. Note that all such types are also +/// zero-size, but not all zero-size types use a `void` return type (in order to aid with C ABI +/// compatibility). pub fn return_type_is_void(ccx: &CrateContext, ty: Ty) -> bool { - /*! - * Identifies types which we declare to be equivalent to `void` - * in C for the purpose of function return types. These are - * `()`, bot, and uninhabited enums. Note that all such types - * are also zero-size, but not all zero-size types use a `void` - * return type (in order to aid with C ABI compatibility). - */ - ty::type_is_nil(ty) || ty::type_is_empty(ccx.tcx(), ty) } @@ -768,19 +761,14 @@ pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ex: &ast::Expr) -> T monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex)) } +/// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we +/// do not (necessarily) resolve all nested obligations on the impl. Note that type check should +/// guarantee to us that all nested obligations *could be* resolved if we wanted to. pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, span: Span, trait_ref: Rc>) -> traits::Vtable<'tcx, ()> { - /*! - * Attempts to resolve an obligation. The result is a shallow - * vtable resolution -- meaning that we do not (necessarily) resolve - * all nested obligations on the impl. Note that type check should - * guarantee to us that all nested obligations *could be* resolved - * if we wanted to. - */ - let tcx = ccx.tcx(); // Remove any references to regions; this helps improve caching. diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 354a6072207..22f030be3d6 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * See the section on datums in `doc.rs` for an overview of what - * Datums are and how they are intended to be used. - */ +//! See the section on datums in `doc.rs` for an overview of what Datums are and how they are +//! intended to be used. pub use self::Expr::*; pub use self::RvalueMode::*; @@ -107,6 +105,10 @@ pub fn immediate_rvalue_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } +/// Allocates temporary space on the stack using alloca() and returns a by-ref Datum pointing to +/// it. The memory will be dropped upon exit from `scope`. The callback `populate` should +/// initialize the memory. If `zero` is true, the space will be zeroed when it is allocated; this +/// is not necessary unless `bcx` does not dominate the end of `scope`. pub fn lvalue_scratch_datum<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>, name: &str, @@ -116,15 +118,6 @@ pub fn lvalue_scratch_datum<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, populate: |A, Block<'blk, 'tcx>, ValueRef| -> Block<'blk, 'tcx>) -> DatumBlock<'blk, 'tcx, Lvalue> { - /*! - * Allocates temporary space on the stack using alloca() and - * returns a by-ref Datum pointing to it. The memory will be - * dropped upon exit from `scope`. The callback `populate` should - * initialize the memory. If `zero` is true, the space will be - * zeroed when it is allocated; this is not necessary unless `bcx` - * does not dominate the end of `scope`. - */ - let scratch = if zero { alloca_zeroed(bcx, ty, name) } else { @@ -140,33 +133,24 @@ pub fn lvalue_scratch_datum<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, Datum::new(scratch, ty, Lvalue)) } +/// Allocates temporary space on the stack using alloca() and returns a by-ref Datum pointing to +/// it. If `zero` is true, the space will be zeroed when it is allocated; this is normally not +/// necessary, but in the case of automatic rooting in match statements it is possible to have +/// temporaries that may not get initialized if a certain arm is not taken, so we must zero them. +/// You must arrange any cleanups etc yourself! pub fn rvalue_scratch_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>, name: &str) -> Datum<'tcx, Rvalue> { - /*! - * Allocates temporary space on the stack using alloca() and - * returns a by-ref Datum pointing to it. If `zero` is true, the - * space will be zeroed when it is allocated; this is normally not - * necessary, but in the case of automatic rooting in match - * statements it is possible to have temporaries that may not get - * initialized if a certain arm is not taken, so we must zero - * them. You must arrange any cleanups etc yourself! - */ - let llty = type_of::type_of(bcx.ccx(), ty); let scratch = alloca(bcx, llty, name); Datum::new(scratch, ty, Rvalue::new(ByRef)) } +/// Indicates the "appropriate" mode for this value, which is either by ref or by value, depending +/// on whether type is immediate or not. pub fn appropriate_rvalue_mode<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> RvalueMode { - /*! - * Indicates the "appropriate" mode for this value, - * which is either by ref or by value, depending - * on whether type is immediate or not. - */ - if type_is_immediate(ccx, ty) { ByValue } else { @@ -234,17 +218,13 @@ impl KindOps for Rvalue { } impl KindOps for Lvalue { + /// If an lvalue is moved, we must zero out the memory in which it resides so as to cancel + /// cleanup. If an @T lvalue is copied, we must increment the reference count. fn post_store<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, val: ValueRef, ty: Ty<'tcx>) -> Block<'blk, 'tcx> { - /*! - * If an lvalue is moved, we must zero out the memory in which - * it resides so as to cancel cleanup. If an @T lvalue is - * copied, we must increment the reference count. - */ - if ty::type_needs_drop(bcx.tcx(), ty) { // cancel cleanup of affine values by zeroing out let () = zero_mem(bcx, val, ty); @@ -288,31 +268,24 @@ impl KindOps for Expr { } impl<'tcx> Datum<'tcx, Rvalue> { + /// Schedules a cleanup for this datum in the given scope. That means that this datum is no + /// longer an rvalue datum; hence, this function consumes the datum and returns the contained + /// ValueRef. pub fn add_clean<'a>(self, fcx: &FunctionContext<'a, 'tcx>, scope: cleanup::ScopeId) -> ValueRef { - /*! - * Schedules a cleanup for this datum in the given scope. - * That means that this datum is no longer an rvalue datum; - * hence, this function consumes the datum and returns the - * contained ValueRef. - */ - add_rvalue_clean(self.kind.mode, fcx, scope, self.val, self.ty); self.val } + /// Returns an lvalue datum (that is, a by ref datum with cleanup scheduled). If `self` is not + /// already an lvalue, cleanup will be scheduled in the temporary scope for `expr_id`. pub fn to_lvalue_datum_in_scope<'blk>(self, bcx: Block<'blk, 'tcx>, name: &str, scope: cleanup::ScopeId) -> DatumBlock<'blk, 'tcx, Lvalue> { - /*! - * Returns an lvalue datum (that is, a by ref datum with - * cleanup scheduled). If `self` is not already an lvalue, - * cleanup will be scheduled in the temporary scope for `expr_id`. - */ let fcx = bcx.fcx; match self.kind.mode { @@ -381,22 +354,16 @@ impl<'tcx> Datum<'tcx, Expr> { } } + /// Asserts that this datum *is* an lvalue and returns it. #[allow(dead_code)] // potentially useful pub fn assert_lvalue(self, bcx: Block) -> Datum<'tcx, Lvalue> { - /*! - * Asserts that this datum *is* an lvalue and returns it. - */ - self.match_kind( |d| d, |_| bcx.sess().bug("assert_lvalue given rvalue")) } + /// Asserts that this datum *is* an lvalue and returns it. pub fn assert_rvalue(self, bcx: Block) -> Datum<'tcx, Rvalue> { - /*! - * Asserts that this datum *is* an lvalue and returns it. - */ - self.match_kind( |_| bcx.sess().bug("assert_rvalue given lvalue"), |r| r) @@ -418,14 +385,11 @@ impl<'tcx> Datum<'tcx, Expr> { } } + /// Arranges cleanup for `self` if it is an rvalue. Use when you are done working with a value + /// that may need drop. pub fn add_clean_if_rvalue<'blk>(self, bcx: Block<'blk, 'tcx>, expr_id: ast::NodeId) { - /*! - * Arranges cleanup for `self` if it is an rvalue. Use when - * you are done working with a value that may need drop. - */ - self.match_kind( |_| { /* Nothing to do, cleanup already arranged */ }, |r| { @@ -434,16 +398,12 @@ impl<'tcx> Datum<'tcx, Expr> { }) } + /// Ensures that `self` will get cleaned up, if it is not an lvalue already. pub fn clean<'blk>(self, bcx: Block<'blk, 'tcx>, name: &'static str, expr_id: ast::NodeId) -> Block<'blk, 'tcx> { - /*! - * Ensures that `self` will get cleaned up, if it is not an lvalue - * already. - */ - self.to_lvalue_datum(bcx, name, expr_id).bcx } @@ -464,15 +424,11 @@ impl<'tcx> Datum<'tcx, Expr> { }) } + /// Ensures that we have an rvalue datum (that is, a datum with no cleanup scheduled). pub fn to_rvalue_datum<'blk>(self, bcx: Block<'blk, 'tcx>, name: &'static str) -> DatumBlock<'blk, 'tcx, Rvalue> { - /*! - * Ensures that we have an rvalue datum (that is, a datum with - * no cleanup scheduled). - */ - self.match_kind( |l| { let mut bcx = bcx; @@ -501,12 +457,9 @@ impl<'tcx> Datum<'tcx, Expr> { * from an array. */ impl<'tcx> Datum<'tcx, Lvalue> { + /// Converts a datum into a by-ref value. The datum type must be one which is always passed by + /// reference. pub fn to_llref(self) -> ValueRef { - /*! - * Converts a datum into a by-ref value. The datum type must - * be one which is always passed by reference. - */ - self.val } @@ -555,40 +508,30 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { Datum { val: val, ty: ty, kind: kind.to_expr_kind() } } + /// Moves or copies this value into a new home, as appropriate depending on the type of the + /// datum. This method consumes the datum, since it would be incorrect to go on using the datum + /// if the value represented is affine (and hence the value is moved). pub fn store_to<'blk>(self, bcx: Block<'blk, 'tcx>, dst: ValueRef) -> Block<'blk, 'tcx> { - /*! - * Moves or copies this value into a new home, as appropriate - * depending on the type of the datum. This method consumes - * the datum, since it would be incorrect to go on using the - * datum if the value represented is affine (and hence the value - * is moved). - */ - self.shallow_copy_raw(bcx, dst); self.kind.post_store(bcx, self.val, self.ty) } + /// Helper function that performs a shallow copy of this value into `dst`, which should be a + /// pointer to a memory location suitable for `self.ty`. `dst` should contain uninitialized + /// memory (either newly allocated, zeroed, or dropped). + /// + /// This function is private to datums because it leaves memory in an unstable state, where the + /// source value has been copied but not zeroed. Public methods are `store_to` (if you no + /// longer need the source value) or `shallow_copy` (if you wish the source value to remain + /// valid). fn shallow_copy_raw<'blk>(&self, bcx: Block<'blk, 'tcx>, dst: ValueRef) -> Block<'blk, 'tcx> { - /*! - * Helper function that performs a shallow copy of this value - * into `dst`, which should be a pointer to a memory location - * suitable for `self.ty`. `dst` should contain uninitialized - * memory (either newly allocated, zeroed, or dropped). - * - * This function is private to datums because it leaves memory - * in an unstable state, where the source value has been - * copied but not zeroed. Public methods are `store_to` - * (if you no longer need the source value) or `shallow_copy` - * (if you wish the source value to remain valid). - */ - let _icx = push_ctxt("copy_to_no_check"); if type_is_zero_size(bcx.ccx(), self.ty) { @@ -604,17 +547,13 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { return bcx; } + /// Copies the value into a new location. This function always preserves the existing datum as + /// a valid value. Therefore, it does not consume `self` and, also, cannot be applied to affine + /// values (since they must never be duplicated). pub fn shallow_copy<'blk>(&self, bcx: Block<'blk, 'tcx>, dst: ValueRef) -> Block<'blk, 'tcx> { - /*! - * Copies the value into a new location. This function always - * preserves the existing datum as a valid value. Therefore, - * it does not consume `self` and, also, cannot be applied to - * affine values (since they must never be duplicated). - */ - assert!(!ty::type_moves_by_default(bcx.tcx(), self.ty)); self.shallow_copy_raw(bcx, dst) } @@ -627,23 +566,17 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { self.kind) } + //! See the `appropriate_rvalue_mode()` function pub fn appropriate_rvalue_mode<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> RvalueMode { - /*! See the `appropriate_rvalue_mode()` function */ - appropriate_rvalue_mode(ccx, self.ty) } + /// Converts `self` into a by-value `ValueRef`. Consumes this datum (i.e., absolves you of + /// responsibility to cleanup the value). For this to work, the value must be something + /// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is + /// naturally passed around by value, and not by reference. pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef { - /*! - * Converts `self` into a by-value `ValueRef`. Consumes this - * datum (i.e., absolves you of responsibility to cleanup the - * value). For this to work, the value must be something - * scalar-ish (like an int or a pointer) which (1) does not - * require drop glue and (2) is naturally passed around by - * value, and not by reference. - */ - assert!(!ty::type_needs_drop(bcx.tcx(), self.ty)); assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue); if self.kind.is_by_ref() { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index a3472e194cf..c35de3209c6 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -8,181 +8,180 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -# Debug Info Module - -This module serves the purpose of generating debug symbols. We use LLVM's -[source level debugging](http://llvm.org/docs/SourceLevelDebugging.html) -features for generating the debug information. The general principle is this: - -Given the right metadata in the LLVM IR, the LLVM code generator is able to -create DWARF debug symbols for the given code. The -[metadata](http://llvm.org/docs/LangRef.html#metadata-type) is structured much -like DWARF *debugging information entries* (DIE), representing type information -such as datatype layout, function signatures, block layout, variable location -and scope information, etc. It is the purpose of this module to generate correct -metadata and insert it into the LLVM IR. - -As the exact format of metadata trees may change between different LLVM -versions, we now use LLVM -[DIBuilder](http://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) to -create metadata where possible. This will hopefully ease the adaption of this -module to future LLVM versions. - -The public API of the module is a set of functions that will insert the correct -metadata into the LLVM IR when called with the right parameters. The module is -thus driven from an outside client with functions like -`debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`. - -Internally the module will try to reuse already created metadata by utilizing a -cache. The way to get a shared metadata node when needed is thus to just call -the corresponding function in this module: - - let file_metadata = file_metadata(crate_context, path); - -The function will take care of probing the cache for an existing node for that -exact file path. - -All private state used by the module is stored within either the -CrateDebugContext struct (owned by the CrateContext) or the FunctionDebugContext -(owned by the FunctionContext). - -This file consists of three conceptual sections: -1. The public interface of the module -2. Module-internal metadata creation functions -3. Minor utility functions - - -## Recursive Types - -Some kinds of types, such as structs and enums can be recursive. That means that -the type definition of some type X refers to some other type which in turn -(transitively) refers to X. This introduces cycles into the type referral graph. -A naive algorithm doing an on-demand, depth-first traversal of this graph when -describing types, can get trapped in an endless loop when it reaches such a -cycle. - -For example, the following simple type for a singly-linked list... - -``` -struct List { - value: int, - tail: Option>, -} -``` - -will generate the following callstack with a naive DFS algorithm: - -``` -describe(t = List) - describe(t = int) - describe(t = Option>) - describe(t = Box) - describe(t = List) // at the beginning again... - ... -``` - -To break cycles like these, we use "forward declarations". That is, when the -algorithm encounters a possibly recursive type (any struct or enum), it -immediately creates a type description node and inserts it into the cache -*before* describing the members of the type. This type description is just a -stub (as type members are not described and added to it yet) but it allows the -algorithm to already refer to the type. After the stub is inserted into the -cache, the algorithm continues as before. If it now encounters a recursive -reference, it will hit the cache and does not try to describe the type anew. - -This behaviour is encapsulated in the 'RecursiveTypeDescription' enum, which -represents a kind of continuation, storing all state needed to continue -traversal at the type members after the type has been registered with the cache. -(This implementation approach might be a tad over-engineered and may change in -the future) - - -## Source Locations and Line Information - -In addition to data type descriptions the debugging information must also allow -to map machine code locations back to source code locations in order to be useful. -This functionality is also handled in this module. The following functions allow -to control source mappings: - -+ set_source_location() -+ clear_source_location() -+ start_emitting_source_locations() - -`set_source_location()` allows to set the current source location. All IR -instructions created after a call to this function will be linked to the given -source location, until another location is specified with -`set_source_location()` or the source location is cleared with -`clear_source_location()`. In the later case, subsequent IR instruction will not -be linked to any source location. As you can see, this is a stateful API -(mimicking the one in LLVM), so be careful with source locations set by previous -calls. It's probably best to not rely on any specific state being present at a -given point in code. - -One topic that deserves some extra attention is *function prologues*. At the -beginning of a function's machine code there are typically a few instructions -for loading argument values into allocas and checking if there's enough stack -space for the function to execute. This *prologue* is not visible in the source -code and LLVM puts a special PROLOGUE END marker into the line table at the -first non-prologue instruction of the function. In order to find out where the -prologue ends, LLVM looks for the first instruction in the function body that is -linked to a source location. So, when generating prologue instructions we have -to make sure that we don't emit source location information until the 'real' -function body begins. For this reason, source location emission is disabled by -default for any new function being translated and is only activated after a call -to the third function from the list above, `start_emitting_source_locations()`. -This function should be called right before regularly starting to translate the -top-level block of the given function. - -There is one exception to the above rule: `llvm.dbg.declare` instruction must be -linked to the source location of the variable being declared. For function -parameters these `llvm.dbg.declare` instructions typically occur in the middle -of the prologue, however, they are ignored by LLVM's prologue detection. The -`create_argument_metadata()` and related functions take care of linking the -`llvm.dbg.declare` instructions to the correct source locations even while -source location emission is still disabled, so there is no need to do anything -special with source location handling here. - -## Unique Type Identification - -In order for link-time optimization to work properly, LLVM needs a unique type -identifier that tells it across compilation units which types are the same as -others. This type identifier is created by TypeMap::get_unique_type_id_of_type() -using the following algorithm: - -(1) Primitive types have their name as ID -(2) Structs, enums and traits have a multipart identifier - - (1) The first part is the SVH (strict version hash) of the crate they were - originally defined in - - (2) The second part is the ast::NodeId of the definition in their original - crate - - (3) The final part is a concatenation of the type IDs of their concrete type - arguments if they are generic types. - -(3) Tuple-, pointer and function types are structurally identified, which means - that they are equivalent if their component types are equivalent (i.e. (int, - int) is the same regardless in which crate it is used). - -This algorithm also provides a stable ID for types that are defined in one crate -but instantiated from metadata within another crate. We just have to take care -to always map crate and node IDs back to the original crate context. - -As a side-effect these unique type IDs also help to solve a problem arising from -lifetime parameters. Since lifetime parameters are completely omitted in -debuginfo, more than one `Ty` instance may map to the same debuginfo type -metadata, that is, some struct `Struct<'a>` may have N instantiations with -different concrete substitutions for `'a`, and thus there will be N `Ty` -instances for the type `Struct<'a>` even though it is not generic otherwise. -Unfortunately this means that we cannot use `ty::type_id()` as cheap identifier -for type metadata---we have done this in the past, but it led to unnecessary -metadata duplication in the best case and LLVM assertions in the worst. However, -the unique type ID as described above *can* be used as identifier. Since it is -comparatively expensive to construct, though, `ty::type_id()` is still used -additionally as an optimization for cases where the exact same type has been -seen before (which is most of the time). */ +//! # Debug Info Module +//! +//! This module serves the purpose of generating debug symbols. We use LLVM's +//! [source level debugging](http://llvm.org/docs/SourceLevelDebugging.html) +//! features for generating the debug information. The general principle is this: +//! +//! Given the right metadata in the LLVM IR, the LLVM code generator is able to +//! create DWARF debug symbols for the given code. The +//! [metadata](http://llvm.org/docs/LangRef.html#metadata-type) is structured much +//! like DWARF *debugging information entries* (DIE), representing type information +//! such as datatype layout, function signatures, block layout, variable location +//! and scope information, etc. It is the purpose of this module to generate correct +//! metadata and insert it into the LLVM IR. +//! +//! As the exact format of metadata trees may change between different LLVM +//! versions, we now use LLVM +//! [DIBuilder](http://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) to +//! create metadata where possible. This will hopefully ease the adaption of this +//! module to future LLVM versions. +//! +//! The public API of the module is a set of functions that will insert the correct +//! metadata into the LLVM IR when called with the right parameters. The module is +//! thus driven from an outside client with functions like +//! `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`. +//! +//! Internally the module will try to reuse already created metadata by utilizing a +//! cache. The way to get a shared metadata node when needed is thus to just call +//! the corresponding function in this module: +//! +//! let file_metadata = file_metadata(crate_context, path); +//! +//! The function will take care of probing the cache for an existing node for that +//! exact file path. +//! +//! All private state used by the module is stored within either the +//! CrateDebugContext struct (owned by the CrateContext) or the FunctionDebugContext +//! (owned by the FunctionContext). +//! +//! This file consists of three conceptual sections: +//! 1. The public interface of the module +//! 2. Module-internal metadata creation functions +//! 3. Minor utility functions +//! +//! +//! ## Recursive Types +//! +//! Some kinds of types, such as structs and enums can be recursive. That means that +//! the type definition of some type X refers to some other type which in turn +//! (transitively) refers to X. This introduces cycles into the type referral graph. +//! A naive algorithm doing an on-demand, depth-first traversal of this graph when +//! describing types, can get trapped in an endless loop when it reaches such a +//! cycle. +//! +//! For example, the following simple type for a singly-linked list... +//! +//! ``` +//! struct List { +//! value: int, +//! tail: Option>, +//! } +//! ``` +//! +//! will generate the following callstack with a naive DFS algorithm: +//! +//! ``` +//! describe(t = List) +//! describe(t = int) +//! describe(t = Option>) +//! describe(t = Box) +//! describe(t = List) // at the beginning again... +//! ... +//! ``` +//! +//! To break cycles like these, we use "forward declarations". That is, when the +//! algorithm encounters a possibly recursive type (any struct or enum), it +//! immediately creates a type description node and inserts it into the cache +//! *before* describing the members of the type. This type description is just a +//! stub (as type members are not described and added to it yet) but it allows the +//! algorithm to already refer to the type. After the stub is inserted into the +//! cache, the algorithm continues as before. If it now encounters a recursive +//! reference, it will hit the cache and does not try to describe the type anew. +//! +//! This behaviour is encapsulated in the 'RecursiveTypeDescription' enum, which +//! represents a kind of continuation, storing all state needed to continue +//! traversal at the type members after the type has been registered with the cache. +//! (This implementation approach might be a tad over-engineered and may change in +//! the future) +//! +//! +//! ## Source Locations and Line Information +//! +//! In addition to data type descriptions the debugging information must also allow +//! to map machine code locations back to source code locations in order to be useful. +//! This functionality is also handled in this module. The following functions allow +//! to control source mappings: +//! +//! + set_source_location() +//! + clear_source_location() +//! + start_emitting_source_locations() +//! +//! `set_source_location()` allows to set the current source location. All IR +//! instructions created after a call to this function will be linked to the given +//! source location, until another location is specified with +//! `set_source_location()` or the source location is cleared with +//! `clear_source_location()`. In the later case, subsequent IR instruction will not +//! be linked to any source location. As you can see, this is a stateful API +//! (mimicking the one in LLVM), so be careful with source locations set by previous +//! calls. It's probably best to not rely on any specific state being present at a +//! given point in code. +//! +//! One topic that deserves some extra attention is *function prologues*. At the +//! beginning of a function's machine code there are typically a few instructions +//! for loading argument values into allocas and checking if there's enough stack +//! space for the function to execute. This *prologue* is not visible in the source +//! code and LLVM puts a special PROLOGUE END marker into the line table at the +//! first non-prologue instruction of the function. In order to find out where the +//! prologue ends, LLVM looks for the first instruction in the function body that is +//! linked to a source location. So, when generating prologue instructions we have +//! to make sure that we don't emit source location information until the 'real' +//! function body begins. For this reason, source location emission is disabled by +//! default for any new function being translated and is only activated after a call +//! to the third function from the list above, `start_emitting_source_locations()`. +//! This function should be called right before regularly starting to translate the +//! top-level block of the given function. +//! +//! There is one exception to the above rule: `llvm.dbg.declare` instruction must be +//! linked to the source location of the variable being declared. For function +//! parameters these `llvm.dbg.declare` instructions typically occur in the middle +//! of the prologue, however, they are ignored by LLVM's prologue detection. The +//! `create_argument_metadata()` and related functions take care of linking the +//! `llvm.dbg.declare` instructions to the correct source locations even while +//! source location emission is still disabled, so there is no need to do anything +//! special with source location handling here. +//! +//! ## Unique Type Identification +//! +//! In order for link-time optimization to work properly, LLVM needs a unique type +//! identifier that tells it across compilation units which types are the same as +//! others. This type identifier is created by TypeMap::get_unique_type_id_of_type() +//! using the following algorithm: +//! +//! (1) Primitive types have their name as ID +//! (2) Structs, enums and traits have a multipart identifier +//! +//! (1) The first part is the SVH (strict version hash) of the crate they were +//! originally defined in +//! +//! (2) The second part is the ast::NodeId of the definition in their original +//! crate +//! +//! (3) The final part is a concatenation of the type IDs of their concrete type +//! arguments if they are generic types. +//! +//! (3) Tuple-, pointer and function types are structurally identified, which means +//! that they are equivalent if their component types are equivalent (i.e. (int, +//! int) is the same regardless in which crate it is used). +//! +//! This algorithm also provides a stable ID for types that are defined in one crate +//! but instantiated from metadata within another crate. We just have to take care +//! to always map crate and node IDs back to the original crate context. +//! +//! As a side-effect these unique type IDs also help to solve a problem arising from +//! lifetime parameters. Since lifetime parameters are completely omitted in +//! debuginfo, more than one `Ty` instance may map to the same debuginfo type +//! metadata, that is, some struct `Struct<'a>` may have N instantiations with +//! different concrete substitutions for `'a`, and thus there will be N `Ty` +//! instances for the type `Struct<'a>` even though it is not generic otherwise. +//! Unfortunately this means that we cannot use `ty::type_id()` as cheap identifier +//! for type metadata---we have done this in the past, but it led to unnecessary +//! metadata duplication in the best case and LLVM assertions in the worst. However, +//! the unique type ID as described above *can* be used as identifier. Since it is +//! comparatively expensive to construct, though, `ty::type_id()` is still used +//! additionally as an optimization for cases where the exact same type has been +//! seen before (which is most of the time). use self::FunctionDebugContextRepr::*; use self::VariableAccess::*; use self::VariableKind::*; diff --git a/src/librustc_trans/trans/doc.rs b/src/librustc_trans/trans/doc.rs index a5281e582f1..c3ab8986372 100644 --- a/src/librustc_trans/trans/doc.rs +++ b/src/librustc_trans/trans/doc.rs @@ -8,230 +8,226 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -# Documentation for the trans module - -This module contains high-level summaries of how the various modules -in trans work. It is a work in progress. For detailed comments, -naturally, you can refer to the individual modules themselves. - -## The Expr module - -The expr module handles translation of expressions. The most general -translation routine is `trans()`, which will translate an expression -into a datum. `trans_into()` is also available, which will translate -an expression and write the result directly into memory, sometimes -avoiding the need for a temporary stack slot. Finally, -`trans_to_lvalue()` is available if you'd like to ensure that the -result has cleanup scheduled. - -Internally, each of these functions dispatches to various other -expression functions depending on the kind of expression. We divide -up expressions into: - -- **Datum expressions:** Those that most naturally yield values. - Examples would be `22`, `box x`, or `a + b` (when not overloaded). -- **DPS expressions:** Those that most naturally write into a location - in memory. Examples would be `foo()` or `Point { x: 3, y: 4 }`. -- **Statement expressions:** That that do not generate a meaningful - result. Examples would be `while { ... }` or `return 44`. - -## The Datum module - -A `Datum` encapsulates the result of evaluating a Rust expression. It -contains a `ValueRef` indicating the result, a `Ty` describing -the Rust type, but also a *kind*. The kind indicates whether the datum -has cleanup scheduled (lvalue) or not (rvalue) and -- in the case of -rvalues -- whether or not the value is "by ref" or "by value". - -The datum API is designed to try and help you avoid memory errors like -forgetting to arrange cleanup or duplicating a value. The type of the -datum incorporates the kind, and thus reflects whether it has cleanup -scheduled: - -- `Datum` -- by ref, cleanup scheduled -- `Datum` -- by value or by ref, no cleanup scheduled -- `Datum` -- either `Datum` or `Datum` - -Rvalue and expr datums are noncopyable, and most of the methods on -datums consume the datum itself (with some notable exceptions). This -reflects the fact that datums may represent affine values which ought -to be consumed exactly once, and if you were to try to (for example) -store an affine value multiple times, you would be duplicating it, -which would certainly be a bug. - -Some of the datum methods, however, are designed to work only on -copyable values such as ints or pointers. Those methods may borrow the -datum (`&self`) rather than consume it, but they always include -assertions on the type of the value represented to check that this -makes sense. An example is `shallow_copy()`, which duplicates -a datum value. - -Translating an expression always yields a `Datum` result, but -the methods `to_[lr]value_datum()` can be used to coerce a -`Datum` into a `Datum` or `Datum` as -needed. Coercing to an lvalue is fairly common, and generally occurs -whenever it is necessary to inspect a value and pull out its -subcomponents (for example, a match, or indexing expression). Coercing -to an rvalue is more unusual; it occurs when moving values from place -to place, such as in an assignment expression or parameter passing. - -### Lvalues in detail - -An lvalue datum is one for which cleanup has been scheduled. Lvalue -datums are always located in memory, and thus the `ValueRef` for an -LLVM value is always a pointer to the actual Rust value. This means -that if the Datum has a Rust type of `int`, then the LLVM type of the -`ValueRef` will be `int*` (pointer to int). - -Because lvalues already have cleanups scheduled, the memory must be -zeroed to prevent the cleanup from taking place (presuming that the -Rust type needs drop in the first place, otherwise it doesn't -matter). The Datum code automatically performs this zeroing when the -value is stored to a new location, for example. - -Lvalues usually result from evaluating lvalue expressions. For -example, evaluating a local variable `x` yields an lvalue, as does a -reference to a field like `x.f` or an index `x[i]`. - -Lvalue datums can also arise by *converting* an rvalue into an lvalue. -This is done with the `to_lvalue_datum` method defined on -`Datum`. Basically this method just schedules cleanup if the -datum is an rvalue, possibly storing the value into a stack slot first -if needed. Converting rvalues into lvalues occurs in constructs like -`&foo()` or `match foo() { ref x => ... }`, where the user is -implicitly requesting a temporary. - -Somewhat surprisingly, not all lvalue expressions yield lvalue datums -when trans'd. Ultimately the reason for this is to micro-optimize -the resulting LLVM. For example, consider the following code: - - fn foo() -> Box { ... } - let x = *foo(); - -The expression `*foo()` is an lvalue, but if you invoke `expr::trans`, -it will return an rvalue datum. See `deref_once` in expr.rs for -more details. - -### Rvalues in detail - -Rvalues datums are values with no cleanup scheduled. One must be -careful with rvalue datums to ensure that cleanup is properly -arranged, usually by converting to an lvalue datum or by invoking the -`add_clean` method. - -### Scratch datums - -Sometimes you need some temporary scratch space. The functions -`[lr]value_scratch_datum()` can be used to get temporary stack -space. As their name suggests, they yield lvalues and rvalues -respectively. That is, the slot from `lvalue_scratch_datum` will have -cleanup arranged, and the slot from `rvalue_scratch_datum` does not. - -## The Cleanup module - -The cleanup module tracks what values need to be cleaned up as scopes -are exited, either via panic or just normal control flow. The basic -idea is that the function context maintains a stack of cleanup scopes -that are pushed/popped as we traverse the AST tree. There is typically -at least one cleanup scope per AST node; some AST nodes may introduce -additional temporary scopes. - -Cleanup items can be scheduled into any of the scopes on the stack. -Typically, when a scope is popped, we will also generate the code for -each of its cleanups at that time. This corresponds to a normal exit -from a block (for example, an expression completing evaluation -successfully without panic). However, it is also possible to pop a -block *without* executing its cleanups; this is typically used to -guard intermediate values that must be cleaned up on panic, but not -if everything goes right. See the section on custom scopes below for -more details. - -Cleanup scopes come in three kinds: -- **AST scopes:** each AST node in a function body has a corresponding - AST scope. We push the AST scope when we start generate code for an AST - node and pop it once the AST node has been fully generated. -- **Loop scopes:** loops have an additional cleanup scope. Cleanups are - never scheduled into loop scopes; instead, they are used to record the - basic blocks that we should branch to when a `continue` or `break` statement - is encountered. -- **Custom scopes:** custom scopes are typically used to ensure cleanup - of intermediate values. - -### When to schedule cleanup - -Although the cleanup system is intended to *feel* fairly declarative, -it's still important to time calls to `schedule_clean()` correctly. -Basically, you should not schedule cleanup for memory until it has -been initialized, because if an unwind should occur before the memory -is fully initialized, then the cleanup will run and try to free or -drop uninitialized memory. If the initialization itself produces -byproducts that need to be freed, then you should use temporary custom -scopes to ensure that those byproducts will get freed on unwind. For -example, an expression like `box foo()` will first allocate a box in the -heap and then call `foo()` -- if `foo()` should panic, this box needs -to be *shallowly* freed. - -### Long-distance jumps - -In addition to popping a scope, which corresponds to normal control -flow exiting the scope, we may also *jump out* of a scope into some -earlier scope on the stack. This can occur in response to a `return`, -`break`, or `continue` statement, but also in response to panic. In -any of these cases, we will generate a series of cleanup blocks for -each of the scopes that is exited. So, if the stack contains scopes A -... Z, and we break out of a loop whose corresponding cleanup scope is -X, we would generate cleanup blocks for the cleanups in X, Y, and Z. -After cleanup is done we would branch to the exit point for scope X. -But if panic should occur, we would generate cleanups for all the -scopes from A to Z and then resume the unwind process afterwards. - -To avoid generating tons of code, we cache the cleanup blocks that we -create for breaks, returns, unwinds, and other jumps. Whenever a new -cleanup is scheduled, though, we must clear these cached blocks. A -possible improvement would be to keep the cached blocks but simply -generate a new block which performs the additional cleanup and then -branches to the existing cached blocks. - -### AST and loop cleanup scopes - -AST cleanup scopes are pushed when we begin and end processing an AST -node. They are used to house cleanups related to rvalue temporary that -get referenced (e.g., due to an expression like `&Foo()`). Whenever an -AST scope is popped, we always trans all the cleanups, adding the cleanup -code after the postdominator of the AST node. - -AST nodes that represent breakable loops also push a loop scope; the -loop scope never has any actual cleanups, it's just used to point to -the basic blocks where control should flow after a "continue" or -"break" statement. Popping a loop scope never generates code. - -### Custom cleanup scopes - -Custom cleanup scopes are used for a variety of purposes. The most -common though is to handle temporary byproducts, where cleanup only -needs to occur on panic. The general strategy is to push a custom -cleanup scope, schedule *shallow* cleanups into the custom scope, and -then pop the custom scope (without transing the cleanups) when -execution succeeds normally. This way the cleanups are only trans'd on -unwind, and only up until the point where execution succeeded, at -which time the complete value should be stored in an lvalue or some -other place where normal cleanup applies. - -To spell it out, here is an example. Imagine an expression `box expr`. -We would basically: - -1. Push a custom cleanup scope C. -2. Allocate the box. -3. Schedule a shallow free in the scope C. -4. Trans `expr` into the box. -5. Pop the scope C. -6. Return the box as an rvalue. - -This way, if a panic occurs while transing `expr`, the custom -cleanup scope C is pushed and hence the box will be freed. The trans -code for `expr` itself is responsible for freeing any other byproducts -that may be in play. - -*/ +//! # Documentation for the trans module +//! +//! This module contains high-level summaries of how the various modules +//! in trans work. It is a work in progress. For detailed comments, +//! naturally, you can refer to the individual modules themselves. +//! +//! ## The Expr module +//! +//! The expr module handles translation of expressions. The most general +//! translation routine is `trans()`, which will translate an expression +//! into a datum. `trans_into()` is also available, which will translate +//! an expression and write the result directly into memory, sometimes +//! avoiding the need for a temporary stack slot. Finally, +//! `trans_to_lvalue()` is available if you'd like to ensure that the +//! result has cleanup scheduled. +//! +//! Internally, each of these functions dispatches to various other +//! expression functions depending on the kind of expression. We divide +//! up expressions into: +//! +//! - **Datum expressions:** Those that most naturally yield values. +//! Examples would be `22`, `box x`, or `a + b` (when not overloaded). +//! - **DPS expressions:** Those that most naturally write into a location +//! in memory. Examples would be `foo()` or `Point { x: 3, y: 4 }`. +//! - **Statement expressions:** That that do not generate a meaningful +//! result. Examples would be `while { ... }` or `return 44`. +//! +//! ## The Datum module +//! +//! A `Datum` encapsulates the result of evaluating a Rust expression. It +//! contains a `ValueRef` indicating the result, a `Ty` describing +//! the Rust type, but also a *kind*. The kind indicates whether the datum +//! has cleanup scheduled (lvalue) or not (rvalue) and -- in the case of +//! rvalues -- whether or not the value is "by ref" or "by value". +//! +//! The datum API is designed to try and help you avoid memory errors like +//! forgetting to arrange cleanup or duplicating a value. The type of the +//! datum incorporates the kind, and thus reflects whether it has cleanup +//! scheduled: +//! +//! - `Datum` -- by ref, cleanup scheduled +//! - `Datum` -- by value or by ref, no cleanup scheduled +//! - `Datum` -- either `Datum` or `Datum` +//! +//! Rvalue and expr datums are noncopyable, and most of the methods on +//! datums consume the datum itself (with some notable exceptions). This +//! reflects the fact that datums may represent affine values which ought +//! to be consumed exactly once, and if you were to try to (for example) +//! store an affine value multiple times, you would be duplicating it, +//! which would certainly be a bug. +//! +//! Some of the datum methods, however, are designed to work only on +//! copyable values such as ints or pointers. Those methods may borrow the +//! datum (`&self`) rather than consume it, but they always include +//! assertions on the type of the value represented to check that this +//! makes sense. An example is `shallow_copy()`, which duplicates +//! a datum value. +//! +//! Translating an expression always yields a `Datum` result, but +//! the methods `to_[lr]value_datum()` can be used to coerce a +//! `Datum` into a `Datum` or `Datum` as +//! needed. Coercing to an lvalue is fairly common, and generally occurs +//! whenever it is necessary to inspect a value and pull out its +//! subcomponents (for example, a match, or indexing expression). Coercing +//! to an rvalue is more unusual; it occurs when moving values from place +//! to place, such as in an assignment expression or parameter passing. +//! +//! ### Lvalues in detail +//! +//! An lvalue datum is one for which cleanup has been scheduled. Lvalue +//! datums are always located in memory, and thus the `ValueRef` for an +//! LLVM value is always a pointer to the actual Rust value. This means +//! that if the Datum has a Rust type of `int`, then the LLVM type of the +//! `ValueRef` will be `int*` (pointer to int). +//! +//! Because lvalues already have cleanups scheduled, the memory must be +//! zeroed to prevent the cleanup from taking place (presuming that the +//! Rust type needs drop in the first place, otherwise it doesn't +//! matter). The Datum code automatically performs this zeroing when the +//! value is stored to a new location, for example. +//! +//! Lvalues usually result from evaluating lvalue expressions. For +//! example, evaluating a local variable `x` yields an lvalue, as does a +//! reference to a field like `x.f` or an index `x[i]`. +//! +//! Lvalue datums can also arise by *converting* an rvalue into an lvalue. +//! This is done with the `to_lvalue_datum` method defined on +//! `Datum`. Basically this method just schedules cleanup if the +//! datum is an rvalue, possibly storing the value into a stack slot first +//! if needed. Converting rvalues into lvalues occurs in constructs like +//! `&foo()` or `match foo() { ref x => ... }`, where the user is +//! implicitly requesting a temporary. +//! +//! Somewhat surprisingly, not all lvalue expressions yield lvalue datums +//! when trans'd. Ultimately the reason for this is to micro-optimize +//! the resulting LLVM. For example, consider the following code: +//! +//! fn foo() -> Box { ... } +//! let x = *foo(); +//! +//! The expression `*foo()` is an lvalue, but if you invoke `expr::trans`, +//! it will return an rvalue datum. See `deref_once` in expr.rs for +//! more details. +//! +//! ### Rvalues in detail +//! +//! Rvalues datums are values with no cleanup scheduled. One must be +//! careful with rvalue datums to ensure that cleanup is properly +//! arranged, usually by converting to an lvalue datum or by invoking the +//! `add_clean` method. +//! +//! ### Scratch datums +//! +//! Sometimes you need some temporary scratch space. The functions +//! `[lr]value_scratch_datum()` can be used to get temporary stack +//! space. As their name suggests, they yield lvalues and rvalues +//! respectively. That is, the slot from `lvalue_scratch_datum` will have +//! cleanup arranged, and the slot from `rvalue_scratch_datum` does not. +//! +//! ## The Cleanup module +//! +//! The cleanup module tracks what values need to be cleaned up as scopes +//! are exited, either via panic or just normal control flow. The basic +//! idea is that the function context maintains a stack of cleanup scopes +//! that are pushed/popped as we traverse the AST tree. There is typically +//! at least one cleanup scope per AST node; some AST nodes may introduce +//! additional temporary scopes. +//! +//! Cleanup items can be scheduled into any of the scopes on the stack. +//! Typically, when a scope is popped, we will also generate the code for +//! each of its cleanups at that time. This corresponds to a normal exit +//! from a block (for example, an expression completing evaluation +//! successfully without panic). However, it is also possible to pop a +//! block *without* executing its cleanups; this is typically used to +//! guard intermediate values that must be cleaned up on panic, but not +//! if everything goes right. See the section on custom scopes below for +//! more details. +//! +//! Cleanup scopes come in three kinds: +//! - **AST scopes:** each AST node in a function body has a corresponding +//! AST scope. We push the AST scope when we start generate code for an AST +//! node and pop it once the AST node has been fully generated. +//! - **Loop scopes:** loops have an additional cleanup scope. Cleanups are +//! never scheduled into loop scopes; instead, they are used to record the +//! basic blocks that we should branch to when a `continue` or `break` statement +//! is encountered. +//! - **Custom scopes:** custom scopes are typically used to ensure cleanup +//! of intermediate values. +//! +//! ### When to schedule cleanup +//! +//! Although the cleanup system is intended to *feel* fairly declarative, +//! it's still important to time calls to `schedule_clean()` correctly. +//! Basically, you should not schedule cleanup for memory until it has +//! been initialized, because if an unwind should occur before the memory +//! is fully initialized, then the cleanup will run and try to free or +//! drop uninitialized memory. If the initialization itself produces +//! byproducts that need to be freed, then you should use temporary custom +//! scopes to ensure that those byproducts will get freed on unwind. For +//! example, an expression like `box foo()` will first allocate a box in the +//! heap and then call `foo()` -- if `foo()` should panic, this box needs +//! to be *shallowly* freed. +//! +//! ### Long-distance jumps +//! +//! In addition to popping a scope, which corresponds to normal control +//! flow exiting the scope, we may also *jump out* of a scope into some +//! earlier scope on the stack. This can occur in response to a `return`, +//! `break`, or `continue` statement, but also in response to panic. In +//! any of these cases, we will generate a series of cleanup blocks for +//! each of the scopes that is exited. So, if the stack contains scopes A +//! ... Z, and we break out of a loop whose corresponding cleanup scope is +//! X, we would generate cleanup blocks for the cleanups in X, Y, and Z. +//! After cleanup is done we would branch to the exit point for scope X. +//! But if panic should occur, we would generate cleanups for all the +//! scopes from A to Z and then resume the unwind process afterwards. +//! +//! To avoid generating tons of code, we cache the cleanup blocks that we +//! create for breaks, returns, unwinds, and other jumps. Whenever a new +//! cleanup is scheduled, though, we must clear these cached blocks. A +//! possible improvement would be to keep the cached blocks but simply +//! generate a new block which performs the additional cleanup and then +//! branches to the existing cached blocks. +//! +//! ### AST and loop cleanup scopes +//! +//! AST cleanup scopes are pushed when we begin and end processing an AST +//! node. They are used to house cleanups related to rvalue temporary that +//! get referenced (e.g., due to an expression like `&Foo()`). Whenever an +//! AST scope is popped, we always trans all the cleanups, adding the cleanup +//! code after the postdominator of the AST node. +//! +//! AST nodes that represent breakable loops also push a loop scope; the +//! loop scope never has any actual cleanups, it's just used to point to +//! the basic blocks where control should flow after a "continue" or +//! "break" statement. Popping a loop scope never generates code. +//! +//! ### Custom cleanup scopes +//! +//! Custom cleanup scopes are used for a variety of purposes. The most +//! common though is to handle temporary byproducts, where cleanup only +//! needs to occur on panic. The general strategy is to push a custom +//! cleanup scope, schedule *shallow* cleanups into the custom scope, and +//! then pop the custom scope (without transing the cleanups) when +//! execution succeeds normally. This way the cleanups are only trans'd on +//! unwind, and only up until the point where execution succeeded, at +//! which time the complete value should be stored in an lvalue or some +//! other place where normal cleanup applies. +//! +//! To spell it out, here is an example. Imagine an expression `box expr`. +//! We would basically: +//! +//! 1. Push a custom cleanup scope C. +//! 2. Allocate the box. +//! 3. Schedule a shallow free in the scope C. +//! 4. Trans `expr` into the box. +//! 5. Pop the scope C. +//! 6. Return the box as an rvalue. +//! +//! This way, if a panic occurs while transing `expr`, the custom +//! cleanup scope C is pushed and hence the box will be freed. The trans +//! code for `expr` itself is responsible for freeing any other byproducts +//! that may be in play. diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 482b318e372..60809c8644d 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -8,28 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * # Translation of Expressions - * - * Public entry points: - * - * - `trans_into(bcx, expr, dest) -> bcx`: evaluates an expression, - * storing the result into `dest`. This is the preferred form, if you - * can manage it. - * - * - `trans(bcx, expr) -> DatumBlock`: evaluates an expression, yielding - * `Datum` with the result. You can then store the datum, inspect - * the value, etc. This may introduce temporaries if the datum is a - * structural type. - * - * - `trans_to_lvalue(bcx, expr, "...") -> DatumBlock`: evaluates an - * expression and ensures that the result has a cleanup associated with it, - * creating a temporary stack slot if necessary. - * - * - `trans_local_var -> Datum`: looks up a local variable or upvar. - * - * See doc.rs for more comments. - */ +//! # Translation of Expressions +//! +//! Public entry points: +//! +//! - `trans_into(bcx, expr, dest) -> bcx`: evaluates an expression, +//! storing the result into `dest`. This is the preferred form, if you +//! can manage it. +//! +//! - `trans(bcx, expr) -> DatumBlock`: evaluates an expression, yielding +//! `Datum` with the result. You can then store the datum, inspect +//! the value, etc. This may introduce temporaries if the datum is a +//! structural type. +//! +//! - `trans_to_lvalue(bcx, expr, "...") -> DatumBlock`: evaluates an +//! expression and ensures that the result has a cleanup associated with it, +//! creating a temporary stack slot if necessary. +//! +//! - `trans_local_var -> Datum`: looks up a local variable or upvar. +//! +//! See doc.rs for more comments. #![allow(non_camel_case_types)] @@ -82,15 +80,12 @@ impl Dest { } } +/// This function is equivalent to `trans(bcx, expr).store_to_dest(dest)` but it may generate +/// better optimized LLVM code. pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, dest: Dest) -> Block<'blk, 'tcx> { - /*! - * This function is equivalent to `trans(bcx, expr).store_to_dest(dest)` - * but it may generate better optimized LLVM code. - */ - let mut bcx = bcx; if bcx.tcx().adjustments.borrow().contains_key(&expr.id) { @@ -124,16 +119,12 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.fcx.pop_and_trans_ast_cleanup_scope(bcx, expr.id) } +/// Translates an expression, returning a datum (and new block) encapsulating the result. When +/// possible, it is preferred to use `trans_into`, as that may avoid creating a temporary on the +/// stack. pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * Translates an expression, returning a datum (and new block) - * encapsulating the result. When possible, it is preferred to - * use `trans_into`, as that may avoid creating a temporary on - * the stack. - */ - debug!("trans(expr={})", bcx.expr_to_string(expr)); let mut bcx = bcx; @@ -157,15 +148,12 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef { GEPi(bcx, fat_ptr, &[0u, abi::FAT_PTR_ADDR]) } +/// Helper for trans that apply adjustments from `expr` to `datum`, which should be the unadjusted +/// translation of `expr`. fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * Helper for trans that apply adjustments from `expr` to `datum`, - * which should be the unadjusted translation of `expr`. - */ - let mut bcx = bcx; let mut datum = datum; let adjustment = match bcx.tcx().adjustments.borrow().get(&expr.id).cloned() { @@ -480,34 +468,27 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } +/// Translates an expression in "lvalue" mode -- meaning that it returns a reference to the memory +/// that the expr represents. +/// +/// If this expression is an rvalue, this implies introducing a temporary. In other words, +/// something like `x().f` is translated into roughly the equivalent of +/// +/// { tmp = x(); tmp.f } pub fn trans_to_lvalue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, name: &str) -> DatumBlock<'blk, 'tcx, Lvalue> { - /*! - * Translates an expression in "lvalue" mode -- meaning that it - * returns a reference to the memory that the expr represents. - * - * If this expression is an rvalue, this implies introducing a - * temporary. In other words, something like `x().f` is - * translated into roughly the equivalent of - * - * { tmp = x(); tmp.f } - */ - let mut bcx = bcx; let datum = unpack_datum!(bcx, trans(bcx, expr)); return datum.to_lvalue_datum(bcx, name, expr.id); } +/// A version of `trans` that ignores adjustments. You almost certainly do not want to call this +/// directly. fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * A version of `trans` that ignores adjustments. You almost - * certainly do not want to call this directly. - */ - let mut bcx = bcx; debug!("trans_unadjusted(expr={})", bcx.expr_to_string(expr)); @@ -1218,14 +1199,10 @@ fn trans_def_fn_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, Datum::new(llfn, fn_ty, RvalueExpr(Rvalue::new(ByValue)))) } +/// Translates a reference to a local variable or argument. This always results in an lvalue datum. pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, def: def::Def) -> Datum<'tcx, Lvalue> { - /*! - * Translates a reference to a local variable or argument. - * This always results in an lvalue datum. - */ - let _icx = push_ctxt("trans_local_var"); match def { @@ -1262,18 +1239,14 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } +/// Helper for enumerating the field types of structs, enums, or records. The optional node ID here +/// is the node ID of the path identifying the enum variant in use. If none, this cannot possibly +/// an enum variant (so, if it is and `node_id_opt` is none, this function panics). pub fn with_field_tys<'tcx, R>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, node_id_opt: Option, op: |ty::Disr, (&[ty::field<'tcx>])| -> R) -> R { - /*! - * Helper for enumerating the field types of structs, enums, or records. - * The optional node ID here is the node ID of the path identifying the enum - * variant in use. If none, this cannot possibly an enum variant (so, if it - * is and `node_id_opt` is none, this function panics). - */ - match ty.sty { ty::ty_struct(did, ref substs) => { op(0, struct_fields(tcx, did, substs).as_slice()) @@ -2189,24 +2162,18 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return r; + /// We microoptimize derefs of owned pointers a bit here. Basically, the idea is to make the + /// deref of an rvalue result in an rvalue. This helps to avoid intermediate stack slots in the + /// resulting LLVM. The idea here is that, if the `Box` pointer is an rvalue, then we can + /// schedule a *shallow* free of the `Box` pointer, and then return a ByRef rvalue into the + /// pointer. Because the free is shallow, it is legit to return an rvalue, because we know that + /// the contents are not yet scheduled to be freed. The language rules ensure that the contents + /// will be used (or moved) before the free occurs. fn deref_owned_pointer<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, content_ty: Ty<'tcx>) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * We microoptimize derefs of owned pointers a bit here. - * Basically, the idea is to make the deref of an rvalue - * result in an rvalue. This helps to avoid intermediate stack - * slots in the resulting LLVM. The idea here is that, if the - * `Box` pointer is an rvalue, then we can schedule a *shallow* - * free of the `Box` pointer, and then return a ByRef rvalue - * into the pointer. Because the free is shallow, it is legit - * to return an rvalue, because we know that the contents are - * not yet scheduled to be freed. The language rules ensure that the - * contents will be used (or moved) before the free occurs. - */ - match datum.kind { RvalueExpr(Rvalue { mode: ByRef }) => { let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 1f6aeacc860..6f97f6453fd 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -161,14 +161,10 @@ pub fn register_static(ccx: &CrateContext, } } +/// Registers a foreign function found in a library. Just adds a LLVM global. pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, abi: Abi, fty: Ty<'tcx>, name: &str) -> ValueRef { - /*! - * Registers a foreign function found in a library. - * Just adds a LLVM global. - */ - debug!("register_foreign_item_fn(abi={}, \ ty={}, \ name={})", @@ -201,6 +197,20 @@ pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfn } +/// Prepares a call to a native function. This requires adapting +/// from the Rust argument passing rules to the native rules. +/// +/// # Parameters +/// +/// - `callee_ty`: Rust type for the function we are calling +/// - `llfn`: the function pointer we are calling +/// - `llretptr`: where to store the return value of the function +/// - `llargs_rust`: a list of the argument values, prepared +/// as they would be if calling a Rust function +/// - `passed_arg_tys`: Rust type for the arguments. Normally we +/// can derive these from callee_ty but in the case of variadic +/// functions passed_arg_tys will include the Rust type of all +/// the arguments including the ones not specified in the fn's signature. pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, callee_ty: Ty<'tcx>, llfn: ValueRef, @@ -208,23 +218,6 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llargs_rust: &[ValueRef], passed_arg_tys: Vec>) -> Block<'blk, 'tcx> { - /*! - * Prepares a call to a native function. This requires adapting - * from the Rust argument passing rules to the native rules. - * - * # Parameters - * - * - `callee_ty`: Rust type for the function we are calling - * - `llfn`: the function pointer we are calling - * - `llretptr`: where to store the return value of the function - * - `llargs_rust`: a list of the argument values, prepared - * as they would be if calling a Rust function - * - `passed_arg_tys`: Rust type for the arguments. Normally we - * can derive these from callee_ty but in the case of variadic - * functions passed_arg_tys will include the Rust type of all - * the arguments including the ones not specified in the fn's signature. - */ - let ccx = bcx.ccx(); let tcx = bcx.tcx(); @@ -832,17 +825,13 @@ pub fn link_name(i: &ast::ForeignItem) -> InternedString { } } +/// The ForeignSignature is the LLVM types of the arguments/return type of a function. Note that +/// these LLVM types are not quite the same as the LLVM types would be for a native Rust function +/// because foreign functions just plain ignore modes. They also don't pass aggregate values by +/// pointer like we do. fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_sig: &ty::FnSig<'tcx>, arg_tys: &[Ty<'tcx>]) -> LlvmSignature { - /*! - * The ForeignSignature is the LLVM types of the arguments/return type - * of a function. Note that these LLVM types are not quite the same - * as the LLVM types would be for a native Rust function because foreign - * functions just plain ignore modes. They also don't pass aggregate - * values by pointer like we do. - */ - let llarg_tys = arg_tys.iter().map(|&arg| arg_type_of(ccx, arg)).collect(); let (llret_ty, ret_def) = match fn_sig.output { ty::FnConverging(ret_ty) => diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 0ff7f3ee71c..06d916c1ea6 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -377,28 +377,21 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } + /// Creates a concatenated set of substitutions which includes those from the impl and those from + /// the method. This are some subtle complications here. Statically, we have a list of type + /// parameters like `[T0, T1, T2, M1, M2, M3]` where `Tn` are type parameters that appear on the + /// receiver. For example, if the receiver is a method parameter `A` with a bound like + /// `trait` then `Tn` would be `[B,C,D]`. + /// + /// The weird part is that the type `A` might now be bound to any other type, such as `foo`. + /// In that case, the vector we want is: `[X, M1, M2, M3]`. Therefore, what we do now is to slice + /// off the method type parameters and append them to the type parameters from the type that the + /// receiver is mapped to. fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, node: ExprOrMethodCall, rcvr_substs: subst::Substs<'tcx>) -> subst::Substs<'tcx> { - /*! - * Creates a concatenated set of substitutions which includes - * those from the impl and those from the method. This are - * some subtle complications here. Statically, we have a list - * of type parameters like `[T0, T1, T2, M1, M2, M3]` where - * `Tn` are type parameters that appear on the receiver. For - * example, if the receiver is a method parameter `A` with a - * bound like `trait` then `Tn` would be `[B,C,D]`. - * - * The weird part is that the type `A` might now be bound to - * any other type, such as `foo`. In that case, the vector - * we want is: `[X, M1, M2, M3]`. Therefore, what we do now is - * to slice off the method type parameters and append them to - * the type parameters from the type that the receiver is - * mapped to. - */ - let ccx = bcx.ccx(); let node_substs = node_id_substs(bcx, node); @@ -422,21 +415,16 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } +/// Create a method callee where the method is coming from a trait object (e.g., Box type). +/// In this case, we must pull the fn pointer out of the vtable that is packaged up with the +/// object. Objects are represented as a pair, so we first evaluate the self expression and then +/// extract the self data and vtable out of the pair. fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, method_ty: Ty<'tcx>, n_method: uint, self_expr: &ast::Expr, arg_cleanup_scope: cleanup::ScopeId) -> Callee<'blk, 'tcx> { - /*! - * Create a method callee where the method is coming from a trait - * object (e.g., Box type). In this case, we must pull the fn - * pointer out of the vtable that is packaged up with the object. - * Objects are represented as a pair, so we first evaluate the self - * expression and then extract the self data and vtable out of the - * pair. - */ - let _icx = push_ctxt("meth::trans_trait_callee"); let mut bcx = bcx; @@ -466,16 +454,13 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans_trait_callee_from_llval(bcx, method_ty, n_method, llval) } +/// Same as `trans_trait_callee()` above, except that it is given a by-ref pointer to the object +/// pair. pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, callee_ty: Ty<'tcx>, n_method: uint, llpair: ValueRef) -> Callee<'blk, 'tcx> { - /*! - * Same as `trans_trait_callee()` above, except that it is given - * a by-ref pointer to the object pair. - */ - let _icx = push_ctxt("meth::trans_trait_callee"); let ccx = bcx.ccx(); @@ -731,19 +716,15 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }).collect() } +/// Generates the code to convert from a pointer (`Box`, `&T`, etc) into an object +/// (`Box`, `&Trait`, etc). This means creating a pair where the first word is the vtable +/// and the second word is the pointer. pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, datum: Datum<'tcx, Expr>, id: ast::NodeId, trait_ref: Rc>, dest: expr::Dest) -> Block<'blk, 'tcx> { - /*! - * Generates the code to convert from a pointer (`Box`, `&T`, etc) - * into an object (`Box`, `&Trait`, etc). This means creating a - * pair where the first word is the vtable and the second word is - * the pointer. - */ - let mut bcx = bcx; let _icx = push_ctxt("meth::trans_trait_cast"); diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 8e986defb6a..9aeb4cdb8a3 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -134,17 +134,13 @@ pub fn trans_fixed_vstore<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; } +/// &[...] allocates memory on the stack and writes the values into it, returning the vector (the +/// caller must make the reference). "..." is similar except that the memory can be statically +/// allocated and we return a reference (strings are always by-ref). pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, slice_expr: &ast::Expr, content_expr: &ast::Expr) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * &[...] allocates memory on the stack and writes the values into it, - * returning the vector (the caller must make the reference). "..." is - * similar except that the memory can be statically allocated and we return - * a reference (strings are always by-ref). - */ - let fcx = bcx.fcx; let ccx = fcx.ccx; let mut bcx = bcx; @@ -208,17 +204,13 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, immediate_rvalue_bcx(bcx, llfixed, vec_ty).to_expr_datumblock() } +/// Literal strings translate to slices into static memory. This is different from +/// trans_slice_vstore() above because it doesn't need to copy the content anywhere. pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, lit_expr: &ast::Expr, str_lit: InternedString, dest: Dest) -> Block<'blk, 'tcx> { - /*! - * Literal strings translate to slices into static memory. This is - * different from trans_slice_vstore() above because it doesn't need to copy - * the content anywhere. - */ - debug!("trans_lit_str(lit_expr={}, dest={})", bcx.expr_to_string(lit_expr), dest.to_string(bcx.ccx())); @@ -382,15 +374,12 @@ pub fn elements_required(bcx: Block, content_expr: &ast::Expr) -> uint { } } +/// Converts a fixed-length vector into the slice pair. The vector should be stored in `llval` +/// which should be by ref. pub fn get_fixed_base_and_len(bcx: Block, llval: ValueRef, vec_length: uint) -> (ValueRef, ValueRef) { - /*! - * Converts a fixed-length vector into the slice pair. - * The vector should be stored in `llval` which should be by ref. - */ - let ccx = bcx.ccx(); let base = expr::get_dataptr(bcx, llval); @@ -406,18 +395,13 @@ fn get_slice_base_and_len(bcx: Block, (base, len) } +/// Converts a vector into the slice pair. The vector should be stored in `llval` which should be +/// by-reference. If you have a datum, you would probably prefer to call +/// `Datum::get_base_and_len()` which will handle any conversions for you. pub fn get_base_and_len(bcx: Block, llval: ValueRef, vec_ty: Ty) -> (ValueRef, ValueRef) { - /*! - * Converts a vector into the slice pair. The vector should be - * stored in `llval` which should be by-reference. If you have a - * datum, you would probably prefer to call - * `Datum::get_base_and_len()` which will handle any conversions - * for you. - */ - let ccx = bcx.ccx(); match vec_ty.sty { diff --git a/src/librustrt/c_str.rs b/src/librustrt/c_str.rs index d62b1485db3..261bd1b9f8c 100644 --- a/src/librustrt/c_str.rs +++ b/src/librustrt/c_str.rs @@ -8,68 +8,64 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -C-string manipulation and management - -This modules provides the basic methods for creating and manipulating -null-terminated strings for use with FFI calls (back to C). Most C APIs require -that the string being passed to them is null-terminated, and by default rust's -string types are *not* null terminated. - -The other problem with translating Rust strings to C strings is that Rust -strings can validly contain a null-byte in the middle of the string (0 is a -valid Unicode codepoint). This means that not all Rust strings can actually be -translated to C strings. - -# Creation of a C string - -A C string is managed through the `CString` type defined in this module. It -"owns" the internal buffer of characters and will automatically deallocate the -buffer when the string is dropped. The `ToCStr` trait is implemented for `&str` -and `&[u8]`, but the conversions can fail due to some of the limitations -explained above. - -This also means that currently whenever a C string is created, an allocation -must be performed to place the data elsewhere (the lifetime of the C string is -not tied to the lifetime of the original string/data buffer). If C strings are -heavily used in applications, then caching may be advisable to prevent -unnecessary amounts of allocations. - -Be carefull to remember that the memory is managed by C allocator API and not -by Rust allocator API. -That means that the CString pointers should be freed with C allocator API -if you intend to do that on your own, as the behaviour if you free them with -Rust's allocator API is not well defined - -An example of creating and using a C string would be: - -```rust -extern crate libc; - -extern { - fn puts(s: *const libc::c_char); -} - -fn main() { - let my_string = "Hello, world!"; - - // Allocate the C string with an explicit local that owns the string. The - // `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope. - let my_c_string = my_string.to_c_str(); - unsafe { - puts(my_c_string.as_ptr()); - } - - // Don't save/return the pointer to the C string, the `c_buffer` will be - // deallocated when this block returns! - my_string.with_c_str(|c_buffer| { - unsafe { puts(c_buffer); } - }); -} -``` - -*/ +//! C-string manipulation and management +//! +//! This modules provides the basic methods for creating and manipulating +//! null-terminated strings for use with FFI calls (back to C). Most C APIs require +//! that the string being passed to them is null-terminated, and by default rust's +//! string types are *not* null terminated. +//! +//! The other problem with translating Rust strings to C strings is that Rust +//! strings can validly contain a null-byte in the middle of the string (0 is a +//! valid Unicode codepoint). This means that not all Rust strings can actually be +//! translated to C strings. +//! +//! # Creation of a C string +//! +//! A C string is managed through the `CString` type defined in this module. It +//! "owns" the internal buffer of characters and will automatically deallocate the +//! buffer when the string is dropped. The `ToCStr` trait is implemented for `&str` +//! and `&[u8]`, but the conversions can fail due to some of the limitations +//! explained above. +//! +//! This also means that currently whenever a C string is created, an allocation +//! must be performed to place the data elsewhere (the lifetime of the C string is +//! not tied to the lifetime of the original string/data buffer). If C strings are +//! heavily used in applications, then caching may be advisable to prevent +//! unnecessary amounts of allocations. +//! +//! Be carefull to remember that the memory is managed by C allocator API and not +//! by Rust allocator API. +//! That means that the CString pointers should be freed with C allocator API +//! if you intend to do that on your own, as the behaviour if you free them with +//! Rust's allocator API is not well defined +//! +//! An example of creating and using a C string would be: +//! +//! ```rust +//! extern crate libc; +//! +//! extern { +//! fn puts(s: *const libc::c_char); +//! } +//! +//! fn main() { +//! let my_string = "Hello, world!"; +//! +//! // Allocate the C string with an explicit local that owns the string. The +//! // `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope. +//! let my_c_string = my_string.to_c_str(); +//! unsafe { +//! puts(my_c_string.as_ptr()); +//! } +//! +//! // Don't save/return the pointer to the C string, the `c_buffer` will be +//! // deallocated when this block returns! +//! my_string.with_c_str(|c_buffer| { +//! unsafe { puts(c_buffer); } +//! }); +//! } +//! ``` use collections::string::String; use collections::hash; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 4a2ca58fc92..3c03dc35f3b 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -14,185 +14,182 @@ #![forbid(non_camel_case_types)] #![allow(missing_docs)] -/*! -JSON parsing and serialization - -# What is JSON? - -JSON (JavaScript Object Notation) is a way to write data in Javascript. -Like XML, it allows to encode structured data in a text format that can be easily read by humans. -Its simple syntax and native compatibility with JavaScript have made it a widely used format. - -Data types that can be encoded are JavaScript types (see the `Json` enum for more details): - -* `Boolean`: equivalent to rust's `bool` -* `Number`: equivalent to rust's `f64` -* `String`: equivalent to rust's `String` -* `Array`: equivalent to rust's `Vec`, but also allowing objects of different types in the same -array -* `Object`: equivalent to rust's `Treemap` -* `Null` - -An object is a series of string keys mapping to values, in `"key": value` format. -Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }). -A simple JSON document encoding a person, his/her age, address and phone numbers could look like: - -```ignore -{ - "FirstName": "John", - "LastName": "Doe", - "Age": 43, - "Address": { - "Street": "Downing Street 10", - "City": "London", - "Country": "Great Britain" - }, - "PhoneNumbers": [ - "+44 1234567", - "+44 2345678" - ] -} -``` - -# Rust Type-based Encoding and Decoding - -Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via -the serialization API. -To be able to encode a piece of data, it must implement the `serialize::Encodable` trait. -To be able to decode a piece of data, it must implement the `serialize::Decodable` trait. -The Rust compiler provides an annotation to automatically generate the code for these traits: -`#[deriving(Decodable, Encodable)]` - -The JSON API provides an enum `json::Json` and a trait `ToJson` to encode objects. -The `ToJson` trait provides a `to_json` method to convert an object into a `json::Json` value. -A `json::Json` value can be encoded as a string or buffer using the functions described above. -You can also use the `json::Encoder` object, which implements the `Encoder` trait. - -When using `ToJson` the `Encodable` trait implementation is not mandatory. - -# Examples of use - -## Using Autoserialization - -Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the -serialization API, using the derived serialization code. - -```rust -extern crate serialize; -use serialize::json; - -// Automatically generate `Decodable` and `Encodable` trait implementations -#[deriving(Decodable, Encodable)] -pub struct TestStruct { - data_int: u8, - data_str: String, - data_vector: Vec, -} - -fn main() { - let object = TestStruct { - data_int: 1, - data_str: "toto".to_string(), - data_vector: vec![2,3,4,5], - }; - - // Serialize using `json::encode` - let encoded = json::encode(&object); - - // Deserialize using `json::decode` - let decoded: TestStruct = json::decode(encoded.as_slice()).unwrap(); -} -``` - -## Using the `ToJson` trait - -The examples above use the `ToJson` trait to generate the JSON string, which is required -for custom mappings. - -### Simple example of `ToJson` usage - -```rust -extern crate serialize; -use serialize::json::ToJson; -use serialize::json; - -// A custom data structure -struct ComplexNum { - a: f64, - b: f64, -} - -// JSON value representation -impl ToJson for ComplexNum { - fn to_json(&self) -> json::Json { - json::String(format!("{}+{}i", self.a, self.b)) - } -} - -// Only generate `Encodable` trait implementation -#[deriving(Encodable)] -pub struct ComplexNumRecord { - uid: u8, - dsc: String, - val: json::Json, -} - -fn main() { - let num = ComplexNum { a: 0.0001, b: 12.539 }; - let data: String = json::encode(&ComplexNumRecord{ - uid: 1, - dsc: "test".to_string(), - val: num.to_json(), - }); - println!("data: {}", data); - // data: {"uid":1,"dsc":"test","val":"0.0001+12.539j"}; -} -``` - -### Verbose example of `ToJson` usage - -```rust -extern crate serialize; -use std::collections::TreeMap; -use serialize::json::ToJson; -use serialize::json; - -// Only generate `Decodable` trait implementation -#[deriving(Decodable)] -pub struct TestStruct { - data_int: u8, - data_str: String, - data_vector: Vec, -} - -// Specify encoding method manually -impl ToJson for TestStruct { - fn to_json(&self) -> json::Json { - let mut d = TreeMap::new(); - // All standard types implement `to_json()`, so use it - d.insert("data_int".to_string(), self.data_int.to_json()); - d.insert("data_str".to_string(), self.data_str.to_json()); - d.insert("data_vector".to_string(), self.data_vector.to_json()); - json::Object(d) - } -} - -fn main() { - // Serialize using `ToJson` - let input_data = TestStruct { - data_int: 1, - data_str: "toto".to_string(), - data_vector: vec![2,3,4,5], - }; - let json_obj: json::Json = input_data.to_json(); - let json_str: String = json_obj.to_string(); - - // Deserialize like before - let decoded: TestStruct = json::decode(json_str.as_slice()).unwrap(); -} -``` - -*/ +//! JSON parsing and serialization +//! +//! # What is JSON? +//! +//! JSON (JavaScript Object Notation) is a way to write data in Javascript. +//! Like XML, it allows to encode structured data in a text format that can be easily read by humans +//! Its simple syntax and native compatibility with JavaScript have made it a widely used format. +//! +//! Data types that can be encoded are JavaScript types (see the `Json` enum for more details): +//! +//! * `Boolean`: equivalent to rust's `bool` +//! * `Number`: equivalent to rust's `f64` +//! * `String`: equivalent to rust's `String` +//! * `Array`: equivalent to rust's `Vec`, but also allowing objects of different types in the +//! same array +//! * `Object`: equivalent to rust's `Treemap` +//! * `Null` +//! +//! An object is a series of string keys mapping to values, in `"key": value` format. +//! Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }). +//! A simple JSON document encoding a person, his/her age, address and phone numbers could look like +//! +//! ```ignore +//! { +//! "FirstName": "John", +//! "LastName": "Doe", +//! "Age": 43, +//! "Address": { +//! "Street": "Downing Street 10", +//! "City": "London", +//! "Country": "Great Britain" +//! }, +//! "PhoneNumbers": [ +//! "+44 1234567", +//! "+44 2345678" +//! ] +//! } +//! ``` +//! +//! # Rust Type-based Encoding and Decoding +//! +//! Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via +//! the serialization API. +//! To be able to encode a piece of data, it must implement the `serialize::Encodable` trait. +//! To be able to decode a piece of data, it must implement the `serialize::Decodable` trait. +//! The Rust compiler provides an annotation to automatically generate the code for these traits: +//! `#[deriving(Decodable, Encodable)]` +//! +//! The JSON API provides an enum `json::Json` and a trait `ToJson` to encode objects. +//! The `ToJson` trait provides a `to_json` method to convert an object into a `json::Json` value. +//! A `json::Json` value can be encoded as a string or buffer using the functions described above. +//! You can also use the `json::Encoder` object, which implements the `Encoder` trait. +//! +//! When using `ToJson` the `Encodable` trait implementation is not mandatory. +//! +//! # Examples of use +//! +//! ## Using Autoserialization +//! +//! Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the +//! serialization API, using the derived serialization code. +//! +//! ```rust +//! extern crate serialize; +//! use serialize::json; +//! +//! // Automatically generate `Decodable` and `Encodable` trait implementations +//! #[deriving(Decodable, Encodable)] +//! pub struct TestStruct { +//! data_int: u8, +//! data_str: String, +//! data_vector: Vec, +//! } +//! +//! fn main() { +//! let object = TestStruct { +//! data_int: 1, +//! data_str: "toto".to_string(), +//! data_vector: vec![2,3,4,5], +//! }; +//! +//! // Serialize using `json::encode` +//! let encoded = json::encode(&object); +//! +//! // Deserialize using `json::decode` +//! let decoded: TestStruct = json::decode(encoded.as_slice()).unwrap(); +//! } +//! ``` +//! +//! ## Using the `ToJson` trait +//! +//! The examples above use the `ToJson` trait to generate the JSON string, which is required +//! for custom mappings. +//! +//! ### Simple example of `ToJson` usage +//! +//! ```rust +//! extern crate serialize; +//! use serialize::json::ToJson; +//! use serialize::json; +//! +//! // A custom data structure +//! struct ComplexNum { +//! a: f64, +//! b: f64, +//! } +//! +//! // JSON value representation +//! impl ToJson for ComplexNum { +//! fn to_json(&self) -> json::Json { +//! json::String(format!("{}+{}i", self.a, self.b)) +//! } +//! } +//! +//! // Only generate `Encodable` trait implementation +//! #[deriving(Encodable)] +//! pub struct ComplexNumRecord { +//! uid: u8, +//! dsc: String, +//! val: json::Json, +//! } +//! +//! fn main() { +//! let num = ComplexNum { a: 0.0001, b: 12.539 }; +//! let data: String = json::encode(&ComplexNumRecord{ +//! uid: 1, +//! dsc: "test".to_string(), +//! val: num.to_json(), +//! }); +//! println!("data: {}", data); +//! // data: {"uid":1,"dsc":"test","val":"0.0001+12.539j"}; +//! } +//! ``` +//! +//! ### Verbose example of `ToJson` usage +//! +//! ```rust +//! extern crate serialize; +//! use std::collections::TreeMap; +//! use serialize::json::ToJson; +//! use serialize::json; +//! +//! // Only generate `Decodable` trait implementation +//! #[deriving(Decodable)] +//! pub struct TestStruct { +//! data_int: u8, +//! data_str: String, +//! data_vector: Vec, +//! } +//! +//! // Specify encoding method manually +//! impl ToJson for TestStruct { +//! fn to_json(&self) -> json::Json { +//! let mut d = TreeMap::new(); +//! // All standard types implement `to_json()`, so use it +//! d.insert("data_int".to_string(), self.data_int.to_json()); +//! d.insert("data_str".to_string(), self.data_str.to_json()); +//! d.insert("data_vector".to_string(), self.data_vector.to_json()); +//! json::Object(d) +//! } +//! } +//! +//! fn main() { +//! // Serialize using `ToJson` +//! let input_data = TestStruct { +//! data_int: 1, +//! data_str: "toto".to_string(), +//! data_vector: vec![2,3,4,5], +//! }; +//! let json_obj: json::Json = input_data.to_json(); +//! let json_str: String = json_obj.to_string(); +//! +//! // Deserialize like before +//! let decoded: TestStruct = json::decode(json_str.as_slice()).unwrap(); +//! } +//! ``` pub use self::JsonEvent::*; pub use self::StackElement::*; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 4b868f6a95b..3cd0c0eeaf2 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -8,13 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Dynamic library facilities. - -A simple wrapper over the platform's dynamic library facilities - -*/ +//! Dynamic library facilities. +//! +//! A simple wrapper over the platform's dynamic library facilities #![experimental] #![allow(missing_docs)] diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index c817e6a806b..62ca3483c21 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -10,392 +10,388 @@ // // ignore-lexer-test FIXME #15679 -/*! - -Utilities for formatting and printing strings - -This module contains the runtime support for the `format!` syntax extension. -This macro is implemented in the compiler to emit calls to this module in order -to format arguments at runtime into strings and streams. - -The functions contained in this module should not normally be used in everyday -use cases of `format!`. The assumptions made by these functions are unsafe for -all inputs, and the compiler performs a large amount of validation on the -arguments to `format!` in order to ensure safety at runtime. While it is -possible to call these functions directly, it is not recommended to do so in the -general case. - -## Usage - -The `format!` macro is intended to be familiar to those coming from C's -printf/fprintf functions or Python's `str.format` function. In its current -revision, the `format!` macro returns a `String` type which is the result of -the formatting. In the future it will also be able to pass in a stream to -format arguments directly while performing minimal allocations. - -Some examples of the `format!` extension are: - -```rust -# fn main() { -format!("Hello"); // => "Hello" -format!("Hello, {}!", "world"); // => "Hello, world!" -format!("The number is {}", 1i); // => "The number is 1" -format!("{}", (3i, 4i)); // => "(3, 4)" -format!("{value}", value=4i); // => "4" -format!("{} {}", 1i, 2u); // => "1 2" -# } -``` - -From these, you can see that the first argument is a format string. It is -required by the compiler for this to be a string literal; it cannot be a -variable passed in (in order to perform validity checking). The compiler will -then parse the format string and determine if the list of arguments provided is -suitable to pass to this format string. - -### Positional parameters - -Each formatting argument is allowed to specify which value argument it's -referencing, and if omitted it is assumed to be "the next argument". For -example, the format string `{} {} {}` would take three parameters, and they -would be formatted in the same order as they're given. The format string -`{2} {1} {0}`, however, would format arguments in reverse order. - -Things can get a little tricky once you start intermingling the two types of -positional specifiers. The "next argument" specifier can be thought of as an -iterator over the argument. Each time a "next argument" specifier is seen, the -iterator advances. This leads to behavior like this: - -```rust -format!("{1} {} {0} {}", 1i, 2i); // => "2 1 1 2" -``` - -The internal iterator over the argument has not been advanced by the time the -first `{}` is seen, so it prints the first argument. Then upon reaching the -second `{}`, the iterator has advanced forward to the second argument. -Essentially, parameters which explicitly name their argument do not affect -parameters which do not name an argument in terms of positional specifiers. - -A format string is required to use all of its arguments, otherwise it is a -compile-time error. You may refer to the same argument more than once in the -format string, although it must always be referred to with the same type. - -### Named parameters - -Rust itself does not have a Python-like equivalent of named parameters to a -function, but the `format!` macro is a syntax extension which allows it to -leverage named parameters. Named parameters are listed at the end of the -argument list and have the syntax: - -```text -identifier '=' expression -``` - -For example, the following `format!` expressions all use named argument: - -```rust -# fn main() { -format!("{argument}", argument = "test"); // => "test" -format!("{name} {}", 1i, name = 2i); // => "2 1" -format!("{a} {c} {b}", a="a", b=(), c=3i); // => "a 3 ()" -# } -``` - -It is illegal to put positional parameters (those without names) after arguments -which have names. Like with positional parameters, it is illegal to provide -named parameters that are unused by the format string. - -### Argument types - -Each argument's type is dictated by the format string. It is a requirement that every argument is -only ever referred to by one type. For example, this is an invalid format string: - -```text -{0:x} {0:o} -``` - -This is invalid because the first argument is both referred to as a hexidecimal as well as an -octal. - -There are various parameters which do require a particular type, however. Namely if the syntax -`{:.*}` is used, then the number of characters to print precedes the actual object being formatted, -and the number of characters must have the type `uint`. Although a `uint` can be printed with -`{}`, it is illegal to reference an argument as such. For example this is another invalid -format string: - -```text -{:.*} {0} -``` - -### Formatting traits - -When requesting that an argument be formatted with a particular type, you are -actually requesting that an argument ascribes to a particular trait. This allows -multiple actual types to be formatted via `{:x}` (like `i8` as well as `int`). -The current mapping of types to traits is: - -* *nothing* ⇒ `Show` -* `o` ⇒ `Octal` -* `x` ⇒ `LowerHex` -* `X` ⇒ `UpperHex` -* `p` ⇒ `Pointer` -* `b` ⇒ `Binary` -* `e` ⇒ `LowerExp` -* `E` ⇒ `UpperExp` - -What this means is that any type of argument which implements the -`std::fmt::Binary` trait can then be formatted with `{:b}`. Implementations are -provided for these traits for a number of primitive types by the standard -library as well. If no format is specified (as in `{}` or `{:6}`), then the -format trait used is the `Show` trait. This is one of the more commonly -implemented traits when formatting a custom type. - -When implementing a format trait for your own type, you will have to implement a -method of the signature: - -```rust -# use std::fmt; -# struct Foo; // our custom type -# impl fmt::Show for Foo { -fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result { -# write!(f, "testing, testing") -# } } -``` - -Your type will be passed as `self` by-reference, and then the function should -emit output into the `f.buf` stream. It is up to each format trait -implementation to correctly adhere to the requested formatting parameters. The -values of these parameters will be listed in the fields of the `Formatter` -struct. In order to help with this, the `Formatter` struct also provides some -helper methods. - -Additionally, the return value of this function is `fmt::Result` which is a -typedef to `Result<(), IoError>` (also known as `IoResult<()>`). Formatting -implementations should ensure that they return errors from `write!` correctly -(propagating errors upward). - -An example of implementing the formatting traits would look -like: - -```rust -use std::fmt; -use std::f64; -use std::num::Float; - -struct Vector2D { - x: int, - y: int, -} - -impl fmt::Show for Vector2D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // The `f` value implements the `Writer` trait, which is what the - // write! macro is expecting. Note that this formatting ignores the - // various flags provided to format strings. - write!(f, "({}, {})", self.x, self.y) - } -} - -// Different traits allow different forms of output of a type. The meaning of -// this format is to print the magnitude of a vector. -impl fmt::Binary for Vector2D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let magnitude = (self.x * self.x + self.y * self.y) as f64; - let magnitude = magnitude.sqrt(); - - // Respect the formatting flags by using the helper method - // `pad_integral` on the Formatter object. See the method documentation - // for details, and the function `pad` can be used to pad strings. - let decimals = f.precision().unwrap_or(3); - let string = f64::to_str_exact(magnitude, decimals); - f.pad_integral(true, "", string.as_bytes()) - } -} - -fn main() { - let myvector = Vector2D { x: 3, y: 4 }; - - println!("{}", myvector); // => "(3, 4)" - println!("{:10.3b}", myvector); // => " 5.000" -} -``` - -### Related macros - -There are a number of related macros in the `format!` family. The ones that are -currently implemented are: - -```ignore -format! // described above -write! // first argument is a &mut io::Writer, the destination -writeln! // same as write but appends a newline -print! // the format string is printed to the standard output -println! // same as print but appends a newline -format_args! // described below. -``` - -#### `write!` - -This and `writeln` are two macros which are used to emit the format string to a -specified stream. This is used to prevent intermediate allocations of format -strings and instead directly write the output. Under the hood, this function is -actually invoking the `write` function defined in this module. Example usage is: - -```rust -# #![allow(unused_must_use)] -use std::io; - -let mut w = Vec::new(); -write!(&mut w as &mut io::Writer, "Hello {}!", "world"); -``` - -#### `print!` - -This and `println` emit their output to stdout. Similarly to the `write!` macro, -the goal of these macros is to avoid intermediate allocations when printing -output. Example usage is: - -```rust -print!("Hello {}!", "world"); -println!("I have a newline {}", "character at the end"); -``` - -#### `format_args!` -This is a curious macro which is used to safely pass around -an opaque object describing the format string. This object -does not require any heap allocations to create, and it only -references information on the stack. Under the hood, all of -the related macros are implemented in terms of this. First -off, some example usage is: - -``` -use std::fmt; -use std::io; - -# #[allow(unused_must_use)] -# fn main() { -format_args!(fmt::format, "this returns {}", "String"); - -let some_writer: &mut io::Writer = &mut io::stdout(); -format_args!(|args| { write!(some_writer, "{}", args) }, "print with a {}", "closure"); - -fn my_fmt_fn(args: &fmt::Arguments) { - write!(&mut io::stdout(), "{}", args); -} -format_args!(my_fmt_fn, "or a {} too", "function"); -# } -``` - -The first argument of the `format_args!` macro is a function (or closure) which -takes one argument of type `&fmt::Arguments`. This structure can then be -passed to the `write` and `format` functions inside this module in order to -process the format string. The goal of this macro is to even further prevent -intermediate allocations when dealing formatting strings. - -For example, a logging library could use the standard formatting syntax, but it -would internally pass around this structure until it has been determined where -output should go to. - -It is unsafe to programmatically create an instance of `fmt::Arguments` because -the operations performed when executing a format string require the compile-time -checks provided by the compiler. The `format_args!` macro is the only method of -safely creating these structures, but they can be unsafely created with the -constructor provided. - -## Syntax - -The syntax for the formatting language used is drawn from other languages, so it -should not be too alien. Arguments are formatted with python-like syntax, -meaning that arguments are surrounded by `{}` instead of the C-like `%`. The -actual grammar for the formatting syntax is: - -```text -format_string := [ format ] * -format := '{' [ argument ] [ ':' format_spec ] '}' -argument := integer | identifier - -format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type] -fill := character -align := '<' | '^' | '>' -sign := '+' | '-' -width := count -precision := count | '*' -type := identifier | '' -count := parameter | integer -parameter := integer '$' -``` - -## Formatting Parameters - -Each argument being formatted can be transformed by a number of formatting -parameters (corresponding to `format_spec` in the syntax above). These -parameters affect the string representation of what's being formatted. This -syntax draws heavily from Python's, so it may seem a bit familiar. - -### Fill/Alignment - -The fill character is provided normally in conjunction with the `width` -parameter. This indicates that if the value being formatted is smaller than -`width` some extra characters will be printed around it. The extra characters -are specified by `fill`, and the alignment can be one of two options: - -* `<` - the argument is left-aligned in `width` columns -* `^` - the argument is center-aligned in `width` columns -* `>` - the argument is right-aligned in `width` columns - -### Sign/#/0 - -These can all be interpreted as flags for a particular formatter. - -* '+' - This is intended for numeric types and indicates that the sign should - always be printed. Positive signs are never printed by default, and the - negative sign is only printed by default for the `Signed` trait. This - flag indicates that the correct sign (+ or -) should always be printed. -* '-' - Currently not used -* '#' - This flag is indicates that the "alternate" form of printing should be - used. By default, this only applies to the integer formatting traits and - performs like: - * `x` - precedes the argument with a "0x" - * `X` - precedes the argument with a "0x" - * `t` - precedes the argument with a "0b" - * `o` - precedes the argument with a "0o" -* '0' - This is used to indicate for integer formats that the padding should - both be done with a `0` character as well as be sign-aware. A format - like `{:08d}` would yield `00000001` for the integer `1`, while the same - format would yield `-0000001` for the integer `-1`. Notice that the - negative version has one fewer zero than the positive version. - -### Width - -This is a parameter for the "minimum width" that the format should take up. If -the value's string does not fill up this many characters, then the padding -specified by fill/alignment will be used to take up the required space. - -The default fill/alignment for non-numerics is a space and left-aligned. The -defaults for numeric formatters is also a space but with right-alignment. If the -'0' flag is specified for numerics, then the implicit fill character is '0'. - -The value for the width can also be provided as a `uint` in the list of -parameters by using the `2$` syntax indicating that the second argument is a -`uint` specifying the width. - -### Precision - -For non-numeric types, this can be considered a "maximum width". If the -resulting string is longer than this width, then it is truncated down to this -many characters and only those are emitted. - -For integral types, this has no meaning currently. - -For floating-point types, this indicates how many digits after the decimal point -should be printed. - -## Escaping - -The literal characters `{` and `}` may be included in a string by preceding them -with the same character. For example, the `{` character is escaped with `{{` and -the `}` character is escaped with `}}`. - -*/ +//! Utilities for formatting and printing strings +//! +//! This module contains the runtime support for the `format!` syntax extension. +//! This macro is implemented in the compiler to emit calls to this module in order +//! to format arguments at runtime into strings and streams. +//! +//! The functions contained in this module should not normally be used in everyday +//! use cases of `format!`. The assumptions made by these functions are unsafe for +//! all inputs, and the compiler performs a large amount of validation on the +//! arguments to `format!` in order to ensure safety at runtime. While it is +//! possible to call these functions directly, it is not recommended to do so in the +//! general case. +//! +//! ## Usage +//! +//! The `format!` macro is intended to be familiar to those coming from C's +//! printf/fprintf functions or Python's `str.format` function. In its current +//! revision, the `format!` macro returns a `String` type which is the result of +//! the formatting. In the future it will also be able to pass in a stream to +//! format arguments directly while performing minimal allocations. +//! +//! Some examples of the `format!` extension are: +//! +//! ```rust +//! # fn main() { +//! format!("Hello"); // => "Hello" +//! format!("Hello, {}!", "world"); // => "Hello, world!" +//! format!("The number is {}", 1i); // => "The number is 1" +//! format!("{}", (3i, 4i)); // => "(3, 4)" +//! format!("{value}", value=4i); // => "4" +//! format!("{} {}", 1i, 2u); // => "1 2" +//! # } +//! ``` +//! +//! From these, you can see that the first argument is a format string. It is +//! required by the compiler for this to be a string literal; it cannot be a +//! variable passed in (in order to perform validity checking). The compiler will +//! then parse the format string and determine if the list of arguments provided is +//! suitable to pass to this format string. +//! +//! ### Positional parameters +//! +//! Each formatting argument is allowed to specify which value argument it's +//! referencing, and if omitted it is assumed to be "the next argument". For +//! example, the format string `{} {} {}` would take three parameters, and they +//! would be formatted in the same order as they're given. The format string +//! `{2} {1} {0}`, however, would format arguments in reverse order. +//! +//! Things can get a little tricky once you start intermingling the two types of +//! positional specifiers. The "next argument" specifier can be thought of as an +//! iterator over the argument. Each time a "next argument" specifier is seen, the +//! iterator advances. This leads to behavior like this: +//! +//! ```rust +//! format!("{1} {} {0} {}", 1i, 2i); // => "2 1 1 2" +//! ``` +//! +//! The internal iterator over the argument has not been advanced by the time the +//! first `{}` is seen, so it prints the first argument. Then upon reaching the +//! second `{}`, the iterator has advanced forward to the second argument. +//! Essentially, parameters which explicitly name their argument do not affect +//! parameters which do not name an argument in terms of positional specifiers. +//! +//! A format string is required to use all of its arguments, otherwise it is a +//! compile-time error. You may refer to the same argument more than once in the +//! format string, although it must always be referred to with the same type. +//! +//! ### Named parameters +//! +//! Rust itself does not have a Python-like equivalent of named parameters to a +//! function, but the `format!` macro is a syntax extension which allows it to +//! leverage named parameters. Named parameters are listed at the end of the +//! argument list and have the syntax: +//! +//! ```text +//! identifier '=' expression +//! ``` +//! +//! For example, the following `format!` expressions all use named argument: +//! +//! ```rust +//! # fn main() { +//! format!("{argument}", argument = "test"); // => "test" +//! format!("{name} {}", 1i, name = 2i); // => "2 1" +//! format!("{a} {c} {b}", a="a", b=(), c=3i); // => "a 3 ()" +//! # } +//! ``` +//! +//! It is illegal to put positional parameters (those without names) after arguments +//! which have names. Like with positional parameters, it is illegal to provide +//! named parameters that are unused by the format string. +//! +//! ### Argument types +//! +//! Each argument's type is dictated by the format string. It is a requirement that every argument is +//! only ever referred to by one type. For example, this is an invalid format string: +//! +//! ```text +//! {0:x} {0:o} +//! ``` +//! +//! This is invalid because the first argument is both referred to as a hexidecimal as well as an +//! octal. +//! +//! There are various parameters which do require a particular type, however. Namely if the syntax +//! `{:.*}` is used, then the number of characters to print precedes the actual object being formatted, +//! and the number of characters must have the type `uint`. Although a `uint` can be printed with +//! `{}`, it is illegal to reference an argument as such. For example this is another invalid +//! format string: +//! +//! ```text +//! {:.*} {0} +//! ``` +//! +//! ### Formatting traits +//! +//! When requesting that an argument be formatted with a particular type, you are +//! actually requesting that an argument ascribes to a particular trait. This allows +//! multiple actual types to be formatted via `{:x}` (like `i8` as well as `int`). +//! The current mapping of types to traits is: +//! +//! * *nothing* ⇒ `Show` +//! * `o` ⇒ `Octal` +//! * `x` ⇒ `LowerHex` +//! * `X` ⇒ `UpperHex` +//! * `p` ⇒ `Pointer` +//! * `b` ⇒ `Binary` +//! * `e` ⇒ `LowerExp` +//! * `E` ⇒ `UpperExp` +//! +//! What this means is that any type of argument which implements the +//! `std::fmt::Binary` trait can then be formatted with `{:b}`. Implementations are +//! provided for these traits for a number of primitive types by the standard +//! library as well. If no format is specified (as in `{}` or `{:6}`), then the +//! format trait used is the `Show` trait. This is one of the more commonly +//! implemented traits when formatting a custom type. +//! +//! When implementing a format trait for your own type, you will have to implement a +//! method of the signature: +//! +//! ```rust +//! # use std::fmt; +//! # struct Foo; // our custom type +//! # impl fmt::Show for Foo { +//! fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result { +//! # write!(f, "testing, testing") +//! # } } +//! ``` +//! +//! Your type will be passed as `self` by-reference, and then the function should +//! emit output into the `f.buf` stream. It is up to each format trait +//! implementation to correctly adhere to the requested formatting parameters. The +//! values of these parameters will be listed in the fields of the `Formatter` +//! struct. In order to help with this, the `Formatter` struct also provides some +//! helper methods. +//! +//! Additionally, the return value of this function is `fmt::Result` which is a +//! typedef to `Result<(), IoError>` (also known as `IoResult<()>`). Formatting +//! implementations should ensure that they return errors from `write!` correctly +//! (propagating errors upward). +//! +//! An example of implementing the formatting traits would look +//! like: +//! +//! ```rust +//! use std::fmt; +//! use std::f64; +//! use std::num::Float; +//! +//! struct Vector2D { +//! x: int, +//! y: int, +//! } +//! +//! impl fmt::Show for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! // The `f` value implements the `Writer` trait, which is what the +//! // write! macro is expecting. Note that this formatting ignores the +//! // various flags provided to format strings. +//! write!(f, "({}, {})", self.x, self.y) +//! } +//! } +//! +//! // Different traits allow different forms of output of a type. The meaning of +//! // this format is to print the magnitude of a vector. +//! impl fmt::Binary for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! let magnitude = (self.x * self.x + self.y * self.y) as f64; +//! let magnitude = magnitude.sqrt(); +//! +//! // Respect the formatting flags by using the helper method +//! // `pad_integral` on the Formatter object. See the method documentation +//! // for details, and the function `pad` can be used to pad strings. +//! let decimals = f.precision().unwrap_or(3); +//! let string = f64::to_str_exact(magnitude, decimals); +//! f.pad_integral(true, "", string.as_bytes()) +//! } +//! } +//! +//! fn main() { +//! let myvector = Vector2D { x: 3, y: 4 }; +//! +//! println!("{}", myvector); // => "(3, 4)" +//! println!("{:10.3b}", myvector); // => " 5.000" +//! } +//! ``` +//! +//! ### Related macros +//! +//! There are a number of related macros in the `format!` family. The ones that are +//! currently implemented are: +//! +//! ```ignore +//! format! // described above +//! write! // first argument is a &mut io::Writer, the destination +//! writeln! // same as write but appends a newline +//! print! // the format string is printed to the standard output +//! println! // same as print but appends a newline +//! format_args! // described below. +//! ``` +//! +//! #### `write!` +//! +//! This and `writeln` are two macros which are used to emit the format string to a +//! specified stream. This is used to prevent intermediate allocations of format +//! strings and instead directly write the output. Under the hood, this function is +//! actually invoking the `write` function defined in this module. Example usage is: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::io; +//! +//! let mut w = Vec::new(); +//! write!(&mut w as &mut io::Writer, "Hello {}!", "world"); +//! ``` +//! +//! #### `print!` +//! +//! This and `println` emit their output to stdout. Similarly to the `write!` macro, +//! the goal of these macros is to avoid intermediate allocations when printing +//! output. Example usage is: +//! +//! ```rust +//! print!("Hello {}!", "world"); +//! println!("I have a newline {}", "character at the end"); +//! ``` +//! +//! #### `format_args!` +//! This is a curious macro which is used to safely pass around +//! an opaque object describing the format string. This object +//! does not require any heap allocations to create, and it only +//! references information on the stack. Under the hood, all of +//! the related macros are implemented in terms of this. First +//! off, some example usage is: +//! +//! ``` +//! use std::fmt; +//! use std::io; +//! +//! # #[allow(unused_must_use)] +//! # fn main() { +//! format_args!(fmt::format, "this returns {}", "String"); +//! +//! let some_writer: &mut io::Writer = &mut io::stdout(); +//! format_args!(|args| { write!(some_writer, "{}", args) }, "print with a {}", "closure"); +//! +//! fn my_fmt_fn(args: &fmt::Arguments) { +//! write!(&mut io::stdout(), "{}", args); +//! } +//! format_args!(my_fmt_fn, "or a {} too", "function"); +//! # } +//! ``` +//! +//! The first argument of the `format_args!` macro is a function (or closure) which +//! takes one argument of type `&fmt::Arguments`. This structure can then be +//! passed to the `write` and `format` functions inside this module in order to +//! process the format string. The goal of this macro is to even further prevent +//! intermediate allocations when dealing formatting strings. +//! +//! For example, a logging library could use the standard formatting syntax, but it +//! would internally pass around this structure until it has been determined where +//! output should go to. +//! +//! It is unsafe to programmatically create an instance of `fmt::Arguments` because +//! the operations performed when executing a format string require the compile-time +//! checks provided by the compiler. The `format_args!` macro is the only method of +//! safely creating these structures, but they can be unsafely created with the +//! constructor provided. +//! +//! ## Syntax +//! +//! The syntax for the formatting language used is drawn from other languages, so it +//! should not be too alien. Arguments are formatted with python-like syntax, +//! meaning that arguments are surrounded by `{}` instead of the C-like `%`. The +//! actual grammar for the formatting syntax is: +//! +//! ```text +//! format_string := [ format ] * +//! format := '{' [ argument ] [ ':' format_spec ] '}' +//! argument := integer | identifier +//! +//! format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type] +//! fill := character +//! align := '<' | '^' | '>' +//! sign := '+' | '-' +//! width := count +//! precision := count | '*' +//! type := identifier | '' +//! count := parameter | integer +//! parameter := integer '$' +//! ``` +//! +//! ## Formatting Parameters +//! +//! Each argument being formatted can be transformed by a number of formatting +//! parameters (corresponding to `format_spec` in the syntax above). These +//! parameters affect the string representation of what's being formatted. This +//! syntax draws heavily from Python's, so it may seem a bit familiar. +//! +//! ### Fill/Alignment +//! +//! The fill character is provided normally in conjunction with the `width` +//! parameter. This indicates that if the value being formatted is smaller than +//! `width` some extra characters will be printed around it. The extra characters +//! are specified by `fill`, and the alignment can be one of two options: +//! +//! * `<` - the argument is left-aligned in `width` columns +//! * `^` - the argument is center-aligned in `width` columns +//! * `>` - the argument is right-aligned in `width` columns +//! +//! ### Sign/#/0 +//! +//! These can all be interpreted as flags for a particular formatter. +//! +//! * '+' - This is intended for numeric types and indicates that the sign should +//! always be printed. Positive signs are never printed by default, and the +//! negative sign is only printed by default for the `Signed` trait. This +//! flag indicates that the correct sign (+ or -) should always be printed. +//! * '-' - Currently not used +//! * '#' - This flag is indicates that the "alternate" form of printing should be +//! used. By default, this only applies to the integer formatting traits and +//! performs like: +//! * `x` - precedes the argument with a "0x" +//! * `X` - precedes the argument with a "0x" +//! * `t` - precedes the argument with a "0b" +//! * `o` - precedes the argument with a "0o" +//! * '0' - This is used to indicate for integer formats that the padding should +//! both be done with a `0` character as well as be sign-aware. A format +//! like `{:08d}` would yield `00000001` for the integer `1`, while the same +//! format would yield `-0000001` for the integer `-1`. Notice that the +//! negative version has one fewer zero than the positive version. +//! +//! ### Width +//! +//! This is a parameter for the "minimum width" that the format should take up. If +//! the value's string does not fill up this many characters, then the padding +//! specified by fill/alignment will be used to take up the required space. +//! +//! The default fill/alignment for non-numerics is a space and left-aligned. The +//! defaults for numeric formatters is also a space but with right-alignment. If the +//! '0' flag is specified for numerics, then the implicit fill character is '0'. +//! +//! The value for the width can also be provided as a `uint` in the list of +//! parameters by using the `2$` syntax indicating that the second argument is a +//! `uint` specifying the width. +//! +//! ### Precision +//! +//! For non-numeric types, this can be considered a "maximum width". If the +//! resulting string is longer than this width, then it is truncated down to this +//! many characters and only those are emitted. +//! +//! For integral types, this has no meaning currently. +//! +//! For floating-point types, this indicates how many digits after the decimal point +//! should be printed. +//! +//! ## Escaping +//! +//! The literal characters `{` and `}` may be included in a string by preceding them +//! with the same character. For example, the `{` character is escaped with `{{` and +//! the `}` character is escaped with `}}`. #![experimental] diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index e4017ea5a47..ac68e1ef121 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -8,58 +8,56 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Generic hashing support. - * - * This module provides a generic way to compute the hash of a value. The - * simplest way to make a type hashable is to use `#[deriving(Hash)]`: - * - * # Example - * - * ```rust - * use std::hash; - * use std::hash::Hash; - * - * #[deriving(Hash)] - * struct Person { - * id: uint, - * name: String, - * phone: u64, - * } - * - * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; - * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; - * - * assert!(hash::hash(&person1) != hash::hash(&person2)); - * ``` - * - * If you need more control over how a value is hashed, you need to implement - * the trait `Hash`: - * - * ```rust - * use std::hash; - * use std::hash::Hash; - * use std::hash::sip::SipState; - * - * struct Person { - * id: uint, - * name: String, - * phone: u64, - * } - * - * impl Hash for Person { - * fn hash(&self, state: &mut SipState) { - * self.id.hash(state); - * self.phone.hash(state); - * } - * } - * - * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; - * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; - * - * assert!(hash::hash(&person1) == hash::hash(&person2)); - * ``` - */ +//! Generic hashing support. +//! +//! This module provides a generic way to compute the hash of a value. The +//! simplest way to make a type hashable is to use `#[deriving(Hash)]`: +//! +//! # Example +//! +//! ```rust +//! use std::hash; +//! use std::hash::Hash; +//! +//! #[deriving(Hash)] +//! struct Person { +//! id: uint, +//! name: String, +//! phone: u64, +//! } +//! +//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; +//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; +//! +//! assert!(hash::hash(&person1) != hash::hash(&person2)); +//! ``` +//! +//! If you need more control over how a value is hashed, you need to implement +//! the trait `Hash`: +//! +//! ```rust +//! use std::hash; +//! use std::hash::Hash; +//! use std::hash::sip::SipState; +//! +//! struct Person { +//! id: uint, +//! name: String, +//! phone: u64, +//! } +//! +//! impl Hash for Person { +//! fn hash(&self, state: &mut SipState) { +//! self.id.hash(state); +//! self.phone.hash(state); +//! } +//! } +//! +//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 }; +//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 }; +//! +//! assert!(hash::hash(&person1) == hash::hash(&person2)); +//! ``` #![experimental] diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 6d29f3d2538..da69cee69e6 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -10,47 +10,45 @@ // // ignore-lexer-test FIXME #15679 -/*! Synchronous File I/O - -This module provides a set of functions and traits for working -with regular files & directories on a filesystem. - -At the top-level of the module are a set of freestanding functions, associated -with various filesystem operations. They all operate on `Path` objects. - -All operations in this module, including those as part of `File` et al -block the task during execution. In the event of failure, all functions/methods -will return an `IoResult` type with an `Err` value. - -Also included in this module is an implementation block on the `Path` object -defined in `std::path::Path`. The impl adds useful methods about inspecting the -metadata of a file. This includes getting the `stat` information, reading off -particular bits of it, etc. - -# Example - -```rust -# #![allow(unused_must_use)] -use std::io::fs::PathExtensions; -use std::io::{File, fs}; - -let path = Path::new("foo.txt"); - -// create the file, whether it exists or not -let mut file = File::create(&path); -file.write(b"foobar"); -# drop(file); - -// open the file in read-only mode -let mut file = File::open(&path); -file.read_to_end(); - -println!("{}", path.stat().unwrap().size); -# drop(file); -fs::unlink(&path); -``` - -*/ +//! Synchronous File I/O +//! +//! This module provides a set of functions and traits for working +//! with regular files & directories on a filesystem. +//! +//! At the top-level of the module are a set of freestanding functions, associated +//! with various filesystem operations. They all operate on `Path` objects. +//! +//! All operations in this module, including those as part of `File` et al +//! block the task during execution. In the event of failure, all functions/methods +//! will return an `IoResult` type with an `Err` value. +//! +//! Also included in this module is an implementation block on the `Path` object +//! defined in `std::path::Path`. The impl adds useful methods about inspecting the +//! metadata of a file. This includes getting the `stat` information, reading off +//! particular bits of it, etc. +//! +//! # Example +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::io::fs::PathExtensions; +//! use std::io::{File, fs}; +//! +//! let path = Path::new("foo.txt"); +//! +//! // create the file, whether it exists or not +//! let mut file = File::create(&path); +//! file.write(b"foobar"); +//! # drop(file); +//! +//! // open the file in read-only mode +//! let mut file = File::open(&path); +//! file.read_to_end(); +//! +//! println!("{}", path.stat().unwrap().size); +//! # drop(file); +//! fs::unlink(&path); +//! ``` use clone::Clone; use io::standard_error; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index a25674030ae..fc6ee58346d 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -16,207 +16,205 @@ // error handling -/*! I/O, including files, networking, timers, and processes - -`std::io` provides Rust's basic I/O types, -for reading and writing to files, TCP, UDP, -and other types of sockets and pipes, -manipulating the file system, spawning processes. - -# Examples - -Some examples of obvious things you might want to do - -* Read lines from stdin - - ```rust - use std::io; - - for line in io::stdin().lines() { - print!("{}", line.unwrap()); - } - ``` - -* Read a complete file - - ```rust - use std::io::File; - - let contents = File::open(&Path::new("message.txt")).read_to_end(); - ``` - -* Write a line to a file - - ```rust - # #![allow(unused_must_use)] - use std::io::File; - - let mut file = File::create(&Path::new("message.txt")); - file.write(b"hello, file!\n"); - # drop(file); - # ::std::io::fs::unlink(&Path::new("message.txt")); - ``` - -* Iterate over the lines of a file - - ```rust,no_run - use std::io::BufferedReader; - use std::io::File; - - let path = Path::new("message.txt"); - let mut file = BufferedReader::new(File::open(&path)); - for line in file.lines() { - print!("{}", line.unwrap()); - } - ``` - -* Pull the lines of a file into a vector of strings - - ```rust,no_run - use std::io::BufferedReader; - use std::io::File; - - let path = Path::new("message.txt"); - let mut file = BufferedReader::new(File::open(&path)); - let lines: Vec = file.lines().map(|x| x.unwrap()).collect(); - ``` - -* Make a simple TCP client connection and request - - ```rust - # #![allow(unused_must_use)] - use std::io::TcpStream; - - # // connection doesn't fail if a server is running on 8080 - # // locally, we still want to be type checking this code, so lets - # // just stop it running (#11576) - # if false { - let mut socket = TcpStream::connect("127.0.0.1:8080").unwrap(); - socket.write(b"GET / HTTP/1.0\n\n"); - let response = socket.read_to_end(); - # } - ``` - -* Make a simple TCP server - - ```rust - # fn main() { } - # fn foo() { - # #![allow(dead_code)] - use std::io::{TcpListener, TcpStream}; - use std::io::{Acceptor, Listener}; - - let listener = TcpListener::bind("127.0.0.1:80"); - - // bind the listener to the specified address - let mut acceptor = listener.listen(); - - fn handle_client(mut stream: TcpStream) { - // ... - # &mut stream; // silence unused mutability/variable warning - } - // accept connections and process them, spawning a new tasks for each one - for stream in acceptor.incoming() { - match stream { - Err(e) => { /* connection failed */ } - Ok(stream) => spawn(proc() { - // connection succeeded - handle_client(stream) - }) - } - } - - // close the socket server - drop(acceptor); - # } - ``` - - -# Error Handling - -I/O is an area where nearly every operation can result in unexpected -errors. Errors should be painfully visible when they happen, and handling them -should be easy to work with. It should be convenient to handle specific I/O -errors, and it should also be convenient to not deal with I/O errors. - -Rust's I/O employs a combination of techniques to reduce boilerplate -while still providing feedback about errors. The basic strategy: - -* All I/O operations return `IoResult` which is equivalent to - `Result`. The `Result` type is defined in the `std::result` - module. -* If the `Result` type goes unused, then the compiler will by default emit a - warning about the unused result. This is because `Result` has the - `#[must_use]` attribute. -* Common traits are implemented for `IoResult`, e.g. - `impl Reader for IoResult`, so that error values do not have - to be 'unwrapped' before use. - -These features combine in the API to allow for expressions like -`File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")` -without having to worry about whether "diary.txt" exists or whether -the write succeeds. As written, if either `new` or `write_line` -encounters an error then the result of the entire expression will -be an error. - -If you wanted to handle the error though you might write: - -```rust -# #![allow(unused_must_use)] -use std::io::File; - -match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") { - Ok(()) => (), // succeeded - Err(e) => println!("failed to write to my diary: {}", e), -} - -# ::std::io::fs::unlink(&Path::new("diary.txt")); -``` - -So what actually happens if `create` encounters an error? -It's important to know that what `new` returns is not a `File` -but an `IoResult`. If the file does not open, then `new` will simply -return `Err(..)`. Because there is an implementation of `Writer` (the trait -required ultimately required for types to implement `write_line`) there is no -need to inspect or unwrap the `IoResult` and we simply call `write_line` -on it. If `new` returned an `Err(..)` then the followup call to `write_line` -will also return an error. - -## `try!` - -Explicit pattern matching on `IoResult`s can get quite verbose, especially -when performing many I/O operations. Some examples (like those above) are -alleviated with extra methods implemented on `IoResult`, but others have more -complex interdependencies among each I/O operation. - -The `try!` macro from `std::macros` is provided as a method of early-return -inside `Result`-returning functions. It expands to an early-return on `Err` -and otherwise unwraps the contained `Ok` value. - -If you wanted to read several `u32`s from a file and return their product: - -```rust -use std::io::{File, IoResult}; - -fn file_product(p: &Path) -> IoResult { - let mut f = File::open(p); - let x1 = try!(f.read_le_u32()); - let x2 = try!(f.read_le_u32()); - - Ok(x1 * x2) -} - -match file_product(&Path::new("numbers.bin")) { - Ok(x) => println!("{}", x), - Err(e) => println!("Failed to read numbers!") -} -``` - -With `try!` in `file_product`, each `read_le_u32` need not be directly -concerned with error handling; instead its caller is responsible for -responding to errors that may occur while attempting to read the numbers. - -*/ +//! I/O, including files, networking, timers, and processes +//! +//! `std::io` provides Rust's basic I/O types, +//! for reading and writing to files, TCP, UDP, +//! and other types of sockets and pipes, +//! manipulating the file system, spawning processes. +//! +//! # Examples +//! +//! Some examples of obvious things you might want to do +//! +//! * Read lines from stdin +//! +//! ```rust +//! use std::io; +//! +//! for line in io::stdin().lines() { +//! print!("{}", line.unwrap()); +//! } +//! ``` +//! +//! * Read a complete file +//! +//! ```rust +//! use std::io::File; +//! +//! let contents = File::open(&Path::new("message.txt")).read_to_end(); +//! ``` +//! +//! * Write a line to a file +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::io::File; +//! +//! let mut file = File::create(&Path::new("message.txt")); +//! file.write(b"hello, file!\n"); +//! # drop(file); +//! # ::std::io::fs::unlink(&Path::new("message.txt")); +//! ``` +//! +//! * Iterate over the lines of a file +//! +//! ```rust,no_run +//! use std::io::BufferedReader; +//! use std::io::File; +//! +//! let path = Path::new("message.txt"); +//! let mut file = BufferedReader::new(File::open(&path)); +//! for line in file.lines() { +//! print!("{}", line.unwrap()); +//! } +//! ``` +//! +//! * Pull the lines of a file into a vector of strings +//! +//! ```rust,no_run +//! use std::io::BufferedReader; +//! use std::io::File; +//! +//! let path = Path::new("message.txt"); +//! let mut file = BufferedReader::new(File::open(&path)); +//! let lines: Vec = file.lines().map(|x| x.unwrap()).collect(); +//! ``` +//! +//! * Make a simple TCP client connection and request +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::io::TcpStream; +//! +//! # // connection doesn't fail if a server is running on 8080 +//! # // locally, we still want to be type checking this code, so lets +//! # // just stop it running (#11576) +//! # if false { +//! let mut socket = TcpStream::connect("127.0.0.1:8080").unwrap(); +//! socket.write(b"GET / HTTP/1.0\n\n"); +//! let response = socket.read_to_end(); +//! # } +//! ``` +//! +//! * Make a simple TCP server +//! +//! ```rust +//! # fn main() { } +//! # fn foo() { +//! # #![allow(dead_code)] +//! use std::io::{TcpListener, TcpStream}; +//! use std::io::{Acceptor, Listener}; +//! +//! let listener = TcpListener::bind("127.0.0.1:80"); +//! +//! // bind the listener to the specified address +//! let mut acceptor = listener.listen(); +//! +//! fn handle_client(mut stream: TcpStream) { +//! // ... +//! # &mut stream; // silence unused mutability/variable warning +//! } +//! // accept connections and process them, spawning a new tasks for each one +//! for stream in acceptor.incoming() { +//! match stream { +//! Err(e) => { /* connection failed */ } +//! Ok(stream) => spawn(proc() { +//! // connection succeeded +//! handle_client(stream) +//! }) +//! } +//! } +//! +//! // close the socket server +//! drop(acceptor); +//! # } +//! ``` +//! +//! +//! # Error Handling +//! +//! I/O is an area where nearly every operation can result in unexpected +//! errors. Errors should be painfully visible when they happen, and handling them +//! should be easy to work with. It should be convenient to handle specific I/O +//! errors, and it should also be convenient to not deal with I/O errors. +//! +//! Rust's I/O employs a combination of techniques to reduce boilerplate +//! while still providing feedback about errors. The basic strategy: +//! +//! * All I/O operations return `IoResult` which is equivalent to +//! `Result`. The `Result` type is defined in the `std::result` +//! module. +//! * If the `Result` type goes unused, then the compiler will by default emit a +//! warning about the unused result. This is because `Result` has the +//! `#[must_use]` attribute. +//! * Common traits are implemented for `IoResult`, e.g. +//! `impl Reader for IoResult`, so that error values do not have +//! to be 'unwrapped' before use. +//! +//! These features combine in the API to allow for expressions like +//! `File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")` +//! without having to worry about whether "diary.txt" exists or whether +//! the write succeeds. As written, if either `new` or `write_line` +//! encounters an error then the result of the entire expression will +//! be an error. +//! +//! If you wanted to handle the error though you might write: +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::io::File; +//! +//! match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") { +//! Ok(()) => (), // succeeded +//! Err(e) => println!("failed to write to my diary: {}", e), +//! } +//! +//! # ::std::io::fs::unlink(&Path::new("diary.txt")); +//! ``` +//! +//! So what actually happens if `create` encounters an error? +//! It's important to know that what `new` returns is not a `File` +//! but an `IoResult`. If the file does not open, then `new` will simply +//! return `Err(..)`. Because there is an implementation of `Writer` (the trait +//! required ultimately required for types to implement `write_line`) there is no +//! need to inspect or unwrap the `IoResult` and we simply call `write_line` +//! on it. If `new` returned an `Err(..)` then the followup call to `write_line` +//! will also return an error. +//! +//! ## `try!` +//! +//! Explicit pattern matching on `IoResult`s can get quite verbose, especially +//! when performing many I/O operations. Some examples (like those above) are +//! alleviated with extra methods implemented on `IoResult`, but others have more +//! complex interdependencies among each I/O operation. +//! +//! The `try!` macro from `std::macros` is provided as a method of early-return +//! inside `Result`-returning functions. It expands to an early-return on `Err` +//! and otherwise unwraps the contained `Ok` value. +//! +//! If you wanted to read several `u32`s from a file and return their product: +//! +//! ```rust +//! use std::io::{File, IoResult}; +//! +//! fn file_product(p: &Path) -> IoResult { +//! let mut f = File::open(p); +//! let x1 = try!(f.read_le_u32()); +//! let x2 = try!(f.read_le_u32()); +//! +//! Ok(x1 * x2) +//! } +//! +//! match file_product(&Path::new("numbers.bin")) { +//! Ok(x) => println!("{}", x), +//! Err(e) => println!("Failed to read numbers!") +//! } +//! ``` +//! +//! With `try!` in `file_product`, each `read_le_u32` need not be directly +//! concerned with error handling; instead its caller is responsible for +//! responding to errors that may occur while attempting to read the numbers. #![experimental] #![deny(unused_must_use)] diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index d6a48fd39e6..7de78692130 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -8,14 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Synchronous DNS Resolution - -Contains the functionality to perform DNS resolution in a style related to -getaddrinfo() - -*/ +//! Synchronous DNS Resolution +//! +//! Contains the functionality to perform DNS resolution in a style related to +//! `getaddrinfo()` #![allow(missing_docs)] diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs index 2984fa59631..ec997b71986 100644 --- a/src/libstd/io/net/pipe.rs +++ b/src/libstd/io/net/pipe.rs @@ -8,19 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Named pipes - -This module contains the ability to communicate over named pipes with -synchronous I/O. On windows, this corresponds to talking over a Named Pipe, -while on Unix it corresponds to UNIX domain sockets. - -These pipes are similar to TCP in the sense that you can have both a stream to a -server and a server itself. The server provided accepts other `UnixStream` -instances as clients. - -*/ +//! Named pipes +//! +//! This module contains the ability to communicate over named pipes with +//! synchronous I/O. On windows, this corresponds to talking over a Named Pipe, +//! while on Unix it corresponds to UNIX domain sockets. +//! +//! These pipes are similar to TCP in the sense that you can have both a stream to a +//! server and a server itself. The server provided accepts other `UnixStream` +//! instances as clients. #![allow(missing_docs)] diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index e6dd20f63fb..665000eae88 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -8,24 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Non-blocking access to stdin, stdout, and stderr. - -This module provides bindings to the local event loop's TTY interface, using it -to offer synchronous but non-blocking versions of stdio. These handles can be -inspected for information about terminal dimensions or for related information -about the stream or terminal to which it is attached. - -# Example - -```rust -# #![allow(unused_must_use)] -use std::io; - -let mut out = io::stdout(); -out.write(b"Hello, world!"); -``` - -*/ +//! Non-blocking access to stdin, stdout, and stderr. +//! +//! This module provides bindings to the local event loop's TTY interface, using it +//! to offer synchronous but non-blocking versions of stdio. These handles can be +//! inspected for information about terminal dimensions or for related information +//! about the stream or terminal to which it is attached. +//! +//! # Example +//! +//! ```rust +//! # #![allow(unused_must_use)] +//! use std::io; +//! +//! let mut out = io::stdout(); +//! out.write(b"Hello, world!"); +//! ``` use self::StdSource::*; diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index a153ead2a38..af56735021e 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Various utility functions useful for writing I/O tests */ +//! Various utility functions useful for writing I/O tests #![macro_escape] @@ -95,17 +95,14 @@ pub fn raise_fd_limit() { unsafe { darwin_fd_limit::raise_fd_limit() } } +/// darwin_fd_limit exists to work around an issue where launchctl on Mac OS X defaults the rlimit +/// maxfiles to 256/unlimited. The default soft limit of 256 ends up being far too low for our +/// multithreaded scheduler testing, depending on the number of cores available. +/// +/// This fixes issue #7772. #[cfg(target_os="macos")] #[allow(non_camel_case_types)] mod darwin_fd_limit { - /*! - * darwin_fd_limit exists to work around an issue where launchctl on Mac OS X defaults the - * rlimit maxfiles to 256/unlimited. The default soft limit of 256 ends up being far too low - * for our multithreaded scheduler testing, depending on the number of cores available. - * - * This fixes issue #7772. - */ - use libc; type rlim_t = libc::uint64_t; #[repr(C)] diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index ec588f13478..ad02b534d04 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -8,14 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Synchronous Timers - -This module exposes the functionality to create timers, block the current task, -and create receivers which will receive notifications after a period of time. - -*/ +//! Synchronous Timers +//! +//! This module exposes the functionality to create timers, block the current task, +//! and create receivers which will receive notifications after a period of time. // FIXME: These functions take Durations but only pass ms to the backend impls. diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 8e0cd660816..393283ff64c 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Utility implementations of Reader and Writer */ +//! Utility implementations of Reader and Writer use prelude::*; use cmp; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 6b5ec983a80..b9a103d3d9b 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -8,23 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Higher-level interfaces to libc::* functions and operating system services. - * - * In general these take and return rust types, use rust idioms (enums, - * closures, vectors) rather than C idioms, and do more extensive safety - * checks. - * - * This module is not meant to only contain 1:1 mappings to libc entries; any - * os-interface code that is reasonably useful and broadly applicable can go - * here. Including utility routines that merely build on other os code. - * - * We assume the general case is that users do not care, and do not want to - * be made to care, which operating system they are on. While they may want - * to special case various special cases -- and so we will not _hide_ the - * facts of which OS the user is on -- they should be given the opportunity - * to write OS-ignorant code by default. - */ +//! Higher-level interfaces to libc::* functions and operating system services. +//! +//! In general these take and return rust types, use rust idioms (enums, closures, vectors) rather +//! than C idioms, and do more extensive safety checks. +//! +//! This module is not meant to only contain 1:1 mappings to libc entries; any os-interface code +//! that is reasonably useful and broadly applicable can go here. Including utility routines that +//! merely build on other os code. +//! +//! We assume the general case is that users do not care, and do not want to be made to care, which +//! operating system they are on. While they may want to special case various special cases -- and +//! so we will not _hide_ the facts of which OS the user is on -- they should be given the +//! opportunity to write OS-ignorant code by default. #![experimental] diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 047fa51b92f..b17106e811f 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -8,62 +8,56 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Cross-platform path support - -This module implements support for two flavors of paths. `PosixPath` represents -a path on any unix-like system, whereas `WindowsPath` represents a path on -Windows. This module also exposes a typedef `Path` which is equal to the -appropriate platform-specific path variant. - -Both `PosixPath` and `WindowsPath` implement a trait `GenericPath`, which -contains the set of methods that behave the same for both paths. They each also -implement some methods that could not be expressed in `GenericPath`, yet behave -identically for both path flavors, such as `.components()`. - -The three main design goals of this module are 1) to avoid unnecessary -allocation, 2) to behave the same regardless of which flavor of path is being -used, and 3) to support paths that cannot be represented in UTF-8 (as Linux has -no restriction on paths beyond disallowing NUL). - -## Usage - -Usage of this module is fairly straightforward. Unless writing platform-specific -code, `Path` should be used to refer to the platform-native path. - -Creation of a path is typically done with either `Path::new(some_str)` or -`Path::new(some_vec)`. This path can be modified with `.push()` and -`.pop()` (and other setters). The resulting Path can either be passed to another -API that expects a path, or can be turned into a `&[u8]` with `.as_vec()` or a -`Option<&str>` with `.as_str()`. Similarly, attributes of the path can be queried -with methods such as `.filename()`. There are also methods that return a new -path instead of modifying the receiver, such as `.join()` or `.dir_path()`. - -Paths are always kept in normalized form. This means that creating the path -`Path::new("a/b/../c")` will return the path `a/c`. Similarly any attempt -to mutate the path will always leave it in normalized form. - -When rendering a path to some form of output, there is a method `.display()` -which is compatible with the `format!()` parameter `{}`. This will render the -path as a string, replacing all non-utf8 sequences with the Replacement -Character (U+FFFD). As such it is not suitable for passing to any API that -actually operates on the path; it is only intended for display. - -## Example - -```rust -use std::io::fs::PathExtensions; - -let mut path = Path::new("/tmp/path"); -println!("path: {}", path.display()); -path.set_filename("foo"); -path.push("bar"); -println!("new path: {}", path.display()); -println!("path exists: {}", path.exists()); -``` - -*/ +//! Cross-platform path support +//! +//! This module implements support for two flavors of paths. `PosixPath` represents a path on any +//! unix-like system, whereas `WindowsPath` represents a path on Windows. This module also exposes +//! a typedef `Path` which is equal to the appropriate platform-specific path variant. +//! +//! Both `PosixPath` and `WindowsPath` implement a trait `GenericPath`, which contains the set of +//! methods that behave the same for both paths. They each also implement some methods that could +//! not be expressed in `GenericPath`, yet behave identically for both path flavors, such as +//! `.components()`. +//! +//! The three main design goals of this module are 1) to avoid unnecessary allocation, 2) to behave +//! the same regardless of which flavor of path is being used, and 3) to support paths that cannot +//! be represented in UTF-8 (as Linux has no restriction on paths beyond disallowing NUL). +//! +//! ## Usage +//! +//! Usage of this module is fairly straightforward. Unless writing platform-specific code, `Path` +//! should be used to refer to the platform-native path. +//! +//! Creation of a path is typically done with either `Path::new(some_str)` or +//! `Path::new(some_vec)`. This path can be modified with `.push()` and `.pop()` (and other +//! setters). The resulting Path can either be passed to another API that expects a path, or can be +//! turned into a `&[u8]` with `.as_vec()` or a `Option<&str>` with `.as_str()`. Similarly, +//! attributes of the path can be queried with methods such as `.filename()`. There are also +//! methods that return a new path instead of modifying the receiver, such as `.join()` or +//! `.dir_path()`. +//! +//! Paths are always kept in normalized form. This means that creating the path +//! `Path::new("a/b/../c")` will return the path `a/c`. Similarly any attempt to mutate the path +//! will always leave it in normalized form. +//! +//! When rendering a path to some form of output, there is a method `.display()` which is +//! compatible with the `format!()` parameter `{}`. This will render the path as a string, +//! replacing all non-utf8 sequences with the Replacement Character (U+FFFD). As such it is not +//! suitable for passing to any API that actually operates on the path; it is only intended for +//! display. +//! +//! ## Example +//! +//! ```rust +//! use std::io::fs::PathExtensions; +//! +//! let mut path = Path::new("/tmp/path"); +//! println!("path: {}", path.display()); +//! path.set_filename("foo"); +//! path.push("bar"); +//! println!("new path: {}", path.display()); +//! println!("path exists: {}", path.exists()); +//! ``` #![experimental] diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 872a5452241..5ecd3ff04f1 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -8,46 +8,38 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Runtime services, including the task scheduler and I/O dispatcher - -The `rt` module provides the private runtime infrastructure necessary -to support core language features like the exchange and local heap, -logging, local data and unwinding. It also implements the default task -scheduler and task model. Initialization routines are provided for setting -up runtime resources in common configurations, including that used by -`rustc` when generating executables. - -It is intended that the features provided by `rt` can be factored in a -way such that the core library can be built with different 'profiles' -for different use cases, e.g. excluding the task scheduler. A number -of runtime features though are critical to the functioning of the -language and an implementation must be provided regardless of the -execution environment. - -Of foremost importance is the global exchange heap, in the module -`heap`. Very little practical Rust code can be written without -access to the global heap. Unlike most of `rt` the global heap is -truly a global resource and generally operates independently of the -rest of the runtime. - -All other runtime features are task-local, including the local heap, -local storage, logging and the stack unwinder. - -The relationship between `rt` and the rest of the core library is -not entirely clear yet and some modules will be moving into or -out of `rt` as development proceeds. - -Several modules in `core` are clients of `rt`: - -* `std::task` - The user-facing interface to the Rust task model. -* `std::local_data` - The interface to local data. -* `std::unstable::lang` - Miscellaneous lang items, some of which rely on `std::rt`. -* `std::cleanup` - Local heap destruction. -* `std::io` - In the future `std::io` will use an `rt` implementation. -* `std::logging` -* `std::comm` - -*/ +//! Runtime services, including the task scheduler and I/O dispatcher +//! +//! The `rt` module provides the private runtime infrastructure necessary to support core language +//! features like the exchange and local heap, logging, local data and unwinding. It also +//! implements the default task scheduler and task model. Initialization routines are provided for +//! setting up runtime resources in common configurations, including that used by `rustc` when +//! generating executables. +//! +//! It is intended that the features provided by `rt` can be factored in a way such that the core +//! library can be built with different 'profiles' for different use cases, e.g. excluding the task +//! scheduler. A number of runtime features though are critical to the functioning of the language +//! and an implementation must be provided regardless of the execution environment. +//! +//! Of foremost importance is the global exchange heap, in the module `heap`. Very little practical +//! Rust code can be written without access to the global heap. Unlike most of `rt` the global heap +//! is truly a global resource and generally operates independently of the rest of the runtime. +//! +//! All other runtime features are task-local, including the local heap, local storage, logging and +//! the stack unwinder. +//! +//! The relationship between `rt` and the rest of the core library is not entirely clear yet and +//! some modules will be moving into or out of `rt` as development proceeds. +//! +//! Several modules in `core` are clients of `rt`: +//! +//! * `std::task` - The user-facing interface to the Rust task model. +//! * `std::local_data` - The interface to local data. +//! * `std::unstable::lang` - Miscellaneous lang items, some of which rely on `std::rt`. +//! * `std::cleanup` - Local heap destruction. +//! * `std::io` - In the future `std::io` will use an `rt` implementation. +//! * `std::logging` +//! * `std::comm` #![experimental] diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs index d6f413a0828..f2f9351fd0d 100644 --- a/src/libstd/sync/future.rs +++ b/src/libstd/sync/future.rs @@ -8,21 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * A type representing values that may be computed concurrently and - * operations for working with them. - * - * # Example - * - * ```rust - * use std::sync::Future; - * # fn fib(n: uint) -> uint {42}; - * # fn make_a_sandwich() {}; - * let mut delayed_fib = Future::spawn(proc() { fib(5000) }); - * make_a_sandwich(); - * println!("fib(5000) = {}", delayed_fib.get()) - * ``` - */ +//! A type representing values that may be computed concurrently and operations for working with +//! them. +//! +//! # Example +//! +//! ```rust +//! use std::sync::Future; +//! # fn fib(n: uint) -> uint {42}; +//! # fn make_a_sandwich() {}; +//! let mut delayed_fib = Future::spawn(proc() { fib(5000) }); +//! make_a_sandwich(); +//! println!("fib(5000) = {}", delayed_fib.get()) +//! ``` #![allow(missing_docs)] diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3d33774aa55..26c049d267d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -276,11 +276,9 @@ impl PathParameters { } } + /// Returns the types that the user wrote. Note that these do not necessarily map to the type + /// parameters in the parenthesized case. pub fn types(&self) -> Vec<&P> { - /*! - * Returns the types that the user wrote. Note that these do not - * necessarily map to the type parameters in the parenthesized case. - */ match *self { AngleBracketedParameters(ref data) => { data.types.iter().collect() diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 043e79bffd9..4d35fbc1437 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -569,6 +569,7 @@ pub fn compute_id_range_for_inlined_item(item: &InlinedItem) -> IdRange { visitor.result } +/// Computes the id range for a single fn body, ignoring nested items. pub fn compute_id_range_for_fn_body(fk: visit::FnKind, decl: &FnDecl, body: &Block, @@ -576,11 +577,6 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind, id: NodeId) -> IdRange { - /*! - * Computes the id range for a single fn body, - * ignoring nested items. - */ - let mut visitor = IdRangeComputingVisitor { result: IdRange::max() }; diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index b019b31de5f..1c1e1acab1c 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -10,18 +10,12 @@ // // ignore-lexer-test FIXME #15679 -/*! - -The CodeMap tracks all the source code used within a single crate, mapping -from integer byte positions to the original source code location. Each bit of -source parsed during crate parsing (typically files, in-memory strings, or -various bits of macro expansion) cover a continuous range of bytes in the -CodeMap and are represented by FileMaps. Byte positions are stored in `spans` -and used pervasively in the compiler. They are absolute positions within the -CodeMap, which upon request can be converted to line and column information, -source code snippets, etc. - -*/ +//! The CodeMap tracks all the source code used within a single crate, mapping from integer byte +//! positions to the original source code location. Each bit of source parsed during crate parsing +//! (typically files, in-memory strings, or various bits of macro expansion) cover a continuous +//! range of bytes in the CodeMap and are represented by FileMaps. Byte positions are stored in +//! `spans` and used pervasively in the compiler. They are absolute positions within the CodeMap, +//! which upon request can be converted to line and column information, source code snippets, etc. pub use self::MacroFormat::*; diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index d0a03658386..e3cf2b68752 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -The compiler code necessary for `#[deriving(Decodable)]`. See -encodable.rs for more. -*/ +//! The compiler code necessary for `#[deriving(Decodable)]`. See encodable.rs for more. use ast; use ast::{MetaItem, Item, Expr, MutMutable}; diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index 700ada8b4ad..f285d2cc2ff 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -A mini version of ast::Ty, which is easier to use, and features an -explicit `Self` type to use when specifying impls to be derived. -*/ +//! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use +//! when specifying impls to be derived. pub use self::PtrTy::*; pub use self::Ty::*; diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index b8cebd8ea20..fccef47d1ea 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -8,15 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -The compiler code necessary to implement the `#[deriving]` extensions. - - -FIXME (#2810): hygiene. Search for "__" strings (in other files too). -We also assume "extra" is the standard library, and "std" is the core -library. - -*/ +//! The compiler code necessary to implement the `#[deriving]` extensions. +//! +//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is +//! the standard library, and "std" is the core library. use ast::{Item, MetaItem, MetaList, MetaNameValue, MetaWord}; use ext::base::ExtCtxt; diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index e2dee607c69..86a96fc5216 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -8,14 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -Support for parsing unsupported, old syntaxes, for the -purpose of reporting errors. Parsing of these syntaxes -is tested by compile-test/obsolete-syntax.rs. - -Obsolete syntax that becomes too hard to parse can be -removed. -*/ +//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of +//! these syntaxes is tested by compile-test/obsolete-syntax.rs. +//! +//! Obsolete syntax that becomes too hard to parse can be removed. pub use self::ObsoleteSyntax::*; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c731a0005f8..b620799cc97 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1963,11 +1963,9 @@ impl<'a> Parser<'a> { } } + /// Parses `lifetime_defs = [ lifetime_defs { ',' lifetime_defs } ]` where `lifetime_def = + /// lifetime [':' lifetimes]` pub fn parse_lifetime_defs(&mut self) -> Vec { - /*! - * Parses `lifetime_defs = [ lifetime_defs { ',' lifetime_defs } ]` - * where `lifetime_def = lifetime [':' lifetimes]` - */ let mut res = Vec::new(); loop { @@ -2003,16 +2001,13 @@ impl<'a> Parser<'a> { } } - // matches lifetimes = ( lifetime ) | ( lifetime , lifetimes ) - // actually, it matches the empty one too, but putting that in there - // messes up the grammar.... + /// matches lifetimes = ( lifetime ) | ( lifetime , lifetimes ) actually, it matches the empty + /// one too, but putting that in there messes up the grammar.... + /// + /// Parses zero or more comma separated lifetimes. Expects each lifetime to be followed by + /// either a comma or `>`. Used when parsing type parameter lists, where we expect something + /// like `<'a, 'b, T>`. pub fn parse_lifetimes(&mut self, sep: token::Token) -> Vec { - /*! - * Parses zero or more comma separated lifetimes. - * Expects each lifetime to be followed by either - * a comma or `>`. Used when parsing type parameter - * lists, where we expect something like `<'a, 'b, T>`. - */ let mut res = Vec::new(); loop { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 3f87dbc0740..84afa56b07d 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -92,14 +92,12 @@ pub trait Visitor<'v> { } fn visit_struct_field(&mut self, s: &'v StructField) { walk_struct_field(self, s) } fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics) { walk_variant(self, v, g) } + + /// Visits an optional reference to a lifetime. The `span` is the span of some surrounding + /// reference should opt_lifetime be None. fn visit_opt_lifetime_ref(&mut self, _span: Span, opt_lifetime: &'v Option) { - /*! - * Visits an optional reference to a lifetime. The `span` is - * the span of some surrounding reference should opt_lifetime - * be None. - */ match *opt_lifetime { Some(ref l) => self.visit_lifetime_ref(l), None => () diff --git a/src/libunicode/normalize.rs b/src/libunicode/normalize.rs index ad36215c11b..962be3d5acd 100644 --- a/src/libunicode/normalize.rs +++ b/src/libunicode/normalize.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - Functions for computing canonical and compatible decompositions - for Unicode characters. - */ +//! Functions for computing canonical and compatible decompositions for Unicode characters. use core::cmp::{Equal, Less, Greater}; use core::option::{Option, Some, None}; diff --git a/src/libunicode/u_char.rs b/src/libunicode/u_char.rs index 369336639a7..a73dac1a618 100644 --- a/src/libunicode/u_char.rs +++ b/src/libunicode/u_char.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Unicode-intensive `char` methods. - * - * These methods implement functionality for `char` that requires knowledge of - * Unicode definitions, including normalization, categorization, and display information. - */ +//! Unicode-intensive `char` methods. +//! +//! These methods implement functionality for `char` that requires knowledge of +//! Unicode definitions, including normalization, categorization, and display information. use core::option::Option; use tables::{derived_property, property, general_category, conversions, charwidth}; diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 03a50409d7e..a5f76142575 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -10,12 +10,10 @@ // // ignore-lexer-test FIXME #15679 -/*! - * Unicode-intensive string manipulations. - * - * This module provides functionality to `str` that requires the Unicode - * methods provided by the UnicodeChar trait. - */ +//! Unicode-intensive string manipulations. +//! +//! This module provides functionality to `str` that requires the Unicode methods provided by the +//! UnicodeChar trait. use self::GraphemeState::*; use core::cmp; -- cgit 1.4.1-3-g733a5 From 232ffa039ddb349c9e9c08d0872aaf95970a1369 Mon Sep 17 00:00:00 2001 From: jfager Date: Sat, 29 Nov 2014 16:41:21 -0500 Subject: Replace some verbose match statements with their `if let` equivalent. No semantic changes, no enabling `if let` where it wasn't already enabled. --- src/librustc/lint/builtin.rs | 190 ++++++-------- src/librustc/metadata/decoder.rs | 75 +++--- src/librustc/metadata/encoder.rs | 149 +++++------ src/librustc/middle/borrowck/check_loans.rs | 12 +- src/librustc/middle/borrowck/gather_loans/mod.rs | 27 +- src/librustc/middle/const_eval.rs | 14 +- src/librustc/middle/effect.rs | 28 +-- src/librustc/middle/intrinsicck.rs | 36 ++- src/librustc/middle/liveness.rs | 52 ++-- src/librustc/middle/privacy.rs | 82 +++---- src/librustc/middle/reachable.rs | 14 +- src/librustc/middle/resolve.rs | 299 +++++++++-------------- src/librustc/middle/stability.rs | 20 +- src/librustc/middle/traits/util.rs | 6 +- src/librustc/middle/ty.rs | 12 +- src/librustc/middle/typeck/check/mod.rs | 85 +++---- src/librustc/middle/typeck/check/regionck.rs | 129 ++++------ src/librustc/middle/typeck/check/vtable.rs | 17 +- src/librustc/middle/typeck/check/wf.rs | 15 +- src/librustc/middle/typeck/collect.rs | 295 ++++++++++------------ src/librustc/plugin/build.rs | 11 +- src/librustc_trans/back/link.rs | 40 ++- src/librustc_trans/save/mod.rs | 12 +- src/librustc_trans/trans/_match.rs | 32 +-- src/librustc_trans/trans/base.rs | 35 +-- src/librustc_trans/trans/callee.rs | 7 +- src/librustc_trans/trans/cleanup.rs | 7 +- src/librustc_trans/trans/consts.rs | 14 +- src/librustc_trans/trans/context.rs | 5 +- src/librustc_trans/trans/controlflow.rs | 15 +- src/librustc_trans/trans/expr.rs | 13 +- src/librustc_trans/trans/foreign.rs | 30 +-- src/librustc_trans/trans/monomorphize.rs | 11 +- src/librustc_trans/trans/tvec.rs | 22 +- src/librustdoc/clean/mod.rs | 9 +- src/librustdoc/html/render.rs | 194 +++++++-------- src/librustdoc/passes.rs | 43 ++-- src/libsyntax/ast_map/mod.rs | 7 +- src/libsyntax/ast_util.rs | 19 +- src/libsyntax/feature_gate.rs | 23 +- src/libsyntax/parse/parser.rs | 63 ++--- src/libsyntax/print/pprust.rs | 43 ++-- src/libsyntax/visit.rs | 7 +- 43 files changed, 882 insertions(+), 1337 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 9b6fedd2955..a90055093a4 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -61,23 +61,13 @@ impl LintPass for WhileTrue { } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - match e.node { - ast::ExprWhile(ref cond, _, _) => { - match cond.node { - ast::ExprLit(ref lit) => { - match lit.node { - ast::LitBool(true) => { - cx.span_lint(WHILE_TRUE, e.span, - "denote infinite loops with loop \ - { ... }"); - } - _ => {} - } - } - _ => () + if let ast::ExprWhile(ref cond, _, _) = e.node { + if let ast::ExprLit(ref lit) = cond.node { + if let ast::LitBool(true) = lit.node { + cx.span_lint(WHILE_TRUE, e.span, + "denote infinite loops with loop { ... }"); } } - _ => () } } } @@ -93,14 +83,11 @@ impl LintPass for UnusedCasts { } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - match e.node { - ast::ExprCast(ref expr, ref ty) => { - let t_t = ast_ty_to_ty(cx, &infer::new_infer_ctxt(cx.tcx), &**ty); - if ty::expr_ty(cx.tcx, &**expr) == t_t { - cx.span_lint(UNUSED_TYPECASTS, ty.span, "unnecessary type cast"); - } + if let ast::ExprCast(ref expr, ref ty) = e.node { + let t_t = ast_ty_to_ty(cx, &infer::new_infer_ctxt(cx.tcx), &**ty); + if ty::expr_ty(cx.tcx, &**expr) == t_t { + cx.span_lint(UNUSED_TYPECASTS, ty.span, "unnecessary type cast"); } - _ => () } } } @@ -540,9 +527,8 @@ struct RawPtrDerivingVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDerivingVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { static MSG: &'static str = "use of `#[deriving]` with a raw pointer"; - match ty.node { - ast::TyPtr(..) => self.cx.span_lint(RAW_POINTER_DERIVING, ty.span, MSG), - _ => {} + if let ast::TyPtr(..) = ty.node { + self.cx.span_lint(RAW_POINTER_DERIVING, ty.span, MSG); } visit::walk_ty(self, ty); } @@ -720,9 +706,8 @@ impl LintPass for UnusedResults { _ => return }; - match expr.node { - ast::ExprRet(..) => return, - _ => {} + if let ast::ExprRet(..) = expr.node { + return; } let t = ty::expr_ty(cx.tcx, expr); @@ -733,11 +718,8 @@ impl LintPass for UnusedResults { ty::ty_struct(did, _) | ty::ty_enum(did, _) => { if ast_util::is_local(did) { - match cx.tcx.map.get(did.node) { - ast_map::NodeItem(it) => { - warned |= check_must_use(cx, it.attrs.as_slice(), s.span); - } - _ => {} + if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) { + warned |= check_must_use(cx, it.attrs.as_slice(), s.span); } } else { csearch::get_item_attrs(&cx.sess().cstore, did, |attrs| { @@ -969,11 +951,8 @@ impl LintPass for NonSnakeCase { } fn check_item(&mut self, cx: &Context, it: &ast::Item) { - match it.node { - ast::ItemMod(_) => { - self.check_snake_case(cx, "module", it.ident, it.span); - } - _ => {} + if let ast::ItemMod(_) = it.node { + self.check_snake_case(cx, "module", it.ident, it.span); } } @@ -986,27 +965,18 @@ impl LintPass for NonSnakeCase { } fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { - match &p.node { - &ast::PatIdent(_, ref path1, _) => { - match cx.tcx.def_map.borrow().get(&p.id) { - Some(&def::DefLocal(_)) => { - self.check_snake_case(cx, "variable", path1.node, p.span); - } - _ => {} - } + if let &ast::PatIdent(_, ref path1, _) = &p.node { + if let Some(&def::DefLocal(_)) = cx.tcx.def_map.borrow().get(&p.id) { + self.check_snake_case(cx, "variable", path1.node, p.span); } - _ => {} } } fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { for sf in s.fields.iter() { - match sf.node { - ast::StructField_ { kind: ast::NamedField(ident, _), .. } => { - self.check_snake_case(cx, "structure field", ident, sf.span); - } - _ => {} + if let ast::StructField_ { kind: ast::NamedField(ident, _), .. } = sf.node { + self.check_snake_case(cx, "structure field", ident, sf.span); } } } @@ -1069,16 +1039,13 @@ pub struct UnusedParens; impl UnusedParens { fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str, struct_lit_needs_parens: bool) { - match value.node { - ast::ExprParen(ref inner) => { - let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); - if !necessary { - cx.span_lint(UNUSED_PARENS, value.span, - format!("unnecessary parentheses around {}", - msg).as_slice()) - } + if let ast::ExprParen(ref inner) = value.node { + let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); + if !necessary { + cx.span_lint(UNUSED_PARENS, value.span, + format!("unnecessary parentheses around {}", + msg).as_slice()) } - _ => {} } /// Expressions that syntactically contain an "exterior" struct @@ -1201,24 +1168,21 @@ impl LintPass for NonShorthandFieldPatterns { fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) { let def_map = cx.tcx.def_map.borrow(); - match pat.node { - ast::PatStruct(_, ref v, _) => { - for fieldpat in v.iter() - .filter(|fieldpat| !fieldpat.node.is_shorthand) - .filter(|fieldpat| def_map.get(&fieldpat.node.pat.id) - == Some(&def::DefLocal(fieldpat.node.pat.id))) { - match fieldpat.node.pat.node { - ast::PatIdent(_, ident, None) if ident.node.as_str() - == fieldpat.node.ident.as_str() => { - cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, - format!("the `{}:` in this pattern is redundant and can \ - be removed", ident.node.as_str()).as_slice()) - }, - _ => {}, - } + if let ast::PatStruct(_, ref v, _) = pat.node { + for fieldpat in v.iter() + .filter(|fieldpat| !fieldpat.node.is_shorthand) + .filter(|fieldpat| def_map.get(&fieldpat.node.pat.id) + == Some(&def::DefLocal(fieldpat.node.pat.id))) { + match fieldpat.node.pat.node { + ast::PatIdent(_, ident, None) if ident.node.as_str() + == fieldpat.node.ident.as_str() => { + cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, + format!("the `{}:` in this pattern is redundant and can \ + be removed", ident.node.as_str()).as_slice()) + }, + _ => {}, } - }, - _ => {} + } } } } @@ -1313,27 +1277,18 @@ impl LintPass for UnusedMut { } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - match e.node { - ast::ExprMatch(_, ref arms, _) => { - for a in arms.iter() { - self.check_unused_mut_pat(cx, a.pats.as_slice()) - } + if let ast::ExprMatch(_, ref arms, _) = e.node { + for a in arms.iter() { + self.check_unused_mut_pat(cx, a.pats.as_slice()) } - _ => {} } } fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { - match s.node { - ast::StmtDecl(ref d, _) => { - match d.node { - ast::DeclLocal(ref l) => { - self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat)); - }, - _ => {} - } - }, - _ => {} + if let ast::StmtDecl(ref d, _) = s.node { + if let ast::DeclLocal(ref l) = d.node { + self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat)); + } } } @@ -1362,26 +1317,20 @@ impl LintPass for UnusedAllocation { _ => return } - match cx.tcx.adjustments.borrow().get(&e.id) { - Some(adjustment) => { - match *adjustment { - ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) => { - match autoref { - &Some(ty::AutoPtr(_, ast::MutImmutable, None)) => { - cx.span_lint(UNUSED_ALLOCATION, e.span, - "unnecessary allocation, use & instead"); - } - &Some(ty::AutoPtr(_, ast::MutMutable, None)) => { - cx.span_lint(UNUSED_ALLOCATION, e.span, - "unnecessary allocation, use &mut instead"); - } - _ => () - } + if let Some(adjustment) = cx.tcx.adjustments.borrow().get(&e.id) { + if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment { + match autoref { + &Some(ty::AutoPtr(_, ast::MutImmutable, None)) => { + cx.span_lint(UNUSED_ALLOCATION, e.span, + "unnecessary allocation, use & instead"); } - _ => {} + &Some(ty::AutoPtr(_, ast::MutMutable, None)) => { + cx.span_lint(UNUSED_ALLOCATION, e.span, + "unnecessary allocation, use &mut instead"); + } + _ => () } } - _ => () } } } @@ -1499,17 +1448,14 @@ impl LintPass for MissingDoc { fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { - match fk { - visit::FkMethod(_, _, m) => { - // If the method is an impl for a trait, don't doc. - if method_context(cx, m) == TraitImpl { return; } - - // Otherwise, doc according to privacy. This will also check - // doc for default methods defined on traits. - self.check_missing_docs_attrs(cx, Some(m.id), m.attrs.as_slice(), - m.span, "a method"); - } - _ => {} + if let visit::FkMethod(_, _, m) = fk { + // If the method is an impl for a trait, don't doc. + if method_context(cx, m) == TraitImpl { return; } + + // Otherwise, doc according to privacy. This will also check + // doc for default methods defined on traits. + self.check_missing_docs_attrs(cx, Some(m.id), m.attrs.as_slice(), + m.span, "a method"); } } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 209e78682b4..92639ea3c78 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -514,41 +514,33 @@ fn each_child_of_item_or_crate(intr: Rc, let inherent_impl_def_id = item_def_id(inherent_impl_def_id_doc, cdata); let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items); - match maybe_find_item(inherent_impl_def_id.node, items) { - None => {} - Some(inherent_impl_doc) => { - let _ = reader::tagged_docs(inherent_impl_doc, - tag_item_impl_item, - |impl_item_def_id_doc| { - let impl_item_def_id = item_def_id(impl_item_def_id_doc, - cdata); - match maybe_find_item(impl_item_def_id.node, items) { - None => {} - Some(impl_method_doc) => { - match item_family(impl_method_doc) { - StaticMethod => { - // Hand off the static method - // to the callback. - let static_method_name = - item_name(&*intr, impl_method_doc); - let static_method_def_like = - item_to_def_like(impl_method_doc, - impl_item_def_id, - cdata.cnum); - callback(static_method_def_like, - static_method_name, - item_visibility(impl_method_doc)); - } - _ => {} - } + if let Some(inherent_impl_doc) = maybe_find_item(inherent_impl_def_id.node, items) { + let _ = reader::tagged_docs(inherent_impl_doc, + tag_item_impl_item, + |impl_item_def_id_doc| { + let impl_item_def_id = item_def_id(impl_item_def_id_doc, + cdata); + if let Some(impl_method_doc) = maybe_find_item(impl_item_def_id.node, items) { + match item_family(impl_method_doc) { + StaticMethod => { + // Hand off the static method + // to the callback. + let static_method_name = + item_name(&*intr, impl_method_doc); + let static_method_def_like = + item_to_def_like(impl_method_doc, + impl_item_def_id, + cdata.cnum); + callback(static_method_def_like, + static_method_name, + item_visibility(impl_method_doc)); } + _ => {} } - - true - }); - } + } + true + }); } - true }); @@ -578,17 +570,14 @@ fn each_child_of_item_or_crate(intr: Rc, let other_crates_items = reader::get_doc(rbml::Doc::new(crate_data.data()), tag_items); // Get the item. - match maybe_find_item(child_def_id.node, other_crates_items) { - None => {} - Some(child_item_doc) => { - // Hand off the item to the callback. - let def_like = item_to_def_like(child_item_doc, - child_def_id, - child_def_id.krate); - // These items have a public visibility because they're part of - // a public re-export. - callback(def_like, token::intern(name), ast::Public); - } + if let Some(child_item_doc) = maybe_find_item(child_def_id.node, other_crates_items) { + // Hand off the item to the callback. + let def_like = item_to_def_like(child_item_doc, + child_def_id, + child_def_id.krate); + // These items have a public visibility because they're part of + // a public re-export. + callback(def_like, token::intern(name), ast::Public); } true diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index d65fb9d2778..f7ee9fa6522 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -433,17 +433,13 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext, match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) { Some(trait_items) => { for trait_item in trait_items.iter() { - match *trait_item { - ty::MethodTraitItem(ref m) => { - encode_reexported_static_method(rbml_w, - exp, - m.def_id, - m.name); - } - _ => {} + if let ty::MethodTraitItem(ref m) = *trait_item { + encode_reexported_static_method(rbml_w, + exp, + m.def_id, + m.name); } } - true } None => { false } @@ -454,46 +450,42 @@ fn encode_reexported_static_methods(ecx: &EncodeContext, rbml_w: &mut Encoder, mod_path: PathElems, exp: &middle::resolve::Export2) { - match ecx.tcx.map.find(exp.def_id.node) { - Some(ast_map::NodeItem(item)) => { - let original_name = token::get_ident(item.ident); - - let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| { - let (mut a, mut b) = (path, mod_path.clone()); - loop { - match (a.next(), b.next()) { - (None, None) => return true, - (None, _) | (_, None) => return false, - (Some(x), Some(y)) => if x != y { return false }, - } + if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) { + let original_name = token::get_ident(item.ident); + + let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| { + let (mut a, mut b) = (path, mod_path.clone()); + loop { + match (a.next(), b.next()) { + (None, None) => return true, + (None, _) | (_, None) => return false, + (Some(x), Some(y)) => if x != y { return false }, } - }); + } + }); - // - // We don't need to reexport static methods on items - // declared in the same module as our `pub use ...` since - // that's done when we encode the item itself. - // - // The only exception is when the reexport *changes* the - // name e.g. `pub use Foo = self::Bar` -- we have - // encoded metadata for static methods relative to Bar, - // but not yet for Foo. - // - if path_differs || original_name.get() != exp.name.as_slice() { - if !encode_reexported_static_base_methods(ecx, rbml_w, exp) { - if encode_reexported_static_trait_methods(ecx, rbml_w, exp) { - debug!("(encode reexported static methods) {} \ - [trait]", - original_name); - } - } - else { - debug!("(encode reexported static methods) {} [base]", - original_name); + // + // We don't need to reexport static methods on items + // declared in the same module as our `pub use ...` since + // that's done when we encode the item itself. + // + // The only exception is when the reexport *changes* the + // name e.g. `pub use Foo = self::Bar` -- we have + // encoded metadata for static methods relative to Bar, + // but not yet for Foo. + // + if path_differs || original_name.get() != exp.name.as_slice() { + if !encode_reexported_static_base_methods(ecx, rbml_w, exp) { + if encode_reexported_static_trait_methods(ecx, rbml_w, exp) { + debug!("(encode reexported static methods) {} [trait]", + original_name); } } + else { + debug!("(encode reexported static methods) {} [base]", + original_name); + } } - _ => {} } } @@ -581,19 +573,15 @@ fn encode_info_for_mod(ecx: &EncodeContext, true }); - match item.node { - ast::ItemImpl(..) => { - let (ident, did) = (item.ident, item.id); - debug!("(encoding info for module) ... encoding impl {} \ - ({}/{})", - token::get_ident(ident), - did, ecx.tcx.map.node_to_string(did)); + if let ast::ItemImpl(..) = item.node { + let (ident, did) = (item.ident, item.id); + debug!("(encoding info for module) ... encoding impl {} ({}/{})", + token::get_ident(ident), + did, ecx.tcx.map.node_to_string(did)); - rbml_w.start_tag(tag_mod_impl); - rbml_w.wr_str(def_to_string(local_def(did)).as_slice()); - rbml_w.end_tag(); - } - _ => {} + rbml_w.start_tag(tag_mod_impl); + rbml_w.wr_str(def_to_string(local_def(did)).as_slice()); + rbml_w.end_tag(); } } @@ -923,12 +911,9 @@ fn encode_method_argument_names(rbml_w: &mut Encoder, rbml_w.start_tag(tag_method_argument_names); for arg in decl.inputs.iter() { rbml_w.start_tag(tag_method_argument_name); - match arg.pat.node { - ast::PatIdent(_, ref path1, _) => { - let name = token::get_ident(path1.node); - rbml_w.writer.write(name.get().as_bytes()); - } - _ => {} + if let ast::PatIdent(_, ref path1, _) = arg.pat.node { + let name = token::get_ident(path1.node); + rbml_w.writer.write(name.get().as_bytes()); } rbml_w.end_tag(); } @@ -1854,22 +1839,19 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> { impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> { fn visit_item(&mut self, item: &ast::Item) { - match item.node { - ast::ItemImpl(_, Some(ref trait_ref), _, _) => { - let def_map = &self.ecx.tcx.def_map; - let trait_def = def_map.borrow()[trait_ref.ref_id].clone(); - let def_id = trait_def.def_id(); - - // Load eagerly if this is an implementation of the Drop trait - // or if the trait is not defined in this crate. - if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() || - def_id.krate != ast::LOCAL_CRATE { - self.rbml_w.start_tag(tag_impls_impl); - encode_def_id(self.rbml_w, local_def(item.id)); - self.rbml_w.end_tag(); - } + if let ast::ItemImpl(_, Some(ref trait_ref), _, _) = item.node { + let def_map = &self.ecx.tcx.def_map; + let trait_def = def_map.borrow()[trait_ref.ref_id].clone(); + let def_id = trait_def.def_id(); + + // Load eagerly if this is an implementation of the Drop trait + // or if the trait is not defined in this crate. + if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() || + def_id.krate != ast::LOCAL_CRATE { + self.rbml_w.start_tag(tag_impls_impl); + encode_def_id(self.rbml_w, local_def(item.id)); + self.rbml_w.end_tag(); } - _ => {} } visit::walk_item(self, item); } @@ -1931,17 +1913,12 @@ fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) { rbml_w.start_tag(tag_reachable_extern_fns); for id in ecx.reachable.iter() { - match ecx.tcx.map.find(*id) { - Some(ast_map::NodeItem(i)) => { - match i.node { - ast::ItemFn(_, _, abi, ref generics, _) - if abi != abi::Rust && !generics.is_type_parameterized() => { - rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id); - } - _ => {} + if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) { + if let ast::ItemFn(_, _, abi, ref generics, _) = i.node { + if abi != abi::Rust && !generics.is_type_parameterized() { + rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id); } } - _ => {} } } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 9a27abbe832..72c6256dcb5 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -892,14 +892,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let guarantor = cmt.guarantor(); debug!("check_for_aliasable_mutable_writes(cmt={}, guarantor={})", cmt.repr(this.tcx()), guarantor.repr(this.tcx())); - match guarantor.cat { - mc::cat_deref(ref b, _, mc::BorrowedPtr(ty::MutBorrow, _)) => { - // Statically prohibit writes to `&mut` when aliasable - - check_for_aliasability_violation(this, span, b.clone()); - } - - _ => {} + if let mc::cat_deref(ref b, _, mc::BorrowedPtr(ty::MutBorrow, _)) = guarantor.cat { + // Statically prohibit writes to `&mut` when aliasable + check_for_aliasability_violation(this, span, b.clone()); } return true; // no errors reported @@ -962,4 +957,3 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.loan_path_to_string(loan_path)).as_slice()); } } - diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 4f7ecc99c89..edffe59fff5 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -97,12 +97,10 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { cmt.repr(self.tcx()), mode); - match cmt.cat { - mc::cat_downcast(..) => - gather_moves::gather_match_variant( - self.bccx, &self.move_data, &self.move_error_collector, - matched_pat, cmt, mode), - _ => {} + if let mc::cat_downcast(..) = cmt.cat { + gather_moves::gather_match_variant( + self.bccx, &self.move_data, &self.move_error_collector, + matched_pat, cmt, mode); } } @@ -489,17 +487,14 @@ struct StaticInitializerCtxt<'a, 'tcx: 'a> { impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { fn visit_expr(&mut self, ex: &Expr) { - match ex.node { - ast::ExprAddrOf(mutbl, ref base) => { - let base_cmt = self.bccx.cat_expr(&**base); - let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); - // Check that we don't allow borrows of unsafe static items. - if check_aliasability(self.bccx, ex.span, euv::AddrOf, - base_cmt, borrow_kind).is_err() { - return; // reported an error, no sense in reporting more. - } + if let ast::ExprAddrOf(mutbl, ref base) = ex.node { + let base_cmt = self.bccx.cat_expr(&**base); + let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); + // Check that we don't allow borrows of unsafe static items. + if check_aliasability(self.bccx, ex.span, euv::AddrOf, + base_cmt, borrow_kind).is_err() { + return; // reported an error, no sense in reporting more. } - _ => {} } visit::walk_expr(self, ex); diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 41901a3f431..d5a292b9f09 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -278,11 +278,8 @@ impl<'a, 'tcx> ConstEvalVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for ConstEvalVisitor<'a, 'tcx> { fn visit_ty(&mut self, t: &ast::Ty) { - match t.node { - ast::TyFixedLengthVec(_, ref expr) => { - check::check_const_in_type(self.tcx, &**expr, ty::mk_uint()); - } - _ => {} + if let ast::TyFixedLengthVec(_, ref expr) = t.node { + check::check_const_in_type(self.tcx, &**expr, ty::mk_uint()); } visit::walk_ty(self, t); @@ -321,10 +318,9 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P { ast::ExprCall(ref callee, ref args) => { let def = tcx.def_map.borrow()[callee.id].clone(); - match tcx.def_map.borrow_mut().entry(expr.id) { - Vacant(entry) => { entry.set(def); } - _ => {} - }; + if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) { + entry.set(def); + } let path = match def { def::DefStruct(def_id) => def_to_path(tcx, def_id), def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did), diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 71885a769f5..e67df0332dc 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -71,12 +71,9 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { debug!("effect: checking index with base type {}", ppaux::ty_to_string(self.tcx, base_type)); match base_type.sty { - ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty { - ty::ty_str => { - span_err!(self.tcx.sess, e.span, E0134, - "modification of string types is not allowed"); - } - _ => {} + ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => if ty::ty_str == ty.sty { + span_err!(self.tcx.sess, e.span, E0134, + "modification of string types is not allowed"); }, ty::ty_str => { span_err!(self.tcx.sess, e.span, E0135, @@ -165,13 +162,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { ast::ExprUnary(ast::UnDeref, ref base) => { let base_type = ty::node_id_to_type(self.tcx, base.id); debug!("effect: unary case, base type is {}", - ppaux::ty_to_string(self.tcx, base_type)); - match base_type.sty { - ty::ty_ptr(_) => { - self.require_unsafe(expr.span, - "dereference of unsafe pointer") - } - _ => {} + ppaux::ty_to_string(self.tcx, base_type)); + if let ty::ty_ptr(_) = base_type.sty { + self.require_unsafe(expr.span, "dereference of unsafe pointer") } } ast::ExprAssign(ref base, _) | ast::ExprAssignOp(_, ref base, _) => { @@ -181,14 +174,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { self.check_str_index(&**base); } ast::ExprInlineAsm(..) => { - self.require_unsafe(expr.span, "use of inline assembly") + self.require_unsafe(expr.span, "use of inline assembly"); } ast::ExprPath(..) => { - match ty::resolve_expr(self.tcx, expr) { - def::DefStatic(_, true) => { - self.require_unsafe(expr.span, "use of mutable static") - } - _ => {} + if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) { + self.require_unsafe(expr.span, "use of mutable static"); } } _ => {} diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 68d0ac93216..acfdf6fefb5 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -118,31 +118,26 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &ast::Expr) { - match expr.node { - ast::ExprPath(..) => { - match ty::resolve_expr(self.tcx, expr) { - DefFn(did, _) if self.def_id_is_transmute(did) => { - let typ = ty::node_id_to_type(self.tcx, expr.id); - match typ.sty { - ty_bare_fn(ref bare_fn_ty) - if bare_fn_ty.abi == RustIntrinsic => { - if let ty::FnConverging(to) = bare_fn_ty.sig.output { - let from = bare_fn_ty.sig.inputs[0]; - self.check_transmute(expr.span, from, to, expr.id); - } - } - _ => { - self.tcx - .sess - .span_bug(expr.span, - "transmute wasn't a bare fn?!"); + if let ast::ExprPath(..) = expr.node { + match ty::resolve_expr(self.tcx, expr) { + DefFn(did, _) if self.def_id_is_transmute(did) => { + let typ = ty::node_id_to_type(self.tcx, expr.id); + match typ.sty { + ty_bare_fn(ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { + if let ty::FnConverging(to) = bare_fn_ty.sig.output { + let from = bare_fn_ty.sig.inputs[0]; + self.check_transmute(expr.span, from, to, expr.id); } } + _ => { + self.tcx + .sess + .span_bug(expr.span, "transmute wasn't a bare fn?!"); + } } - _ => {} } + _ => {} } - _ => {} } visit::walk_expr(self, expr); @@ -153,4 +148,3 @@ pub fn check_crate(tcx: &ctxt) { visit::walk_crate(&mut IntrinsicCheckingVisitor { tcx: tcx }, tcx.map.krate()); } - diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index a09ceac11a5..fcc23d8ac55 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -445,9 +445,8 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { ast::ExprPath(_) => { let def = ir.tcx.def_map.borrow()[expr.id].clone(); debug!("expr {}: path that leads to {}", expr.id, def); - match def { - DefLocal(..) => ir.add_live_node_for_node(expr.id, ExprNode(expr.span)), - _ => {} + if let DefLocal(..) = def { + ir.add_live_node_for_node(expr.id, ExprNode(expr.span)); } visit::walk_expr(ir, expr); } @@ -463,13 +462,10 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { let mut call_caps = Vec::new(); ty::with_freevars(ir.tcx, expr.id, |freevars| { for fv in freevars.iter() { - match fv.def { - DefLocal(rv) => { - let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); - call_caps.push(CaptureInfo {ln: fv_ln, - var_nid: rv}); - } - _ => {} + if let DefLocal(rv) = fv.def { + let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); + call_caps.push(CaptureInfo {ln: fv_ln, + var_nid: rv}); } } }); @@ -1576,27 +1572,23 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_lvalue(&mut self, expr: &Expr) { match expr.node { - ast::ExprPath(_) => { - match self.ir.tcx.def_map.borrow()[expr.id].clone() { - DefLocal(nid) => { - // Assignment to an immutable variable or argument: only legal - // if there is no later assignment. If this local is actually - // mutable, then check for a reassignment to flag the mutability - // as being used. - let ln = self.live_node(expr.id, expr.span); - let var = self.variable(nid, expr.span); - self.warn_about_dead_assign(expr.span, expr.id, ln, var); - } - _ => {} + ast::ExprPath(_) => { + if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() { + // Assignment to an immutable variable or argument: only legal + // if there is no later assignment. If this local is actually + // mutable, then check for a reassignment to flag the mutability + // as being used. + let ln = self.live_node(expr.id, expr.span); + let var = self.variable(nid, expr.span); + self.warn_about_dead_assign(expr.span, expr.id, ln, var); + } } - } - - _ => { - // For other kinds of lvalues, no checks are required, - // and any embedded expressions are actually rvalues - visit::walk_expr(self, expr); - } - } + _ => { + // For other kinds of lvalues, no checks are required, + // and any embedded expressions are actually rvalues + visit::walk_expr(self, expr); + } + } } fn should_warn(&self, var: Variable) -> Option { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index ec939d19b72..5e182ba8337 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -310,19 +310,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { } ast::ItemTy(ref ty, _) if public_first => { - match ty.node { - ast::TyPath(_, id) => { - match self.tcx.def_map.borrow()[id].clone() { - def::DefPrimTy(..) | def::DefTyParam(..) => {}, - def => { - let did = def.def_id(); - if is_local(did) { - self.exported_items.insert(did.node); - } + if let ast::TyPath(_, id) = ty.node { + match self.tcx.def_map.borrow()[id].clone() { + def::DefPrimTy(..) | def::DefTyParam(..) => {}, + def => { + let did = def.def_id(); + if is_local(did) { + self.exported_items.insert(did.node); } } } - _ => {} } } @@ -771,11 +768,8 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { resolve::AllPublic => None, resolve::DependsOn(def) => ck_public(def), }; - match (v, t) { - (Some(_), Some(t)) => { - self.report_error(Some(t)); - }, - _ => {}, + if let (Some(_), Some(t)) = (v, t) { + self.report_error(Some(t)); } }, _ => {}, @@ -1001,9 +995,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { match ty::pat_ty(self.tcx, pattern).sty { ty::ty_struct(id, _) => { for (i, field) in fields.iter().enumerate() { - match field.node { - ast::PatWild(..) => continue, - _ => {} + if let ast::PatWild(..) = field.node { + continue } self.check_field(field.span, id, UnnamedField(i)); } @@ -1075,14 +1068,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> { self.tcx.sess.span_err(i.span, "unnecessary `pub`, imports \ in functions are never \ reachable"); - } else { - match i.node { - ast::ViewItemExternCrate(..) => { - self.tcx.sess.span_err(i.span, "`pub` visibility \ - is not allowed"); - } - _ => {} - } + } else if let ast::ViewItemExternCrate(..) = i.node { + self.tcx.sess.span_err(i.span, "`pub` visibility \ + is not allowed"); } } } @@ -1275,34 +1263,28 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { fn check_ty_param_bound(&self, span: Span, ty_param_bound: &ast::TyParamBound) { - match *ty_param_bound { - ast::TraitTyParamBound(ref trait_ref) => { - if !self.tcx.sess.features.borrow().visible_private_types && - self.path_is_private_type(trait_ref.trait_ref.ref_id) { + if let ast::TraitTyParamBound(ref trait_ref) = *ty_param_bound { + if !self.tcx.sess.features.borrow().visible_private_types && + self.path_is_private_type(trait_ref.trait_ref.ref_id) { self.tcx.sess.span_err(span, "private type in exported type \ parameter bound"); - } } - _ => {} } } } impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { - match ty.node { - ast::TyPath(_, path_id) => { - if self.inner.path_is_private_type(path_id) { - self.contains_private = true; - // found what we're looking for so let's stop - // working. - return - } else if self.at_outer_type { - self.outer_type_is_public_path = true; - } + if let ast::TyPath(_, path_id) = ty.node { + if self.inner.path_is_private_type(path_id) { + self.contains_private = true; + // found what we're looking for so let's stop + // working. + return + } else if self.at_outer_type { + self.outer_type_is_public_path = true; } - _ => {} } self.at_outer_type = false; visit::walk_ty(self, ty) @@ -1492,16 +1474,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_ty(&mut self, t: &ast::Ty) { - match t.node { - ast::TyPath(ref p, path_id) => { - if !self.tcx.sess.features.borrow().visible_private_types && - self.path_is_private_type(path_id) { - self.tcx.sess.span_err(p.span, - "private type in exported type \ - signature"); - } + if let ast::TyPath(ref p, path_id) = t.node { + if !self.tcx.sess.features.borrow().visible_private_types && + self.path_is_private_type(path_id) { + self.tcx.sess.span_err(p.span, + "private type in exported type signature"); } - _ => {} } visit::walk_ty(self, t) } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 7dcc0510a6a..96e1aacb0ce 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -264,18 +264,12 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // functions may still participate in some form of native interface, // but all other rust-only interfaces can be private (they will not // participate in linkage after this product is produced) - match *node { - ast_map::NodeItem(item) => { - match item.node { - ast::ItemFn(_, _, abi, _, _) => { - if abi != abi::Rust { - self.reachable_symbols.insert(search_item); - } - } - _ => {} + if let ast_map::NodeItem(item) = *node { + if let ast::ItemFn(_, _, abi, _, _) = item.node { + if abi != abi::Rust { + self.reachable_symbols.insert(search_item); } } - _ => {} } } else { // If we are building a library, then reachable symbols will diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index ae32a10f314..823bc2a6873 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -3052,22 +3052,15 @@ impl<'a> Resolver<'a> { match import_resolution.value_target { Some(ref target) if !target.shadowable => { - match *name_bindings.value_def.borrow() { - Some(ref value) => { - let msg = format!("import `{}` conflicts with value \ - in this module", - token::get_name(name).get()); - self.session.span_err(import_span, msg.as_slice()); - match value.value_span { - None => {} - Some(span) => { - self.session - .span_note(span, + if let Some(ref value) = *name_bindings.value_def.borrow() { + let msg = format!("import `{}` conflicts with value \ + in this module", + token::get_name(name).get()); + self.session.span_err(import_span, msg.as_slice()); + if let Some(span) = value.value_span { + self.session.span_note(span, "conflicting value here"); - } - } } - _ => {} } } Some(_) | None => {} @@ -3075,59 +3068,43 @@ impl<'a> Resolver<'a> { match import_resolution.type_target { Some(ref target) if !target.shadowable => { - match *name_bindings.type_def.borrow() { - Some(ref ty) => { - match ty.module_def { - None => { - let msg = format!("import `{}` conflicts with type in \ - this module", - token::get_name(name).get()); - self.session.span_err(import_span, msg.as_slice()); - match ty.type_span { - None => {} - Some(span) => { - self.session - .span_note(span, + if let Some(ref ty) = *name_bindings.type_def.borrow() { + match ty.module_def { + None => { + let msg = format!("import `{}` conflicts with type in \ + this module", + token::get_name(name).get()); + self.session.span_err(import_span, msg.as_slice()); + if let Some(span) = ty.type_span { + self.session.span_note(span, "note conflicting type here") - } - } } - Some(ref module_def) => { - match module_def.kind.get() { - ImplModuleKind => { - match ty.type_span { - None => { /* this can't ever happen */ } - Some(span) => { - let msg = format!("inherent implementations \ - are only allowed on types \ - defined in the current module"); - self.session - .span_err(span, msg.as_slice()); - self.session - .span_note(import_span, + } + Some(ref module_def) => { + match module_def.kind.get() { + ImplModuleKind => { + if let Some(span) = ty.type_span { + let msg = format!("inherent implementations \ + are only allowed on types \ + defined in the current module"); + self.session.span_err(span, msg.as_slice()); + self.session.span_note(import_span, "import from other module here") - } - } } - _ => { - let msg = format!("import `{}` conflicts with existing \ - submodule", - token::get_name(name).get()); - self.session.span_err(import_span, msg.as_slice()); - match ty.type_span { - None => {} - Some(span) => { - self.session - .span_note(span, + } + _ => { + let msg = format!("import `{}` conflicts with existing \ + submodule", + token::get_name(name).get()); + self.session.span_err(import_span, msg.as_slice()); + if let Some(span) = ty.type_span { + self.session.span_note(span, "note conflicting module here") - } - } } } } } } - _ => {} } } Some(_) | None => {} @@ -3269,25 +3246,16 @@ impl<'a> Resolver<'a> { search_module = module_def.clone(); // track extern crates for unused_extern_crate lint - match module_def.def_id.get() { - Some(did) => { - self.used_crates.insert(did.krate); - } - _ => {} + if let Some(did) = module_def.def_id.get() { + self.used_crates.insert(did.krate); } // Keep track of the closest // private module used when // resolving this import chain. - if !used_proxy && - !search_module.is_public { - match search_module.def_id - .get() { - Some(did) => { - closest_private = - LastMod(DependsOn(did)); - } - None => {} + if !used_proxy && !search_module.is_public { + if let Some(did) = search_module.def_id.get() { + closest_private = LastMod(DependsOn(did)); } } } @@ -3442,46 +3410,35 @@ impl<'a> Resolver<'a> { // all its imports in the usual way; this is because chains of // adjacent import statements are processed as though they mutated the // current scope. - match module_.import_resolutions.borrow().get(&name) { - None => { - // Not found; continue. - } - Some(import_resolution) => { - match (*import_resolution).target_for_namespace(namespace) { - None => { - // Not found; continue. - debug!("(resolving item in lexical scope) found \ - import resolution, but not in namespace {}", - namespace); - } - Some(target) => { - debug!("(resolving item in lexical scope) using \ - import resolution"); - // track used imports and extern crates as well - self.used_imports.insert((import_resolution.id(namespace), namespace)); - match target.target_module.def_id.get() { - Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); }, - _ => {} - } - return Success((target, false)); + if let Some(import_resolution) = module_.import_resolutions.borrow().get(&name) { + match (*import_resolution).target_for_namespace(namespace) { + None => { + // Not found; continue. + debug!("(resolving item in lexical scope) found \ + import resolution, but not in namespace {}", + namespace); + } + Some(target) => { + debug!("(resolving item in lexical scope) using \ + import resolution"); + // track used imports and extern crates as well + self.used_imports.insert((import_resolution.id(namespace), namespace)); + if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() { + self.used_crates.insert(kid); } + return Success((target, false)); } } } // Search for external modules. if namespace == TypeNS { - match module_.external_module_children.borrow().get(&name).cloned() { - None => {} - Some(module) => { - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module(module)); - debug!("lower name bindings succeeded"); - return Success((Target::new(module_, - name_bindings, - false), - false)); - } + if let Some(module) = module_.external_module_children.borrow().get(&name).cloned() { + let name_bindings = + Rc::new(Resolver::create_name_bindings_from_module(module)); + debug!("lower name bindings succeeded"); + return Success((Target::new(module_, name_bindings, false), + false)); } } @@ -3743,9 +3700,8 @@ impl<'a> Resolver<'a> { import"); // track used imports and extern crates as well self.used_imports.insert((import_resolution.id(namespace), namespace)); - match target.target_module.def_id.get() { - Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); }, - _ => {} + if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() { + self.used_crates.insert(kid); } return Success((target, true)); } @@ -3756,16 +3712,11 @@ impl<'a> Resolver<'a> { // Finally, search through external children. if namespace == TypeNS { - match module_.external_module_children.borrow().get(&name).cloned() { - None => {} - Some(module) => { - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module(module)); - return Success((Target::new(module_, - name_bindings, - false), - false)); - } + if let Some(module) = module_.external_module_children.borrow().get(&name).cloned() { + let name_bindings = + Rc::new(Resolver::create_name_bindings_from_module(module)); + return Success((Target::new(module_, name_bindings, false), + false)); } } @@ -4271,11 +4222,8 @@ impl<'a> Resolver<'a> { this.resolve_type(&*argument.ty); } - match ty_m.explicit_self.node { - SelfExplicit(ref typ, _) => { - this.resolve_type(&**typ) - } - _ => {} + if let SelfExplicit(ref typ, _) = ty_m.explicit_self.node { + this.resolve_type(&**typ) } if let ast::Return(ref ret_ty) = ty_m.decl.output { @@ -4563,19 +4511,14 @@ impl<'a> Resolver<'a> { &trait_reference.path))); // If it's a typedef, give a note - match def { - DefTy(..) => { - self.session.span_note( - trait_reference.path.span, - format!("`type` aliases cannot \ - be used for traits") - .as_slice()); - } - _ => {} + if let DefTy(..) = def { + self.session.span_note( + trait_reference.path.span, + format!("`type` aliases cannot be used for traits") + .as_slice()); } } } - } } } @@ -4637,9 +4580,8 @@ impl<'a> Resolver<'a> { method.id, rib_kind); - match method.pe_explicit_self().node { - SelfExplicit(ref typ, _) => self.resolve_type(&**typ), - _ => {} + if let SelfExplicit(ref typ, _) = method.pe_explicit_self().node { + self.resolve_type(&**typ); } self.resolve_function(rib_kind, @@ -5351,29 +5293,26 @@ impl<'a> Resolver<'a> { // Next, search import resolutions. match containing_module.import_resolutions.borrow().get(&name) { Some(import_resolution) if import_resolution.is_public => { - match (*import_resolution).target_for_namespace(namespace) { - Some(target) => { - match target.bindings.def_for_namespace(namespace) { - Some(def) => { - // Found it. - let id = import_resolution.id(namespace); - // track imports and extern crates as well - self.used_imports.insert((id, namespace)); - match target.target_module.def_id.get() { - Some(DefId{krate: kid, ..}) => { - self.used_crates.insert(kid); - }, - _ => {} - } - return ImportNameDefinition(def, LastMod(AllPublic)); - } - None => { - // This can happen with external impls, due to - // the imperfect way we read the metadata. + if let Some(target) = (*import_resolution).target_for_namespace(namespace) { + match target.bindings.def_for_namespace(namespace) { + Some(def) => { + // Found it. + let id = import_resolution.id(namespace); + // track imports and extern crates as well + self.used_imports.insert((id, namespace)); + match target.target_module.def_id.get() { + Some(DefId{krate: kid, ..}) => { + self.used_crates.insert(kid); + }, + _ => {} } + return ImportNameDefinition(def, LastMod(AllPublic)); + } + None => { + // This can happen with external impls, due to + // the imperfect way we read the metadata. } } - None => {} } } Some(..) | None => {} // Continue. @@ -5381,21 +5320,15 @@ impl<'a> Resolver<'a> { // Finally, search through external children. if namespace == TypeNS { - match containing_module.external_module_children.borrow() - .get(&name).cloned() { - None => {} - Some(module) => { - match module.def_id.get() { - None => {} // Continue. - Some(def_id) => { - // track used crates - self.used_crates.insert(def_id.krate); - let lp = if module.is_public {LastMod(AllPublic)} else { - LastMod(DependsOn(def_id)) - }; - return ChildNameDefinition(DefMod(def_id), lp); - } - } + if let Some(module) = containing_module.external_module_children.borrow() + .get(&name).cloned() { + if let Some(def_id) = module.def_id.get() { + // track used crates + self.used_crates.insert(def_id.krate); + let lp = if module.is_public {LastMod(AllPublic)} else { + LastMod(DependsOn(def_id)) + }; + return ChildNameDefinition(DefMod(def_id), lp); } } } @@ -5454,9 +5387,8 @@ impl<'a> Resolver<'a> { (def, last_private.or(lp)) } }; - match containing_module.def_id.get() { - Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); }, - _ => {} + if let Some(DefId{krate: kid, ..}) = containing_module.def_id.get() { + self.used_crates.insert(kid); } return Some(def); } @@ -6049,9 +5981,8 @@ impl<'a> Resolver<'a> { if self.trait_item_map.contains_key(&(name, did)) { add_trait_info(&mut found_traits, did, name); self.used_imports.insert((import.type_id, TypeNS)); - match target.target_module.def_id.get() { - Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); }, - _ => {} + if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() { + self.used_crates.insert(kid); } } } @@ -6128,15 +6059,13 @@ impl<'a> Resolver<'a> { match vi.node { ViewItemExternCrate(_, _, id) => { - match self.session.cstore.find_extern_mod_stmt_cnum(id) - { - Some(crate_num) => if !self.used_crates.contains(&crate_num) { - self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES, - id, - vi.span, - "unused extern crate".to_string()); - }, - _ => {} + if let Some(crate_num) = self.session.cstore.find_extern_mod_stmt_cnum(id) { + if !self.used_crates.contains(&crate_num) { + self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES, + id, + vi.span, + "unused extern crate".to_string()); + } } }, ViewItemUse(ref p) => { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 4d0474b68da..994fe2e9e27 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -69,24 +69,18 @@ impl<'v> Visitor<'v> for Annotator { fn visit_item(&mut self, i: &Item) { self.annotate(i.id, &i.attrs, |v| visit::walk_item(v, i)); - match i.node { - ast::ItemStruct(ref sd, _) => { - sd.ctor_id.map(|id| { - self.annotate(id, &i.attrs, |_| {}) - }); - } - _ => {} + if let ast::ItemStruct(ref sd, _) = i.node { + sd.ctor_id.map(|id| { + self.annotate(id, &i.attrs, |_| {}) + }); } } fn visit_fn(&mut self, fk: FnKind<'v>, _: &'v FnDecl, _: &'v Block, _: Span, _: NodeId) { - match fk { - FkMethod(_, _, meth) => { - // Methods are not already annotated, so we annotate it - self.annotate(meth.id, &meth.attrs, |_| {}); - } - _ => {} + if let FkMethod(_, _, meth) = fk { + // Methods are not already annotated, so we annotate it + self.annotate(meth.id, &meth.attrs, |_| {}); } // Items defined in a function body have no reason to have // a stability attribute, so we don't recurse. diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index cd7260b1812..e8b292aac6d 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -211,9 +211,8 @@ fn push_obligations_for_param_bounds<'tcx>( builtin_bound, recursion_depth, param_ty); - match obligation { - Ok(ob) => obligations.push(space, ob), - _ => {} + if let Ok(ob) = obligation { + obligations.push(space, ob); } } @@ -383,4 +382,3 @@ impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> { ty::type_err_to_str(tcx, self) } } - diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 0574806c1b7..35aed356303 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1893,11 +1893,8 @@ impl FlagComputation { } &ty_closure(ref f) => { - match f.store { - RegionTraitStore(r, _) => { - self.add_region(r); - } - _ => {} + if let RegionTraitStore(r, _) = f.store { + self.add_region(r); } self.add_fn_sig(&f.sig); self.add_bounds(&f.bounds); @@ -3664,9 +3661,8 @@ pub fn adjust_ty<'tcx>(cx: &ctxt<'tcx>, method_type: |typeck::MethodCall| -> Option>) -> Ty<'tcx> { - match unadjusted_ty.sty { - ty_err => return unadjusted_ty, - _ => {} + if let ty_err = unadjusted_ty.sty { + return unadjusted_ty; } return match adjustment { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 40a38d45fa0..641cbd11d64 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -441,21 +441,19 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { // Add pattern bindings. fn visit_pat(&mut self, p: &ast::Pat) { - match p.node { - ast::PatIdent(_, ref path1, _) - if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => { - let var_ty = self.assign(p.span, p.id, None); - - self.fcx.require_type_is_sized(var_ty, p.span, - traits::VariableType(p.id)); - - debug!("Pattern binding {} is assigned to {} with type {}", - token::get_ident(path1.node), - self.fcx.infcx().ty_to_string( - self.fcx.inh.locals.borrow()[p.id].clone()), - var_ty.repr(self.fcx.tcx())); - } - _ => {} + if let ast::PatIdent(_, ref path1, _) = p.node { + if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) { + let var_ty = self.assign(p.span, p.id, None); + + self.fcx.require_type_is_sized(var_ty, p.span, + traits::VariableType(p.id)); + + debug!("Pattern binding {} is assigned to {} with type {}", + token::get_ident(path1.node), + self.fcx.infcx().ty_to_string( + self.fcx.inh.locals.borrow()[p.id].clone()), + var_ty.repr(self.fcx.tcx())); + } } visit::walk_pat(self, p); } @@ -681,14 +679,11 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { "foreign items may not have type parameters"); } - match item.node { - ast::ForeignItemFn(ref fn_decl, _) => { - if fn_decl.variadic && m.abi != abi::C { - span_err!(ccx.tcx.sess, item.span, E0045, - "variadic function must have C calling convention"); - } + if let ast::ForeignItemFn(ref fn_decl, _) = item.node { + if fn_decl.variadic && m.abi != abi::C { + span_err!(ccx.tcx.sess, item.span, E0045, + "variadic function must have C calling convention"); } - _ => {} } } } @@ -1808,9 +1803,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { traits::ObligationCause::new(span, code), ty, bound); - match obligation { - Ok(ob) => self.register_obligation(ob), - _ => {} + if let Ok(ob) = obligation { + self.register_obligation(ob); } } @@ -3763,19 +3757,16 @@ fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, check_expr(fcx, &**subexpr); let mut checked = false; - match place.node { - ast::ExprPath(ref path) => { - // FIXME(pcwalton): For now we hardcode the two permissible - // places: the exchange heap and the managed heap. - let definition = lookup_def(fcx, path.span, place.id); - let def_id = definition.def_id(); - let referent_ty = fcx.expr_ty(&**subexpr); - if tcx.lang_items.exchange_heap() == Some(def_id) { - fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty)); - checked = true - } + if let ast::ExprPath(ref path) = place.node { + // FIXME(pcwalton): For now we hardcode the two permissible + // places: the exchange heap and the managed heap. + let definition = lookup_def(fcx, path.span, place.id); + let def_id = definition.def_id(); + let referent_ty = fcx.expr_ty(&**subexpr); + if tcx.lang_items.exchange_heap() == Some(def_id) { + fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty)); + checked = true } - _ => {} } if !checked { @@ -4129,11 +4120,8 @@ fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } ast::ExprCast(ref e, ref t) => { - match t.node { - ast::TyFixedLengthVec(_, ref count_expr) => { - check_expr_with_hint(fcx, &**count_expr, ty::mk_uint()); - } - _ => {} + if let ast::TyFixedLengthVec(_, ref count_expr) = t.node { + check_expr_with_hint(fcx, &**count_expr, ty::mk_uint()); } check_cast(fcx, expr, &**e, &**t); } @@ -4524,15 +4512,12 @@ pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) { let t = fcx.local_ty(local.span, local.id); fcx.write_ty(local.id, t); - match local.init { - Some(ref init) => { - check_decl_initializer(fcx, local.id, &**init); - let init_ty = fcx.expr_ty(&**init); - if ty::type_is_error(init_ty) { - fcx.write_ty(local.id, init_ty); - } + if let Some(ref init) = local.init { + check_decl_initializer(fcx, local.id, &**init); + let init_ty = fcx.expr_ty(&**init); + if ty::type_is_error(init_ty) { + fcx.write_ty(local.id, init_ty); } - _ => {} } let pcx = pat_ctxt { diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index bc6e7d9d87f..08f7f9cf5e3 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -672,12 +672,9 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { } None => rcx.resolve_node_type(base.id) }; - match base_ty.sty { - ty::ty_rptr(r_ptr, _) => { - mk_subregion_due_to_dereference( - rcx, expr.span, ty::ReScope(CodeExtent::from_node_id(expr.id)), r_ptr); - } - _ => {} + if let ty::ty_rptr(r_ptr, _) = base_ty.sty { + mk_subregion_due_to_dereference( + rcx, expr.span, ty::ReScope(CodeExtent::from_node_id(expr.id)), r_ptr); } visit::walk_expr(rcx, expr); @@ -943,12 +940,9 @@ fn check_expr_fn_block(rcx: &mut Rcx, let cause = traits::ObligationCause::new(freevar.span, code); let obligation = traits::obligation_for_builtin_bound(rcx.tcx(), cause, var_ty, builtin_bound); - match obligation { - Ok(obligation) => { - rcx.fcx.inh.fulfillment_cx.borrow_mut().register_obligation(rcx.tcx(), - obligation) - } - _ => {} + if let Ok(obligation) = obligation { + rcx.fcx.inh.fulfillment_cx.borrow_mut().register_obligation(rcx.tcx(), + obligation) } } type_must_outlive( @@ -1036,20 +1030,17 @@ fn check_expr_fn_block(rcx: &mut Rcx, // after checking the inner closure (and hence // determining the final borrow_kind) and propagate that as // a constraint on the outer closure. - match freevar.def { - def::DefUpvar(var_id, outer_closure_id, _) => { - // thing being captured is itself an upvar: - let outer_upvar_id = ty::UpvarId { - var_id: var_id, - closure_expr_id: outer_closure_id }; - let inner_upvar_id = ty::UpvarId { - var_id: var_id, - closure_expr_id: expr.id }; - link_upvar_borrow_kind_for_nested_closures(rcx, - inner_upvar_id, - outer_upvar_id); - } - _ => {} + if let def::DefUpvar(var_id, outer_closure_id, _) = freevar.def { + // thing being captured is itself an upvar: + let outer_upvar_id = ty::UpvarId { + var_id: var_id, + closure_expr_id: outer_closure_id }; + let inner_upvar_id = ty::UpvarId { + var_id: var_id, + closure_expr_id: expr.id }; + link_upvar_borrow_kind_for_nested_closures(rcx, + inner_upvar_id, + outer_upvar_id); } } } @@ -1199,12 +1190,9 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, None => derefd_ty }; - match derefd_ty.sty { - ty::ty_rptr(r_ptr, _) => { - mk_subregion_due_to_dereference(rcx, deref_expr.span, - r_deref_expr, r_ptr); - } - _ => {} + if let ty::ty_rptr(r_ptr, _) = derefd_ty.sty { + mk_subregion_due_to_dereference(rcx, deref_expr.span, + r_deref_expr, r_ptr); } match ty::deref(derefd_ty, true) { @@ -1235,16 +1223,14 @@ fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, rcx.fcx.infcx().ty_to_string(indexed_ty)); let r_index_expr = ty::ReScope(CodeExtent::from_node_id(index_expr.id)); - match indexed_ty.sty { - ty::ty_rptr(r_ptr, mt) => match mt.ty.sty { + if let ty::ty_rptr(r_ptr, mt) = indexed_ty.sty { + match mt.ty.sty { ty::ty_vec(_, None) | ty::ty_str => { rcx.fcx.mk_subr(infer::IndexSlice(index_expr.span), r_index_expr, r_ptr); } _ => {} - }, - - _ => {} + } } } @@ -1615,21 +1601,18 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, // upvar borrow kind to mutable/unique. Record the // information needed to perform the recursive link in the // maybe link map. - match note { - mc::NoteUpvarRef(upvar_id) => { - let link = MaybeLink { - span: span, - borrow_region: borrow_region, - borrow_kind: new_borrow_kind, - borrow_cmt: ref_cmt - }; - - match rcx.maybe_links.borrow_mut().entry(upvar_id) { - Vacant(entry) => { entry.set(vec![link]); } - Occupied(entry) => { entry.into_mut().push(link); } - } - }, - _ => {} + if let mc::NoteUpvarRef(upvar_id) = note { + let link = MaybeLink { + span: span, + borrow_region: borrow_region, + borrow_kind: new_borrow_kind, + borrow_cmt: ref_cmt + }; + + match rcx.maybe_links.borrow_mut().entry(upvar_id) { + Vacant(entry) => { entry.set(vec![link]); } + Occupied(entry) => { entry.into_mut().push(link); } + } } return None; @@ -1673,19 +1656,15 @@ fn adjust_upvar_borrow_kind_for_mut<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, mc::cat_deref(base, _, mc::BorrowedPtr(..)) | mc::cat_deref(base, _, mc::Implicit(..)) => { - match cmt.note { - mc::NoteUpvarRef(ref upvar_id) => { - // if this is an implicit deref of an - // upvar, then we need to modify the - // borrow_kind of the upvar to make sure it - // is inferred to mutable if necessary - let mut upvar_borrow_map = - rcx.fcx.inh.upvar_borrow_map.borrow_mut(); - let ub = &mut (*upvar_borrow_map)[*upvar_id]; - return adjust_upvar_borrow_kind(rcx, *upvar_id, ub, ty::MutBorrow); - } - - _ => {} + if let mc::NoteUpvarRef(ref upvar_id) = cmt.note { + // if this is an implicit deref of an + // upvar, then we need to modify the + // borrow_kind of the upvar to make sure it + // is inferred to mutable if necessary + let mut upvar_borrow_map = + rcx.fcx.inh.upvar_borrow_map.borrow_mut(); + let ub = &mut (*upvar_borrow_map)[*upvar_id]; + return adjust_upvar_borrow_kind(rcx, *upvar_id, ub, ty::MutBorrow); } // assignment to deref of an `&mut` @@ -1724,18 +1703,14 @@ fn adjust_upvar_borrow_kind_for_unique<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, cmt: mc::c mc::cat_deref(base, _, mc::BorrowedPtr(..)) | mc::cat_deref(base, _, mc::Implicit(..)) => { - match cmt.note { - mc::NoteUpvarRef(ref upvar_id) => { - // if this is an implicit deref of an - // upvar, then we need to modify the - // borrow_kind of the upvar to make sure it - // is inferred to unique if necessary - let mut ub = rcx.fcx.inh.upvar_borrow_map.borrow_mut(); - let ub = &mut (*ub)[*upvar_id]; - return adjust_upvar_borrow_kind(rcx, *upvar_id, ub, ty::UniqueImmBorrow); - } - - _ => {} + if let mc::NoteUpvarRef(ref upvar_id) = cmt.note { + // if this is an implicit deref of an + // upvar, then we need to modify the + // borrow_kind of the upvar to make sure it + // is inferred to unique if necessary + let mut ub = rcx.fcx.inh.upvar_borrow_map.borrow_mut(); + let ub = &mut (*ub)[*upvar_id]; + return adjust_upvar_borrow_kind(rcx, *upvar_id, ub, ty::UniqueImmBorrow); } // for a borrowed pointer to be unique, its diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 51978a01f71..84cb74b4de2 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -208,15 +208,13 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, }; let ref sig = method.fty.sig; for &input_ty in sig.inputs[1..].iter() { - match check_for_self_ty(input_ty) { - Some(msg) => msgs.push(msg), - _ => {} + if let Some(msg) = check_for_self_ty(input_ty) { + msgs.push(msg); } } if let ty::FnConverging(result_type) = sig.output { - match check_for_self_ty(result_type) { - Some(msg) => msgs.push(msg), - _ => {} + if let Some(msg) = check_for_self_ty(result_type) { + msgs.push(msg); } } @@ -290,10 +288,9 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, traits::ObjectCastObligation(object_trait_ty)), referent_ty, builtin_bound); - match obligation { - Ok(obligation) => fcx.register_obligation(obligation), - _ => {} - } + if let Ok(obligation) = obligation { + fcx.register_obligation(obligation); + } } object_trait_ref diff --git a/src/librustc/middle/typeck/check/wf.rs b/src/librustc/middle/typeck/check/wf.rs index 502e37aa9f3..8535ec4fa6e 100644 --- a/src/librustc/middle/typeck/check/wf.rs +++ b/src/librustc/middle/typeck/check/wf.rs @@ -127,9 +127,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { cause, field.ty, ty::BoundSized); - match obligation { - Ok(obligation) => fcx.register_obligation(obligation), - _ => {} + if let Ok(obligation) = obligation { + fcx.register_obligation(obligation); } } } @@ -233,9 +232,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { cause, trait_ref.self_ty(), builtin_bound); - match obligation { - Ok (obligation) => fcx.register_obligation(obligation), - _ => {} + if let Ok(obligation) = obligation { + fcx.register_obligation(obligation); } } for trait_bound in trait_def.bounds.trait_bounds.iter() { @@ -471,9 +469,8 @@ fn check_struct_safe_for_destructor<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cause, self_ty, ty::BoundSend); - match obligation { - Ok(obligation) => fcx.register_obligation(obligation), - _ => {} + if let Ok(obligation) = obligation { + fcx.register_obligation(obligation); } } else { span_err!(fcx.tcx().sess, span, E0141, diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 3a62978ed00..061d2a2f5c4 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -258,112 +258,96 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_id: ast::NodeId, trait_def: &ty::TraitDef<'tcx>) { let tcx = ccx.tcx; - match tcx.map.get(trait_id) { - ast_map::NodeItem(item) => { - match item.node { - ast::ItemTrait(_, _, _, ref trait_items) => { - // For each method, construct a suitable ty::Method and - // store it into the `tcx.impl_or_trait_items` table: - for trait_item in trait_items.iter() { - match *trait_item { - ast::RequiredMethod(_) | - ast::ProvidedMethod(_) => { - let ty_method = Rc::new(match *trait_item { - ast::RequiredMethod(ref m) => { - ty_method_of_trait_method( - ccx, - trait_id, - &trait_def.generics, - trait_items.as_slice(), - &m.id, - &m.ident.name, - &m.explicit_self, - m.abi, - &m.generics, - &m.fn_style, - &*m.decl) - } - ast::ProvidedMethod(ref m) => { - ty_method_of_trait_method( - ccx, - trait_id, - &trait_def.generics, - trait_items.as_slice(), - &m.id, - &m.pe_ident().name, - m.pe_explicit_self(), - m.pe_abi(), - m.pe_generics(), - &m.pe_fn_style(), - &*m.pe_fn_decl()) - } - ast::TypeTraitItem(ref at) => { - tcx.sess.span_bug(at.ty_param.span, - "there shouldn't \ - be a type trait \ - item here") - } - }); - - debug!("ty_method_of_trait_method yielded {} \ - for method {} of trait {}", - ty_method.repr(ccx.tcx), - trait_item.repr(ccx.tcx), - local_def(trait_id).repr(ccx.tcx)); - - make_method_ty(ccx, &*ty_method); - - tcx.impl_or_trait_items - .borrow_mut() - .insert(ty_method.def_id, - ty::MethodTraitItem(ty_method)); + if let ast_map::NodeItem(item) = tcx.map.get(trait_id) { + if let ast::ItemTrait(_, _, _, ref trait_items) = item.node { + // For each method, construct a suitable ty::Method and + // store it into the `tcx.impl_or_trait_items` table: + for trait_item in trait_items.iter() { + match *trait_item { + ast::RequiredMethod(_) | + ast::ProvidedMethod(_) => { + let ty_method = Rc::new(match *trait_item { + ast::RequiredMethod(ref m) => { + ty_method_of_trait_method( + ccx, + trait_id, + &trait_def.generics, + trait_items.as_slice(), + &m.id, + &m.ident.name, + &m.explicit_self, + m.abi, + &m.generics, + &m.fn_style, + &*m.decl) } - ast::TypeTraitItem(ref ast_associated_type) => { - let trait_did = local_def(trait_id); - let associated_type = ty::AssociatedType { - name: ast_associated_type.ty_param.ident.name, - vis: ast::Public, - def_id: local_def(ast_associated_type.ty_param.id), - container: TraitContainer(trait_did), - }; - - let trait_item = ty::TypeTraitItem(Rc::new( - associated_type)); - tcx.impl_or_trait_items - .borrow_mut() - .insert(associated_type.def_id, - trait_item); + ast::ProvidedMethod(ref m) => { + ty_method_of_trait_method( + ccx, + trait_id, + &trait_def.generics, + trait_items.as_slice(), + &m.id, + &m.pe_ident().name, + m.pe_explicit_self(), + m.pe_abi(), + m.pe_generics(), + &m.pe_fn_style(), + &*m.pe_fn_decl()) } - } - } - - // Add an entry mapping - let trait_item_def_ids = - Rc::new(trait_items.iter() - .map(|ti| { - match *ti { - ast::RequiredMethod(ref ty_method) => { - ty::MethodTraitItemId(local_def( - ty_method.id)) - } - ast::ProvidedMethod(ref method) => { - ty::MethodTraitItemId(local_def( - method.id)) - } - ast::TypeTraitItem(ref typedef) => { - ty::TypeTraitItemId(local_def(typedef.ty_param.id)) - } + ast::TypeTraitItem(ref at) => { + tcx.sess.span_bug(at.ty_param.span, + "there shouldn't be a type trait item here") } - }).collect()); + }); + + debug!("ty_method_of_trait_method yielded {} for method {} of trait {}", + ty_method.repr(ccx.tcx), + trait_item.repr(ccx.tcx), + local_def(trait_id).repr(ccx.tcx)); + + make_method_ty(ccx, &*ty_method); - let trait_def_id = local_def(trait_id); - tcx.trait_item_def_ids.borrow_mut() - .insert(trait_def_id, trait_item_def_ids); + tcx.impl_or_trait_items + .borrow_mut() + .insert(ty_method.def_id, ty::MethodTraitItem(ty_method)); + } + ast::TypeTraitItem(ref ast_associated_type) => { + let trait_did = local_def(trait_id); + let associated_type = ty::AssociatedType { + name: ast_associated_type.ty_param.ident.name, + vis: ast::Public, + def_id: local_def(ast_associated_type.ty_param.id), + container: TraitContainer(trait_did), + }; + + let trait_item = ty::TypeTraitItem(Rc::new(associated_type)); + tcx.impl_or_trait_items + .borrow_mut() + .insert(associated_type.def_id, trait_item); + } } - _ => {} // Ignore things that aren't traits. } + + // Add an entry mapping + let trait_item_def_ids = + Rc::new(trait_items.iter().map(|ti| { + match *ti { + ast::RequiredMethod(ref ty_method) => { + ty::MethodTraitItemId(local_def(ty_method.id)) + } + ast::ProvidedMethod(ref method) => { + ty::MethodTraitItemId(local_def(method.id)) + } + ast::TypeTraitItem(ref typedef) => { + ty::TypeTraitItemId(local_def(typedef.ty_param.id)) + } + } + }).collect()); + + let trait_def_id = local_def(trait_id); + tcx.trait_item_def_ids.borrow_mut().insert(trait_def_id, trait_item_def_ids); } - _ => { /* Ignore things that aren't traits */ } } fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) { @@ -664,17 +648,13 @@ fn is_associated_type_valid_for_param(ty: Ty, trait_id: ast::DefId, generics: &ty::Generics) -> bool { - match ty.sty { - ty::ty_param(param_ty) => { - let type_parameter = generics.types.get(param_ty.space, - param_ty.idx); - for trait_bound in type_parameter.bounds.trait_bounds.iter() { - if trait_bound.def_id == trait_id { - return true - } + if let ty::ty_param(param_ty) = ty.sty { + let type_parameter = generics.types.get(param_ty.space, param_ty.idx); + for trait_bound in type_parameter.bounds.trait_bounds.iter() { + if trait_bound.def_id == trait_id { + return true } } - _ => {} } false @@ -1352,9 +1332,8 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, -> Rc> { let def_id = local_def(it.id); let tcx = ccx.tcx; - match tcx.trait_defs.borrow().get(&def_id) { - Some(def) => return def.clone(), - _ => {} + if let Some(def) = tcx.trait_defs.borrow().get(&def_id) { + return def.clone(); } let (generics, unbound, bounds, items) = match it.node { @@ -1452,9 +1431,8 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) -> ty::Polytype<'tcx> { let def_id = local_def(it.id); let tcx = ccx.tcx; - match tcx.tcache.borrow().get(&def_id) { - Some(pty) => return pty.clone(), - _ => {} + if let Some(pty) = tcx.tcache.borrow().get(&def_id) { + return pty.clone(); } match it.node { ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => { @@ -2146,54 +2124,51 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>( explicit_self: &ast::ExplicitSelf, body_id: ast::NodeId) { - match explicit_self.node { - ast::SelfExplicit(ref ast_type, _) => { - let typ = crate_context.to_ty(rs, &**ast_type); - let base_type = match typ.sty { - ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty, - ty::ty_uniq(typ) => typ, - _ => typ, - }; + if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node { + let typ = crate_context.to_ty(rs, &**ast_type); + let base_type = match typ.sty { + ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty, + ty::ty_uniq(typ) => typ, + _ => typ, + }; - let body_scope = region::CodeExtent::from_node_id(body_id); - - // "Required type" comes from the trait definition. It may - // contain late-bound regions from the method, but not the - // trait (since traits only have early-bound region - // parameters). - assert!(!ty::type_escapes_depth(required_type, 1)); - let required_type_free = - ty::liberate_late_bound_regions( - crate_context.tcx, body_scope, &ty::bind(required_type)).value; - - // The "base type" comes from the impl. It may have late-bound - // regions from the impl or the method. - let base_type_free = // liberate impl regions: - ty::liberate_late_bound_regions( - crate_context.tcx, body_scope, &ty::bind(ty::bind(base_type))).value.value; - let base_type_free = // liberate method regions: - ty::liberate_late_bound_regions( - crate_context.tcx, body_scope, &ty::bind(base_type_free)).value; - - debug!("required_type={} required_type_free={} \ - base_type={} base_type_free={}", - required_type.repr(crate_context.tcx), - required_type_free.repr(crate_context.tcx), - base_type.repr(crate_context.tcx), - base_type_free.repr(crate_context.tcx)); - let infcx = infer::new_infer_ctxt(crate_context.tcx); - drop(typeck::require_same_types(crate_context.tcx, - Some(&infcx), - false, - explicit_self.span, - base_type_free, - required_type_free, - || { + let body_scope = region::CodeExtent::from_node_id(body_id); + + // "Required type" comes from the trait definition. It may + // contain late-bound regions from the method, but not the + // trait (since traits only have early-bound region + // parameters). + assert!(!ty::type_escapes_depth(required_type, 1)); + let required_type_free = + ty::liberate_late_bound_regions( + crate_context.tcx, body_scope, &ty::bind(required_type)).value; + + // The "base type" comes from the impl. It may have late-bound + // regions from the impl or the method. + let base_type_free = // liberate impl regions: + ty::liberate_late_bound_regions( + crate_context.tcx, body_scope, &ty::bind(ty::bind(base_type))).value.value; + let base_type_free = // liberate method regions: + ty::liberate_late_bound_regions( + crate_context.tcx, body_scope, &ty::bind(base_type_free)).value; + + debug!("required_type={} required_type_free={} \ + base_type={} base_type_free={}", + required_type.repr(crate_context.tcx), + required_type_free.repr(crate_context.tcx), + base_type.repr(crate_context.tcx), + base_type_free.repr(crate_context.tcx)); + let infcx = infer::new_infer_ctxt(crate_context.tcx); + drop(typeck::require_same_types(crate_context.tcx, + Some(&infcx), + false, + explicit_self.span, + base_type_free, + required_type_free, + || { format!("mismatched self type: expected `{}`", ppaux::ty_to_string(crate_context.tcx, required_type)) - })); - infcx.resolve_regions_and_report_errors(); - } - _ => {} + })); + infcx.resolve_regions_and_report_errors(); } } diff --git a/src/librustc/plugin/build.rs b/src/librustc/plugin/build.rs index 457fcb861e6..a8018662d29 100644 --- a/src/librustc/plugin/build.rs +++ b/src/librustc/plugin/build.rs @@ -23,14 +23,11 @@ struct RegistrarFinder { impl<'v> Visitor<'v> for RegistrarFinder { fn visit_item(&mut self, item: &ast::Item) { - match item.node { - ast::ItemFn(..) => { - if attr::contains_name(item.attrs.as_slice(), - "plugin_registrar") { - self.registrars.push((item.id, item.span)); - } + if let ast::ItemFn(..) = item.node { + if attr::contains_name(item.attrs.as_slice(), + "plugin_registrar") { + self.registrars.push((item.id, item.span)); } - _ => {} } visit::walk_item(self, item); diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 3715256e3ec..d8cdffe2100 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -139,39 +139,27 @@ pub fn find_crate_name(sess: Option<&Session>, let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name")) .and_then(|at| at.value_str().map(|s| (at, s))); - match sess { - Some(sess) => { - match sess.opts.crate_name { - Some(ref s) => { - match attr_crate_name { - Some((attr, ref name)) if s.as_slice() != name.get() => { - let msg = format!("--crate-name and #[crate_name] \ - are required to match, but `{}` \ - != `{}`", s, name); - sess.span_err(attr.span, msg.as_slice()); - } - _ => {}, - } - return validate(s.clone(), None); + if let Some(sess) = sess { + if let Some(ref s) = sess.opts.crate_name { + if let Some((attr, ref name)) = attr_crate_name { + if s.as_slice() != name.get() { + let msg = format!("--crate-name and #[crate_name] are \ + required to match, but `{}` != `{}`", + s, name); + sess.span_err(attr.span, msg.as_slice()); } - None => {} } + return validate(s.clone(), None); } - None => {} } - match attr_crate_name { - Some((attr, s)) => return validate(s.get().to_string(), Some(attr.span)), - None => {} + if let Some((attr, s)) = attr_crate_name { + return validate(s.get().to_string(), Some(attr.span)); } - match *input { - FileInput(ref path) => { - match path.filestem_str() { - Some(s) => return validate(s.to_string(), None), - None => {} - } + if let FileInput(ref path) = *input { + if let Some(s) = path.filestem_str() { + return validate(s.to_string(), None); } - _ => {} } "rust-out".to_string() diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index f5c732d9adc..7a41be1dbe4 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1073,16 +1073,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { fn visit_generics(&mut self, generics: &ast::Generics) { for param in generics.ty_params.iter() { for bound in param.bounds.iter() { - match *bound { - ast::TraitTyParamBound(ref trait_ref) => { - self.process_trait_ref(&trait_ref.trait_ref, None); - } - _ => {} + if let ast::TraitTyParamBound(ref trait_ref) = *bound { + self.process_trait_ref(&trait_ref.trait_ref, None); } } - match param.default { - Some(ref ty) => self.visit_ty(&**ty), - None => {} + if let Some(ref ty) = param.default { + self.visit_ty(&**ty); } } } diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index e8b759fa1a2..ada46ab7db7 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -438,14 +438,11 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } ast::PatVec(ref before, Some(ref slice), ref after) => { - match slice.node { - ast::PatIdent(_, ref path, None) => { - let subslice_val = bind_subslice_pat( - bcx, this.id, val, - before.len(), after.len()); - bound_ptrs.push((path.node, subslice_val)); - } - _ => {} + if let ast::PatIdent(_, ref path, None) = slice.node { + let subslice_val = bind_subslice_pat( + bcx, this.id, val, + before.len(), after.len()); + bound_ptrs.push((path.node, subslice_val)); } } _ => {} @@ -835,9 +832,8 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let datum = Datum::new(llval, binding_info.ty, Lvalue); call_lifetime_start(bcx, llbinding); bcx = datum.store_to(bcx, llbinding); - match cs { - Some(cs) => bcx.fcx.schedule_lifetime_end(cs, llbinding), - _ => {} + if let Some(cs) = cs { + bcx.fcx.schedule_lifetime_end(cs, llbinding); } llbinding @@ -851,12 +847,9 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }; let datum = Datum::new(llval, binding_info.ty, Lvalue); - match cs { - Some(cs) => { - bcx.fcx.schedule_drop_and_zero_mem(cs, llval, binding_info.ty); - bcx.fcx.schedule_lifetime_end(cs, binding_info.llmatch); - } - _ => {} + if let Some(cs) = cs { + bcx.fcx.schedule_drop_and_zero_mem(cs, llval, binding_info.ty); + bcx.fcx.schedule_lifetime_end(cs, binding_info.llmatch); } debug!("binding {} to {}", @@ -894,9 +887,8 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let val = val.to_llbool(bcx); for (_, &binding_info) in data.bindings_map.iter() { - match binding_info.trmode { - TrByCopy(llbinding) => call_lifetime_end(bcx, llbinding), - _ => {} + if let TrByCopy(llbinding) = binding_info.trmode { + call_lifetime_end(bcx, llbinding); } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 52e54a4a261..9d6d1bc4a9e 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2212,21 +2212,18 @@ pub fn update_linkage(ccx: &CrateContext, OriginalTranslation => {}, } - match id { - Some(id) => { - let item = ccx.tcx().map.get(id); - if let ast_map::NodeItem(i) = item { - if let Some(name) = attr::first_attr_value_str_by_name(i.attrs[], "linkage") { - if let Some(linkage) = llvm_linkage_by_name(name.get()) { - llvm::SetLinkage(llval, linkage); - } else { - ccx.sess().span_fatal(i.span, "invalid linkage specified"); - } - return; + if let Some(id) = id { + let item = ccx.tcx().map.get(id); + if let ast_map::NodeItem(i) = item { + if let Some(name) = attr::first_attr_value_str_by_name(i.attrs[], "linkage") { + if let Some(linkage) = llvm_linkage_by_name(name.get()) { + llvm::SetLinkage(llval, linkage); + } else { + ccx.sess().span_fatal(i.span, "invalid linkage specified"); } + return; } } - _ => {} } match id { @@ -2492,11 +2489,8 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< _ => {} } - match ret_ty.sty { - ty::ty_bool => { - attrs.ret(llvm::ZExtAttribute); - } - _ => {} + if let ty::ty_bool = ret_ty.sty { + attrs.ret(llvm::ZExtAttribute); } } } @@ -2543,11 +2537,8 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< attrs.arg(idx, llvm::ReadOnlyAttribute); } - match b { - ReLateBound(_, BrAnon(_)) => { - attrs.arg(idx, llvm::NoCaptureAttribute); - } - _ => {} + if let ReLateBound(_, BrAnon(_)) = b { + attrs.arg(idx, llvm::NoCaptureAttribute); } } diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 5d713526a3d..80a17465d78 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -92,11 +92,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) debug!("callee::trans(expr={})", expr.repr(bcx.tcx())); // pick out special kinds of expressions that can be called: - match expr.node { - ast::ExprPath(_) => { - return trans_def(bcx, bcx.def(expr.id), expr); - } - _ => {} + if let ast::ExprPath(_) = expr.node { + return trans_def(bcx, bcx.def(expr.id), expr); } // any other expressions are closures: diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index d7da83ddb0d..33393ba76c5 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -236,11 +236,8 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// Returns the id of the top-most loop scope fn top_loop_scope(&self) -> ast::NodeId { for scope in self.scopes.borrow().iter().rev() { - match scope.kind { - LoopScopeKind(id, _) => { - return id; - } - _ => {} + if let LoopScopeKind(id, _) = scope.kind { + return id; } } self.ccx.sess().bug("no loop scope found"); diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index aa549c99d02..42daf718816 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -171,9 +171,8 @@ pub fn get_const_val(cx: &CrateContext, def_id = inline::maybe_instantiate_inline(cx, def_id); } - match cx.tcx().map.expect_item(def_id.node).node { - ast::ItemConst(..) => { base::get_item_val(cx, def_id.node); } - _ => {} + if let ast::ItemConst(..) = cx.tcx().map.expect_item(def_id.node).node { + base::get_item_val(cx, def_id.node); } } @@ -546,12 +545,9 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { } } let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned(); - match opt_def { - Some(def::DefStatic(def_id, _)) => { - let ty = ty::expr_ty(cx.tcx(), e); - return get_static_val(cx, def_id, ty); - } - _ => {} + if let Some(def::DefStatic(def_id, _)) = opt_def { + let ty = ty::expr_ty(cx.tcx(), e); + return get_static_val(cx, def_id, ty); } // If this isn't the address of a static, then keep going through diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 6a28ef38c51..a0b7eb02f02 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -519,9 +519,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn get_intrinsic(&self, key: & &'static str) -> ValueRef { - match self.intrinsics().borrow().get(key).cloned() { - Some(v) => return v, - _ => {} + if let Some(v) = self.intrinsics().borrow().get(key).cloned() { + return v; } match declare_intrinsic(self, key) { Some(v) => return v, diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 10a73033b64..7b2e48cd2e3 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -465,17 +465,14 @@ pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } _ => expr::Ignore, }; - match e { - Some(x) => { - bcx = expr::trans_into(bcx, &*x, dest); - match dest { - expr::SaveIn(slot) if fcx.needs_ret_allocas => { - Store(bcx, slot, fcx.llretslotptr.get().unwrap()); - } - _ => {} + if let Some(x) = e { + bcx = expr::trans_into(bcx, &*x, dest); + match dest { + expr::SaveIn(slot) if fcx.needs_ret_allocas => { + Store(bcx, slot, fcx.llretslotptr.get().unwrap()); } + _ => {} } - _ => {} } let cleanup_llbb = fcx.return_exit_block(); Br(bcx, cleanup_llbb); diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index b7ac0f49754..5a9131d94e2 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -209,14 +209,11 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // (You might think there is a more elegant way to do this than a // use_autoref bool, but then you remember that the borrow checker exists). - match (use_autoref, &adj.autoref) { - (true, &Some(ref a)) => { - datum = unpack_datum!(bcx, apply_autoref(a, - bcx, - expr, - datum)); - } - _ => {} + if let (true, &Some(ref a)) = (use_autoref, &adj.autoref) { + datum = unpack_datum!(bcx, apply_autoref(a, + bcx, + expr, + datum)); } } } diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 6f97f6453fd..615d5467f84 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -355,9 +355,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // skip padding if arg_ty.pad.is_some() { arg_idx += 1; } - match arg_ty.attr { - Some(attr) => { attrs.arg(arg_idx, attr); }, - _ => {} + if let Some(attr) = arg_ty.attr { + attrs.arg(arg_idx, attr); } arg_idx += 1; @@ -429,22 +428,19 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) { for foreign_item in foreign_mod.items.iter() { let lname = link_name(&**foreign_item); - match foreign_item.node { - ast::ForeignItemFn(..) => { - match foreign_mod.abi { - Rust | RustIntrinsic => {} - abi => { - let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id); - register_foreign_item_fn(ccx, abi, ty, - lname.get().as_slice()); - // Unlike for other items, we shouldn't call - // `base::update_linkage` here. Foreign items have - // special linkage requirements, which are handled - // inside `foreign::register_*`. - } + if let ast::ForeignItemFn(..) = foreign_item.node { + match foreign_mod.abi { + Rust | RustIntrinsic => {} + abi => { + let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id); + register_foreign_item_fn(ccx, abi, ty, + lname.get().as_slice()); + // Unlike for other items, we shouldn't call + // `base::update_linkage` here. Foreign items have + // special linkage requirements, which are handled + // inside `foreign::register_*`. } } - _ => {} } ccx.item_symbols().borrow_mut().insert(foreign_item.id, diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index bf7d560fdaa..cb3c56ad277 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -84,14 +84,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_id) }); - match map_node { - ast_map::NodeForeignItem(_) => { - if ccx.tcx().map.get_foreign_abi(fn_id.node) != abi::RustIntrinsic { - // Foreign externs don't have to be monomorphized. - return (get_item_val(ccx, fn_id.node), true); - } + if let ast_map::NodeForeignItem(_) = map_node { + if ccx.tcx().map.get_foreign_abi(fn_id.node) != abi::RustIntrinsic { + // Foreign externs don't have to be monomorphized. + return (get_item_val(ccx, fn_id.node), true); } - _ => {} } debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx())); diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 9aeb4cdb8a3..00f938191f8 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -151,21 +151,15 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let vec_ty = node_id_type(bcx, slice_expr.id); // Handle the "..." case (returns a slice since strings are always unsized): - match content_expr.node { - ast::ExprLit(ref lit) => { - match lit.node { - ast::LitStr(ref s, _) => { - let scratch = rvalue_scratch_datum(bcx, vec_ty, ""); - bcx = trans_lit_str(bcx, - content_expr, - s.clone(), - SaveIn(scratch.val)); - return DatumBlock::new(bcx, scratch.to_expr_datum()); - } - _ => {} - } + if let ast::ExprLit(ref lit) = content_expr.node { + if let ast::LitStr(ref s, _) = lit.node { + let scratch = rvalue_scratch_datum(bcx, vec_ty, ""); + bcx = trans_lit_str(bcx, + content_expr, + s.clone(), + SaveIn(scratch.val)); + return DatumBlock::new(bcx, scratch.to_expr_datum()); } - _ => {} } // Handle the &[...] case: diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8270c8f3a20..d23c1b6ccf8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2200,12 +2200,9 @@ fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId { None => return did }; inline::record_extern_fqn(cx, did, kind); - match kind { - TypeTrait => { - let t = inline::build_external_trait(cx, tcx, did); - cx.external_traits.borrow_mut().as_mut().unwrap().insert(did, t); - } - _ => {} + if let TypeTrait = kind { + let t = inline::build_external_trait(cx, tcx, did); + cx.external_traits.borrow_mut().as_mut().unwrap().insert(did, t); } return did; } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3fbb2a8749f..2522de92584 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -805,96 +805,87 @@ impl DocFolder for Cache { // Propagate a trait methods' documentation to all implementors of the // trait - match item.inner { - clean::TraitItem(ref t) => { - self.traits.insert(item.def_id, t.clone()); - } - _ => {} + if let clean::TraitItem(ref t) = item.inner { + self.traits.insert(item.def_id, t.clone()); } // Collect all the implementors of traits. - match item.inner { - clean::ImplItem(ref i) => { - match i.trait_ { - Some(clean::ResolvedPath{ did, .. }) => { - let v = match self.implementors.entry(did) { - Vacant(entry) => entry.set(Vec::with_capacity(1)), - Occupied(entry) => entry.into_mut(), - }; - v.push(Implementor { - def_id: item.def_id, - generics: i.generics.clone(), - trait_: i.trait_.as_ref().unwrap().clone(), - for_: i.for_.clone(), - stability: item.stability.clone(), - }); - } - Some(..) | None => {} + if let clean::ImplItem(ref i) = item.inner { + match i.trait_ { + Some(clean::ResolvedPath{ did, .. }) => { + let v = match self.implementors.entry(did) { + Vacant(entry) => entry.set(Vec::with_capacity(1)), + Occupied(entry) => entry.into_mut(), + }; + v.push(Implementor { + def_id: item.def_id, + generics: i.generics.clone(), + trait_: i.trait_.as_ref().unwrap().clone(), + for_: i.for_.clone(), + stability: item.stability.clone(), + }); } + Some(..) | None => {} } - _ => {} } // Index this method for searching later on - match item.name { - Some(ref s) => { - let (parent, is_method) = match item.inner { - clean::TyMethodItem(..) | - clean::StructFieldItem(..) | - clean::VariantItem(..) => { - ((Some(*self.parent_stack.last().unwrap()), - Some(self.stack[..self.stack.len() - 1])), - false) - } - clean::MethodItem(..) => { - if self.parent_stack.len() == 0 { - ((None, None), false) - } else { - let last = self.parent_stack.last().unwrap(); - let did = *last; - let path = match self.paths.get(&did) { - Some(&(_, item_type::Trait)) => - Some(self.stack[..self.stack.len() - 1]), - // The current stack not necessarily has correlation for - // where the type was defined. On the other hand, - // `paths` always has the right information if present. - Some(&(ref fqp, item_type::Struct)) | - Some(&(ref fqp, item_type::Enum)) => - Some(fqp[..fqp.len() - 1]), - Some(..) => Some(self.stack.as_slice()), - None => None - }; - ((Some(*last), path), true) - } + if let Some(ref s) = item.name { + let (parent, is_method) = match item.inner { + clean::TyMethodItem(..) | + clean::StructFieldItem(..) | + clean::VariantItem(..) => { + ((Some(*self.parent_stack.last().unwrap()), + Some(self.stack[..self.stack.len() - 1])), + false) + } + clean::MethodItem(..) => { + if self.parent_stack.len() == 0 { + ((None, None), false) + } else { + let last = self.parent_stack.last().unwrap(); + let did = *last; + let path = match self.paths.get(&did) { + Some(&(_, item_type::Trait)) => + Some(self.stack[..self.stack.len() - 1]), + // The current stack not necessarily has correlation for + // where the type was defined. On the other hand, + // `paths` always has the right information if present. + Some(&(ref fqp, item_type::Struct)) | + Some(&(ref fqp, item_type::Enum)) => + Some(fqp[..fqp.len() - 1]), + Some(..) => Some(self.stack.as_slice()), + None => None + }; + ((Some(*last), path), true) } - _ => ((None, Some(self.stack.as_slice())), false) - }; - let hidden_field = match item.inner { - clean::StructFieldItem(clean::HiddenStructField) => true, - _ => false - }; + } + _ => ((None, Some(self.stack.as_slice())), false) + }; + let hidden_field = match item.inner { + clean::StructFieldItem(clean::HiddenStructField) => true, + _ => false + }; - match parent { - (parent, Some(path)) if is_method || (!self.privmod && !hidden_field) => { - self.search_index.push(IndexItem { - ty: shortty(&item), - name: s.to_string(), - path: path.connect("::").to_string(), - desc: shorter(item.doc_value()).to_string(), - parent: parent, - }); - } - (Some(parent), None) if is_method || (!self.privmod && !hidden_field)=> { - if ast_util::is_local(parent) { - // We have a parent, but we don't know where they're - // defined yet. Wait for later to index this item. - self.orphan_methods.push((parent.node, item.clone())) - } + match parent { + (parent, Some(path)) if is_method || (!self.privmod && !hidden_field) => { + self.search_index.push(IndexItem { + ty: shortty(&item), + name: s.to_string(), + path: path.connect("::").to_string(), + desc: shorter(item.doc_value()).to_string(), + parent: parent, + }); + } + (Some(parent), None) if is_method || (!self.privmod && !hidden_field)=> { + if ast_util::is_local(parent) { + // We have a parent, but we don't know where they're + // defined yet. Wait for later to index this item. + self.orphan_methods.push((parent.node, item.clone())) } - _ => {} } + _ => {} } - None => {} } // Keep track of the fully qualified path for this item. @@ -1013,20 +1004,18 @@ impl DocFolder for Cache { _ => None, }; - match did { - Some(did) => { - let v = match self.impls.entry(did) { - Vacant(entry) => entry.set(Vec::with_capacity(1)), - Occupied(entry) => entry.into_mut(), - }; - v.push(Impl { - impl_: i, - dox: dox, - stability: item.stability.clone(), - }); - } - None => {} + if let Some(did) = did { + let v = match self.impls.entry(did) { + Vacant(entry) => entry.set(Vec::with_capacity(1)), + Occupied(entry) => entry.into_mut(), + }; + v.push(Impl { + impl_: i, + dox: dox, + stability: item.stability.clone(), + }); } + None } @@ -1865,22 +1854,19 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item, _ => false, } }).peekable(); - match s.struct_type { - doctree::Plain => { - if fields.peek().is_some() { - try!(write!(w, "

Fields

\n")); - for field in fields { - try!(write!(w, "")); - } - try!(write!(w, "
\ - {stab}{name}", - stab = ConciseStability(&field.stability), - name = field.name.as_ref().unwrap().as_slice())); - try!(document(w, field)); - try!(write!(w, "
")); + if let doctree::Plain = s.struct_type { + if fields.peek().is_some() { + try!(write!(w, "

Fields

\n")); + for field in fields { + try!(write!(w, "")); } + try!(write!(w, "
\ + {stab}{name}", + stab = ConciseStability(&field.stability), + name = field.name.as_ref().unwrap().as_slice())); + try!(document(w, field)); + try!(write!(w, "
")); } - _ => {} } render_methods(w, it) } diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index eefdeb94984..8675d2b3749 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -65,26 +65,20 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult { }; impl<'a> fold::DocFolder for ImplStripper<'a> { fn fold_item(&mut self, i: Item) -> Option { - match i.inner { - clean::ImplItem(clean::Impl{ - for_: clean::ResolvedPath{ did, .. }, - ref trait_, .. - }) => { - // Impls for stripped types don't need to exist + if let clean::ImplItem(clean::Impl{ + for_: clean::ResolvedPath{ did, .. }, + ref trait_, .. + }) = i.inner { + // Impls for stripped types don't need to exist + if self.stripped.contains(&did.node) { + return None; + } + // Impls of stripped traits also don't need to exist + if let Some(clean::ResolvedPath { did, .. }) = *trait_ { if self.stripped.contains(&did.node) { return None; } - // Impls of stripped traits also don't need to exist - match *trait_ { - Some(clean::ResolvedPath { did, .. }) => { - if self.stripped.contains(&did.node) { - return None - } - } - _ => {} - } } - _ => {} } self.fold_item_recur(i) } @@ -239,19 +233,16 @@ impl<'a> fold::DocFolder for Stripper<'a> { struct ImplStripper<'a>(&'a HashSet); impl<'a> fold::DocFolder for ImplStripper<'a> { fn fold_item(&mut self, i: Item) -> Option { - match i.inner { - clean::ImplItem(ref imp) => { - match imp.trait_ { - Some(clean::ResolvedPath{ did, .. }) => { - let ImplStripper(s) = *self; - if ast_util::is_local(did) && !s.contains(&did.node) { - return None; - } + if let clean::ImplItem(ref imp) = i.inner { + match imp.trait_ { + Some(clean::ResolvedPath{ did, .. }) => { + let ImplStripper(s) = *self; + if ast_util::is_local(did) && !s.contains(&did.node) { + return None; } - Some(..) | None => {} } + Some(..) | None => {} } - _ => {} } self.fold_item_recur(i) } diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 6b97b931ef7..2913666a315 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -776,11 +776,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } ItemTrait(_, _, ref bounds, ref trait_items) => { for b in bounds.iter() { - match *b { - TraitTyParamBound(ref t) => { - self.insert(t.trait_ref.ref_id, NodeItem(i)); - } - _ => {} + if let TraitTyParamBound(ref t) = *b { + self.insert(t.trait_ref.ref_id, NodeItem(i)); } } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index aa693976fe4..68bb7ecfb85 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -412,13 +412,10 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { } self.operation.visit_id(item.id); - match item.node { - ItemEnum(ref enum_definition, _) => { - for variant in enum_definition.variants.iter() { - self.operation.visit_id(variant.node.id) - } + if let ItemEnum(ref enum_definition, _) = item.node { + for variant in enum_definition.variants.iter() { + self.operation.visit_id(variant.node.id) } - _ => {} } visit::walk_item(self, item); @@ -453,9 +450,8 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { fn visit_ty(&mut self, typ: &Ty) { self.operation.visit_id(typ.id); - match typ.node { - TyPath(_, id) => self.operation.visit_id(id), - _ => {} + if let TyPath(_, id) = typ.node { + self.operation.visit_id(id); } visit::walk_ty(self, typ) } @@ -500,9 +496,8 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { span); if !self.pass_through_items { - match function_kind { - visit::FkMethod(..) => self.visited_outermost = false, - _ => {} + if let visit::FkMethod(..) = function_kind { + self.visited_outermost = false; } } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9635f0175f0..7453da6374e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -151,13 +151,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { fn visit_view_item(&mut self, i: &ast::ViewItem) { match i.node { ast::ViewItemUse(ref path) => { - match path.node { - ast::ViewPathGlob(..) => { - self.gate_feature("globs", path.span, - "glob import statements are \ - experimental and possibly buggy"); - } - _ => {} + if let ast::ViewPathGlob(..) = path.node { + self.gate_feature("globs", path.span, + "glob import statements are \ + experimental and possibly buggy"); } } ast::ViewItemExternCrate(..) => { @@ -295,13 +292,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } fn visit_ty(&mut self, t: &ast::Ty) { - match t.node { - ast::TyClosure(ref closure) => { - // this used to be blocked by a feature gate, but it should just - // be plain impossible right now - assert!(closure.onceness != ast::Once); - }, - _ => {} + if let ast::TyClosure(ref closure) = t.node { + // this used to be blocked by a feature gate, but it should just + // be plain impossible right now + assert!(closure.onceness != ast::Once); } visit::walk_ty(self, t); @@ -465,4 +459,3 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, }, unknown_features) } - diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 447f2a376e1..01dc3564a84 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -178,11 +178,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return x.clone() - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return x.clone(); } } ); @@ -194,11 +191,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return x - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return x; } } ); @@ -210,11 +204,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return (*x).clone() - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return (*x).clone(); } } ); @@ -226,11 +217,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return Some(x.clone()), - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return Some(x.clone()); } } ); @@ -242,11 +230,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return IoviItem(x.clone()) - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return IoviItem(x.clone()); } } ); @@ -258,11 +243,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return (Vec::new(), x) - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return (Vec::new(), x); } } ) @@ -469,15 +451,11 @@ impl<'a> Parser<'a> { /// from anticipated input errors, discarding erroneous characters. pub fn commit_expr(&mut self, e: &Expr, edible: &[token::Token], inedible: &[token::Token]) { debug!("commit_expr {}", e); - match e.node { - ExprPath(..) => { - // might be unit-struct construction; check for recoverableinput error. - let mut expected = edible.iter().map(|x| x.clone()).collect::>(); - expected.push_all(inedible); - self.check_for_erroneous_unit_struct_expecting( - expected.as_slice()); - } - _ => {} + if let ExprPath(..) = e.node { + // might be unit-struct construction; check for recoverableinput error. + let mut expected = edible.iter().map(|x| x.clone()).collect::>(); + expected.push_all(inedible); + self.check_for_erroneous_unit_struct_expecting(expected.as_slice()); } self.expect_one_of(edible, inedible) } @@ -1764,11 +1742,8 @@ impl<'a> Parser<'a> { token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()), _ => None, }; - match found { - Some(token::Interpolated(token::NtPath(box path))) => { - return path; - } - _ => {} + if let Some(token::Interpolated(token::NtPath(box path))) = found { + return path; } let lo = self.span.lo; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c12c3098279..93376c5ef0d 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -969,14 +969,11 @@ impl<'a> State<'a> { "trait").as_slice())); try!(self.print_ident(item.ident)); try!(self.print_generics(generics)); - match unbound { - &Some(ref tref) => { - try!(space(&mut self.s)); - try!(self.word_space("for")); - try!(self.print_trait_ref(tref)); - try!(word(&mut self.s, "?")); - } - _ => {} + if let &Some(ref tref) = unbound { + try!(space(&mut self.s)); + try!(self.word_space("for")); + try!(self.print_trait_ref(tref)); + try!(word(&mut self.s, "?")); } try!(self.print_bounds(":", bounds.as_slice())); try!(self.print_where_clause(generics)); @@ -1761,16 +1758,14 @@ impl<'a> State<'a> { try!(space(&mut self.s)); } } - match start { - &Some(ref e) => try!(self.print_expr(&**e)), - _ => {} + if let &Some(ref e) = start { + try!(self.print_expr(&**e)); } if start.is_some() || end.is_some() { try!(word(&mut self.s, "..")); } - match end { - &Some(ref e) => try!(self.print_expr(&**e)), - _ => {} + if let &Some(ref e) = end { + try!(self.print_expr(&**e)); } try!(word(&mut self.s, "]")); } @@ -1875,13 +1870,10 @@ impl<'a> State<'a> { try!(self.ibox(indent_unit)); try!(self.print_local_decl(&**loc)); try!(self.end()); - match loc.init { - Some(ref init) => { - try!(self.nbsp()); - try!(self.word_space("=")); - try!(self.print_expr(&**init)); - } - _ => {} + if let Some(ref init) = loc.init { + try!(self.nbsp()); + try!(self.word_space("=")); + try!(self.print_expr(&**init)); } self.end() } @@ -2404,12 +2396,9 @@ impl<'a> State<'a> { } pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> { - match param.unbound { - Some(ref tref) => { - try!(self.print_trait_ref(tref)); - try!(self.word_space("?")); - } - _ => {} + if let Some(ref tref) = param.unbound { + try!(self.print_trait_ref(tref)); + try!(self.word_space("?")); } try!(self.print_ident(param.ident)); try!(self.print_bounds(":", param.bounds.as_slice())); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 1385fb982e5..18623ca2a81 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -671,11 +671,8 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) { - match struct_field.node.kind { - NamedField(name, _) => { - visitor.visit_ident(struct_field.span, name) - } - _ => {} + if let NamedField(name, _) = struct_field.node.kind { + visitor.visit_ident(struct_field.span, name); } visitor.visit_ty(&*struct_field.node.ty); -- cgit 1.4.1-3-g733a5 From 63553a10adc8b507edee1fce43f868d93628ce34 Mon Sep 17 00:00:00 2001 From: P1start Date: Sun, 30 Nov 2014 21:33:04 +1300 Subject: Fix the ordering of `unsafe` and `extern` in methods This breaks code that looks like this: trait Foo { extern "C" unsafe fn foo(); } impl Foo for Bar { extern "C" unsafe fn foo() { ... } } Change such code to look like this: trait Foo { unsafe extern "C" fn foo(); } impl Foo for Bar { unsafe extern "C" fn foo() { ... } } Fixes #19398. [breaking-change] --- src/libsyntax/parse/parser.rs | 15 ++++++++------- src/test/compile-fail/issue-19398.rs | 15 +++++++++++++++ src/test/compile-fail/removed-syntax-static-fn.rs | 2 +- src/test/run-pass/issue-19398.rs | 19 +++++++++++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 src/test/compile-fail/issue-19398.rs create mode 100644 src/test/run-pass/issue-19398.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 447f2a376e1..c76d9edf635 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1296,13 +1296,14 @@ impl<'a> Parser<'a> { let lo = p.span.lo; let vis = p.parse_visibility(); + let style = p.parse_fn_style(); let abi = if p.eat_keyword(keywords::Extern) { p.parse_opt_abi().unwrap_or(abi::C) } else { abi::Rust }; + p.expect_keyword(keywords::Fn); - let style = p.parse_fn_style(); let ident = p.parse_ident(); let mut generics = p.parse_generics(); @@ -4458,12 +4459,13 @@ impl<'a> Parser<'a> { self.span.hi) }; (ast::MethMac(m), self.span.hi, attrs) } else { + let fn_style = self.parse_fn_style(); let abi = if self.eat_keyword(keywords::Extern) { self.parse_opt_abi().unwrap_or(abi::C) } else { abi::Rust }; - let fn_style = self.parse_fn_style(); + self.expect_keyword(keywords::Fn); let ident = self.parse_ident(); let mut generics = self.parse_generics(); let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| { @@ -5009,14 +5011,13 @@ impl<'a> Parser<'a> { }) } - /// Parse safe/unsafe and fn + /// Parse unsafe or not fn parse_fn_style(&mut self) -> FnStyle { - if self.eat_keyword(keywords::Fn) { NormalFn } - else if self.eat_keyword(keywords::Unsafe) { - self.expect_keyword(keywords::Fn); + if self.eat_keyword(keywords::Unsafe) { UnsafeFn + } else { + NormalFn } - else { self.unexpected(); } } diff --git a/src/test/compile-fail/issue-19398.rs b/src/test/compile-fail/issue-19398.rs new file mode 100644 index 00000000000..3a6d15e0086 --- /dev/null +++ b/src/test/compile-fail/issue-19398.rs @@ -0,0 +1,15 @@ +// Copyright 2014 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 T { + extern "Rust" unsafe fn foo(); //~ ERROR expected `fn`, found `unsafe` +} + +fn main() {} diff --git a/src/test/compile-fail/removed-syntax-static-fn.rs b/src/test/compile-fail/removed-syntax-static-fn.rs index f6455608fdc..e3e1cb0f3ca 100644 --- a/src/test/compile-fail/removed-syntax-static-fn.rs +++ b/src/test/compile-fail/removed-syntax-static-fn.rs @@ -11,5 +11,5 @@ struct S; impl S { - static fn f() {} //~ ERROR unexpected token: `static` + static fn f() {} //~ ERROR expected `fn`, found `static` } diff --git a/src/test/run-pass/issue-19398.rs b/src/test/run-pass/issue-19398.rs new file mode 100644 index 00000000000..1196162568a --- /dev/null +++ b/src/test/run-pass/issue-19398.rs @@ -0,0 +1,19 @@ +// Copyright 2014 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 T { + unsafe extern "Rust" fn foo(); +} + +impl T for () { + unsafe extern "Rust" fn foo() {} +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From f5715f7867ab7e13fd3304d85861b1dcb1375a89 Mon Sep 17 00:00:00 2001 From: P1start Date: Sun, 30 Nov 2014 17:39:50 +1300 Subject: Allow trailing commas in array patterns and attributes --- src/libsyntax/parse/attr.rs | 2 +- src/libsyntax/parse/common.rs | 7 +------ src/libsyntax/parse/parser.rs | 5 +++++ src/test/compile-fail/trailing-comma-array-repeat.rs | 13 +++++++++++++ src/test/run-pass/trailing-comma.rs | 6 ++++++ 5 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/trailing-comma-array-repeat.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 0c919daa8ed..40703049cc3 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -212,7 +212,7 @@ impl<'a> ParserAttr for Parser<'a> { fn parse_meta_seq(&mut self) -> Vec> { self.parse_seq(&token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), - seq_sep_trailing_disallowed(token::Comma), + seq_sep_trailing_allowed(token::Comma), |p| p.parse_meta_item()).node } diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 3842170d677..a96bf1ce10b 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -19,18 +19,13 @@ pub struct SeqSep { pub trailing_sep_allowed: bool } -pub fn seq_sep_trailing_disallowed(t: token::Token) -> SeqSep { - SeqSep { - sep: Some(t), - trailing_sep_allowed: false, - } -} pub fn seq_sep_trailing_allowed(t: token::Token) -> SeqSep { SeqSep { sep: Some(t), trailing_sep_allowed: true, } } + pub fn seq_sep_none() -> SeqSep { SeqSep { sep: None, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 447f2a376e1..9623a1b75b5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3129,6 +3129,11 @@ impl<'a> Parser<'a> { first = false; } else { self.expect(&token::Comma); + + if self.token == token::CloseDelim(token::Bracket) + && (before_slice || after.len() != 0) { + break + } } if before_slice { diff --git a/src/test/compile-fail/trailing-comma-array-repeat.rs b/src/test/compile-fail/trailing-comma-array-repeat.rs new file mode 100644 index 00000000000..dadd6571583 --- /dev/null +++ b/src/test/compile-fail/trailing-comma-array-repeat.rs @@ -0,0 +1,13 @@ +// Copyright 2014 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. + +fn main() { + let [_, ..,] = [(), ()]; //~ ERROR unexpected token: `]` +} diff --git a/src/test/run-pass/trailing-comma.rs b/src/test/run-pass/trailing-comma.rs index 5e93f8eedb7..00e05064080 100644 --- a/src/test/run-pass/trailing-comma.rs +++ b/src/test/run-pass/trailing-comma.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(advanced_slice_patterns,)] + fn f(_: T,) {} struct Foo; @@ -24,9 +26,13 @@ enum Baz { Qux(int,), } +#[allow(unused,)] pub fn main() { f::(0i,); let (_, _,) = (1i, 1i,); + let [_, _,] = [1i, 1,]; + let [_, _, .., _,] = [1i, 1, 1, 1,]; + let [_, _, _.., _,] = [1i, 1, 1, 1,]; let x: Foo = Foo::; -- cgit 1.4.1-3-g733a5 From 798da237725a8b1292dfbcee6847bb297586eb44 Mon Sep 17 00:00:00 2001 From: Alexander Light Date: Sun, 30 Nov 2014 09:51:15 -0500 Subject: allow macro expansions in attributes --- src/libsyntax/parse/parser.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 447f2a376e1..b9fd28ecfc8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1669,6 +1669,12 @@ impl<'a> Parser<'a> { /// Matches token_lit = LIT_INTEGER | ... pub fn lit_from_token(&mut self, tok: &token::Token) -> Lit_ { match *tok { + token::Interpolated(token::NtExpr(ref v)) => { + match v.node { + ExprLit(ref lit) => { lit.node.clone() } + _ => { self.unexpected_last(tok); } + } + } token::Literal(lit, suf) => { let (suffix_illegal, out) = match lit { token::Byte(i) => (true, LitByte(parse::byte_lit(i.as_str()).val0())), -- cgit 1.4.1-3-g733a5 From 108bca53f04342a4626b34ac1d5b8236d170a12a Mon Sep 17 00:00:00 2001 From: P1start Date: Wed, 3 Dec 2014 22:47:53 +1300 Subject: Make the parser’s ‘expected , found ’ errors more accurate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As an example of what this changes, the following code: let x: [int ..4]; Currently spits out ‘expected `]`, found `..`’. However, a comma would also be valid there, as would a number of other tokens. This change adjusts the parser to produce more accurate errors, so that that example now produces ‘expected one of `(`, `+`, `,`, `::`, or `]`, found `..`’. --- src/libsyntax/parse/parser.rs | 183 +++++++++++++-------- src/test/compile-fail/better-expected.rs | 13 ++ src/test/compile-fail/column-offset-1-based.rs | 2 +- src/test/compile-fail/empty-impl-semicolon.rs | 2 +- src/test/compile-fail/issue-1655.rs | 2 +- src/test/compile-fail/issue-19096.rs | 2 +- src/test/compile-fail/issue-3036.rs | 2 +- src/test/compile-fail/match-vec-invalid.rs | 2 +- src/test/compile-fail/multitrait.rs | 2 +- src/test/compile-fail/mut-patterns.rs | 2 +- src/test/compile-fail/omitted-arg-in-item-fn.rs | 2 +- src/test/compile-fail/pat-range-bad-dots.rs | 2 +- src/test/compile-fail/raw-str-unbalanced.rs | 2 +- .../removed-syntax-closure-lifetime.rs | 2 +- .../compile-fail/removed-syntax-enum-newtype.rs | 2 +- src/test/compile-fail/removed-syntax-fixed-vec.rs | 2 +- .../compile-fail/removed-syntax-larrow-init.rs | 2 +- .../compile-fail/removed-syntax-larrow-move.rs | 2 +- .../compile-fail/removed-syntax-mut-vec-expr.rs | 2 +- src/test/compile-fail/removed-syntax-mut-vec-ty.rs | 2 +- .../compile-fail/removed-syntax-ptr-lifetime.rs | 2 +- src/test/compile-fail/removed-syntax-record.rs | 2 +- .../compile-fail/removed-syntax-uniq-mut-expr.rs | 2 +- .../compile-fail/removed-syntax-uniq-mut-ty.rs | 2 +- src/test/compile-fail/removed-syntax-with-1.rs | 2 +- src/test/compile-fail/struct-literal-in-for.rs | 2 +- src/test/compile-fail/struct-literal-in-if.rs | 2 +- .../struct-literal-in-match-discriminant.rs | 2 +- src/test/compile-fail/struct-literal-in-while.rs | 2 +- 29 files changed, 155 insertions(+), 95 deletions(-) create mode 100644 src/test/compile-fail/better-expected.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 920bcc3a951..c9d78eccdc7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -87,6 +87,7 @@ use std::mem; use std::num::Float; use std::rc::Rc; use std::iter; +use std::slice; bitflags! { flags Restrictions: u8 { @@ -303,6 +304,22 @@ pub struct Parser<'a> { /// name is not known. This does not change while the parser is descending /// into modules, and sub-parsers have new values for this name. pub root_module_name: Option, + pub expected_tokens: Vec, +} + +#[deriving(PartialEq, Eq, Clone)] +pub enum TokenType { + Token(token::Token), + Operator, +} + +impl TokenType { + fn to_string(&self) -> String { + match *self { + TokenType::Token(ref t) => format!("`{}`", Parser::token_to_string(t)), + TokenType::Operator => "an operator".into_string(), + } + } } fn is_plain_ident_or_underscore(t: &token::Token) -> bool { @@ -347,6 +364,7 @@ impl<'a> Parser<'a> { open_braces: Vec::new(), owns_directory: true, root_module_name: None, + expected_tokens: Vec::new(), } } @@ -375,14 +393,18 @@ impl<'a> Parser<'a> { /// Expect and consume the token t. Signal an error if /// the next token is not t. pub fn expect(&mut self, t: &token::Token) { - if self.token == *t { - self.bump(); + if self.expected_tokens.is_empty() { + if self.token == *t { + self.bump(); + } else { + let token_str = Parser::token_to_string(t); + let this_token_str = self.this_token_to_string(); + self.fatal(format!("expected `{}`, found `{}`", + token_str, + this_token_str).as_slice()) + } } else { - let token_str = Parser::token_to_string(t); - let this_token_str = self.this_token_to_string(); - self.fatal(format!("expected `{}`, found `{}`", - token_str, - this_token_str).as_slice()) + self.expect_one_of(slice::ref_slice(t), &[]); } } @@ -392,15 +414,20 @@ impl<'a> Parser<'a> { pub fn expect_one_of(&mut self, edible: &[token::Token], inedible: &[token::Token]) { - fn tokens_to_string(tokens: &[token::Token]) -> String { + fn tokens_to_string(tokens: &[TokenType]) -> String { let mut i = tokens.iter(); // This might be a sign we need a connect method on Iterator. let b = i.next() - .map_or("".to_string(), |t| Parser::token_to_string(t)); - i.fold(b, |b,a| { - let mut b = b; - b.push_str("`, `"); - b.push_str(Parser::token_to_string(a).as_slice()); + .map_or("".into_string(), |t| t.to_string()); + i.enumerate().fold(b, |mut b, (i, ref a)| { + if tokens.len() > 2 && i == tokens.len() - 2 { + b.push_str(", or "); + } else if tokens.len() == 2 && i == tokens.len() - 2 { + b.push_str(" or "); + } else { + b.push_str(", "); + } + b.push_str(&*a.to_string()); b }) } @@ -409,17 +436,21 @@ impl<'a> Parser<'a> { } else if inedible.contains(&self.token) { // leave it in the input } else { - let mut expected = edible.iter().map(|x| x.clone()).collect::>(); - expected.push_all(inedible); + let mut expected = edible.iter().map(|x| TokenType::Token(x.clone())) + .collect::>(); + expected.extend(inedible.iter().map(|x| TokenType::Token(x.clone()))); + expected.push_all(&*self.expected_tokens); + expected.sort_by(|a, b| a.to_string().cmp(&b.to_string())); + expected.dedup(); let expect = tokens_to_string(expected.as_slice()); let actual = self.this_token_to_string(); self.fatal( (if expected.len() != 1 { - (format!("expected one of `{}`, found `{}`", + (format!("expected one of {}, found `{}`", expect, actual)) } else { - (format!("expected `{}`, found `{}`", + (format!("expected {}, found `{}`", expect, actual)) }).as_slice() @@ -514,10 +545,20 @@ impl<'a> Parser<'a> { spanned(lo, hi, node) } + /// Check if the next token is `tok`, and return `true` if so. + /// + /// This method is will automatically add `tok` to `expected_tokens` if `tok` is not + /// encountered. + pub fn check(&mut self, tok: &token::Token) -> bool { + let is_present = self.token == *tok; + if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); } + is_present + } + /// Consume token 'tok' if it exists. Returns true if the given /// token was present, false otherwise. pub fn eat(&mut self, tok: &token::Token) -> bool { - let is_present = self.token == *tok; + let is_present = self.check(tok); if is_present { self.bump() } is_present } @@ -739,7 +780,7 @@ impl<'a> Parser<'a> { // commas in generic parameters, because it can stop either after // parsing a type or after parsing a comma. for i in iter::count(0u, 1) { - if self.token == token::Gt + if self.check(&token::Gt) || self.token == token::BinOp(token::Shr) || self.token == token::Ge || self.token == token::BinOpEq(token::Shr) { @@ -798,7 +839,7 @@ impl<'a> Parser<'a> { } _ => () } - if sep.trailing_sep_allowed && self.token == *ket { break; } + if sep.trailing_sep_allowed && self.check(ket) { break; } v.push(f(self)); } return v; @@ -881,6 +922,7 @@ impl<'a> Parser<'a> { self.span = next.sp; self.token = next.tok; self.tokens_consumed += 1u; + self.expected_tokens.clear(); } /// Advance the parser by one token and return the bumped token. @@ -999,7 +1041,7 @@ impl<'a> Parser<'a> { self.parse_proc_type(lifetime_defs) } else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() { self.parse_ty_bare_fn_or_ty_closure(lifetime_defs) - } else if self.token == token::ModSep || + } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { @@ -1101,7 +1143,7 @@ impl<'a> Parser<'a> { /// Parses an optional unboxed closure kind (`&:`, `&mut:`, or `:`). pub fn parse_optional_unboxed_closure_kind(&mut self) -> Option { - if self.token == token::BinOp(token::And) && + if self.check(&token::BinOp(token::And)) && self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && self.look_ahead(2, |t| *t == token::Colon) { self.bump(); @@ -1211,7 +1253,8 @@ impl<'a> Parser<'a> { lifetime_defs: Vec) -> Vec { - if self.eat(&token::Lt) { + if self.token == token::Lt { + self.bump(); if lifetime_defs.is_empty() { self.warn("deprecated syntax; use the `for` keyword now \ (e.g. change `fn<'a>` to `for<'a> fn`)"); @@ -1430,7 +1473,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; - let t = if self.token == token::OpenDelim(token::Paren) { + let t = if self.check(&token::OpenDelim(token::Paren)) { self.bump(); // (t) is a parenthesized ty @@ -1440,7 +1483,7 @@ impl<'a> Parser<'a> { let mut last_comma = false; while self.token != token::CloseDelim(token::Paren) { ts.push(self.parse_ty_sum()); - if self.token == token::Comma { + if self.check(&token::Comma) { last_comma = true; self.bump(); } else { @@ -1464,11 +1507,11 @@ impl<'a> Parser<'a> { _ => self.obsolete(last_span, ObsoleteOwnedType) } TyTup(vec![self.parse_ty()]) - } else if self.token == token::BinOp(token::Star) { + } else if self.check(&token::BinOp(token::Star)) { // STAR POINTER (bare pointer?) self.bump(); TyPtr(self.parse_ptr()) - } else if self.token == token::OpenDelim(token::Bracket) { + } else if self.check(&token::OpenDelim(token::Bracket)) { // VECTOR self.expect(&token::OpenDelim(token::Bracket)); let t = self.parse_ty_sum(); @@ -1481,7 +1524,7 @@ impl<'a> Parser<'a> { }; self.expect(&token::CloseDelim(token::Bracket)); t - } else if self.token == token::BinOp(token::And) || + } else if self.check(&token::BinOp(token::And)) || self.token == token::AndAnd { // BORROWED POINTER self.expect_and(); @@ -1492,7 +1535,7 @@ impl<'a> Parser<'a> { self.token_is_closure_keyword() { // BARE FUNCTION OR CLOSURE self.parse_ty_bare_fn_or_ty_closure(Vec::new()) - } else if self.token == token::BinOp(token::Or) || + } else if self.check(&token::BinOp(token::Or)) || self.token == token::OrOr || (self.token == token::Lt && self.look_ahead(1, |t| { @@ -1509,7 +1552,7 @@ impl<'a> Parser<'a> { TyTypeof(e) } else if self.eat_keyword(keywords::Proc) { self.parse_proc_type(Vec::new()) - } else if self.token == token::Lt { + } else if self.check(&token::Lt) { // QUALIFIED PATH `::item` self.bump(); let self_type = self.parse_ty_sum(); @@ -1523,7 +1566,7 @@ impl<'a> Parser<'a> { trait_ref: P(trait_ref), item_name: item_name, })) - } else if self.token == token::ModSep || + } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { // NAMED TYPE @@ -1532,7 +1575,8 @@ impl<'a> Parser<'a> { // TYPE TO BE INFERRED TyInfer } else { - let msg = format!("expected type, found token {}", self.token); + let this_token_str = self.this_token_to_string(); + let msg = format!("expected type, found `{}`", this_token_str); self.fatal(msg.as_slice()); }; @@ -1635,7 +1679,7 @@ impl<'a> Parser<'a> { } pub fn maybe_parse_fixed_vstore(&mut self) -> Option> { - if self.token == token::Comma && + if self.check(&token::Comma) && self.look_ahead(1, |t| *t == token::DotDot) { self.bump(); self.bump(); @@ -1959,9 +2003,10 @@ impl<'a> Parser<'a> { token::Gt => { return res; } token::BinOp(token::Shr) => { return res; } _ => { + let this_token_str = self.this_token_to_string(); let msg = format!("expected `,` or `>` after lifetime \ - name, got: {}", - self.token); + name, found `{}`", + this_token_str); self.fatal(msg.as_slice()); } } @@ -2126,7 +2171,7 @@ impl<'a> Parser<'a> { es.push(self.parse_expr()); self.commit_expr(&**es.last().unwrap(), &[], &[token::Comma, token::CloseDelim(token::Paren)]); - if self.token == token::Comma { + if self.check(&token::Comma) { trailing_comma = true; self.bump(); @@ -2167,14 +2212,14 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Bracket) => { self.bump(); - if self.token == token::CloseDelim(token::Bracket) { + if self.check(&token::CloseDelim(token::Bracket)) { // Empty vector. self.bump(); ex = ExprVec(Vec::new()); } else { // Nonempty vector. let first_expr = self.parse_expr(); - if self.token == token::Comma && + if self.check(&token::Comma) && self.look_ahead(1, |t| *t == token::DotDot) { // Repeating vector syntax: [ 0, ..512 ] self.bump(); @@ -2182,7 +2227,7 @@ impl<'a> Parser<'a> { let count = self.parse_expr(); self.expect(&token::CloseDelim(token::Bracket)); ex = ExprRepeat(first_expr, count); - } else if self.token == token::Comma { + } else if self.check(&token::Comma) { // Vector with two or more elements. self.bump(); let remaining_exprs = self.parse_seq_to_end( @@ -2284,7 +2329,7 @@ impl<'a> Parser<'a> { ex = ExprBreak(None); } hi = self.span.hi; - } else if self.token == token::ModSep || + } else if self.check(&token::ModSep) || self.token.is_ident() && !self.token.is_keyword(keywords::True) && !self.token.is_keyword(keywords::False) { @@ -2292,7 +2337,7 @@ impl<'a> Parser<'a> { self.parse_path(LifetimeAndTypesWithColons); // `!`, as an operator, is prefix, so we know this isn't that - if self.token == token::Not { + if self.check(&token::Not) { // MACRO INVOCATION expression self.bump(); @@ -2309,7 +2354,7 @@ impl<'a> Parser<'a> { tts, EMPTY_CTXT)); } - if self.token == token::OpenDelim(token::Brace) { + if self.check(&token::OpenDelim(token::Brace)) { // This is a struct literal, unless we're prohibited // from parsing struct literals here. if !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) { @@ -2840,6 +2885,7 @@ impl<'a> Parser<'a> { self.restrictions.contains(RESTRICTION_NO_BAR_OP) { return lhs; } + self.expected_tokens.push(TokenType::Operator); let cur_opt = self.token.to_binop(); match cur_opt { @@ -3079,7 +3125,7 @@ impl<'a> Parser<'a> { /// Parse the RHS of a local variable declaration (e.g. '= 14;') fn parse_initializer(&mut self) -> Option> { - if self.token == token::Eq { + if self.check(&token::Eq) { self.bump(); Some(self.parse_expr()) } else { @@ -3092,7 +3138,7 @@ impl<'a> Parser<'a> { let mut pats = Vec::new(); loop { pats.push(self.parse_pat()); - if self.token == token::BinOp(token::Or) { self.bump(); } + if self.check(&token::BinOp(token::Or)) { self.bump(); } else { return pats; } }; } @@ -3114,11 +3160,11 @@ impl<'a> Parser<'a> { } if before_slice { - if self.token == token::DotDot { + if self.check(&token::DotDot) { self.bump(); - if self.token == token::Comma || - self.token == token::CloseDelim(token::Bracket) { + if self.check(&token::Comma) || + self.check(&token::CloseDelim(token::Bracket)) { slice = Some(P(ast::Pat { id: ast::DUMMY_NODE_ID, node: PatWild(PatWildMulti), @@ -3135,7 +3181,7 @@ impl<'a> Parser<'a> { } let subpat = self.parse_pat(); - if before_slice && self.token == token::DotDot { + if before_slice && self.check(&token::DotDot) { self.bump(); slice = Some(subpat); before_slice = false; @@ -3160,13 +3206,13 @@ impl<'a> Parser<'a> { } else { self.expect(&token::Comma); // accept trailing commas - if self.token == token::CloseDelim(token::Brace) { break } + if self.check(&token::CloseDelim(token::Brace)) { break } } let lo = self.span.lo; let hi; - if self.token == token::DotDot { + if self.check(&token::DotDot) { self.bump(); if self.token != token::CloseDelim(token::Brace) { let token_str = self.this_token_to_string(); @@ -3187,7 +3233,7 @@ impl<'a> Parser<'a> { let fieldname = self.parse_ident(); - let (subpat, is_shorthand) = if self.token == token::Colon { + let (subpat, is_shorthand) = if self.check(&token::Colon) { match bind_type { BindByRef(..) | BindByValue(MutMutable) => { let token_str = self.this_token_to_string(); @@ -3267,15 +3313,15 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Paren) => { // parse (pat,pat,pat,...) as tuple self.bump(); - if self.token == token::CloseDelim(token::Paren) { + if self.check(&token::CloseDelim(token::Paren)) { self.bump(); pat = PatTup(vec![]); } else { let mut fields = vec!(self.parse_pat()); if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) { - while self.token == token::Comma { + while self.check(&token::Comma) { self.bump(); - if self.token == token::CloseDelim(token::Paren) { break; } + if self.check(&token::CloseDelim(token::Paren)) { break; } fields.push(self.parse_pat()); } } @@ -3318,7 +3364,7 @@ impl<'a> Parser<'a> { // These expressions are limited to literals (possibly // preceded by unary-minus) or identifiers. let val = self.parse_literal_maybe_minus(); - if (self.token == token::DotDotDot) && + if (self.check(&token::DotDotDot)) && self.look_ahead(1, |t| { *t != token::Comma && *t != token::CloseDelim(token::Bracket) }) { @@ -3621,7 +3667,7 @@ impl<'a> Parser<'a> { let hi = self.span.hi; if id.name == token::special_idents::invalid.name { - if self.token == token::Dot { + if self.check(&token::Dot) { let span = self.span; let token_string = self.this_token_to_string(); self.span_err(span, @@ -3934,7 +3980,7 @@ impl<'a> Parser<'a> { let bounds = self.parse_colon_then_ty_param_bounds(); - let default = if self.token == token::Eq { + let default = if self.check(&token::Eq) { self.bump(); Some(self.parse_ty_sum()) } @@ -4334,7 +4380,7 @@ impl<'a> Parser<'a> { (optional_unboxed_closure_kind, args) } }; - let output = if self.token == token::RArrow { + let output = if self.check(&token::RArrow) { self.parse_ret_ty() } else { Return(P(Ty { @@ -4359,7 +4405,7 @@ impl<'a> Parser<'a> { seq_sep_trailing_allowed(token::Comma), |p| p.parse_fn_block_arg()); - let output = if self.token == token::RArrow { + let output = if self.check(&token::RArrow) { self.parse_ret_ty() } else { Return(P(Ty { @@ -4616,7 +4662,7 @@ impl<'a> Parser<'a> { token::get_ident(class_name)).as_slice()); } self.bump(); - } else if self.token == token::OpenDelim(token::Paren) { + } else if self.check(&token::OpenDelim(token::Paren)) { // It's a tuple-like struct. is_tuple_like = true; fields = self.parse_unspanned_seq( @@ -4801,7 +4847,7 @@ impl<'a> Parser<'a> { fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> ItemInfo { let id_span = self.span; let id = self.parse_ident(); - if self.token == token::Semi { + if self.check(&token::Semi) { self.bump(); // This mod is in an external file. Let's go get it! let (m, attrs) = self.eval_src_mod(id, outer_attrs, id_span); @@ -5044,7 +5090,8 @@ impl<'a> Parser<'a> { let (maybe_path, ident) = match self.token { token::Ident(..) => { let the_ident = self.parse_ident(); - let path = if self.eat(&token::Eq) { + let path = if self.token == token::Eq { + self.bump(); let path = self.parse_str(); let span = self.span; self.obsolete(span, ObsoleteExternCrateRenaming); @@ -5184,7 +5231,7 @@ impl<'a> Parser<'a> { token::get_ident(ident)).as_slice()); } kind = StructVariantKind(struct_def); - } else if self.token == token::OpenDelim(token::Paren) { + } else if self.check(&token::OpenDelim(token::Paren)) { all_nullary = false; let arg_tys = self.parse_enum_variant_seq( &token::OpenDelim(token::Paren), @@ -5348,7 +5395,7 @@ impl<'a> Parser<'a> { visibility, maybe_append(attrs, extra_attrs)); return IoviItem(item); - } else if self.token == token::OpenDelim(token::Brace) { + } else if self.check(&token::OpenDelim(token::Brace)) { return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs); } @@ -5629,7 +5676,7 @@ impl<'a> Parser<'a> { fn parse_view_path(&mut self) -> P { let lo = self.span.lo; - if self.token == token::OpenDelim(token::Brace) { + if self.check(&token::OpenDelim(token::Brace)) { // use {foo,bar} let idents = self.parse_unspanned_seq( &token::OpenDelim(token::Brace), @@ -5653,7 +5700,7 @@ impl<'a> Parser<'a> { self.bump(); let path_lo = self.span.lo; path = vec!(self.parse_ident()); - while self.token == token::ModSep { + while self.check(&token::ModSep) { self.bump(); let id = self.parse_ident(); path.push(id); @@ -5677,7 +5724,7 @@ impl<'a> Parser<'a> { token::ModSep => { // foo::bar or foo::{a,b,c} or foo::* - while self.token == token::ModSep { + while self.check(&token::ModSep) { self.bump(); match self.token { @@ -5846,7 +5893,7 @@ impl<'a> Parser<'a> { loop { match self.parse_foreign_item(attrs, macros_allowed) { IoviNone(returned_attrs) => { - if self.token == token::CloseDelim(token::Brace) { + if self.check(&token::CloseDelim(token::Brace)) { attrs = returned_attrs; break } diff --git a/src/test/compile-fail/better-expected.rs b/src/test/compile-fail/better-expected.rs new file mode 100644 index 00000000000..489f892726a --- /dev/null +++ b/src/test/compile-fail/better-expected.rs @@ -0,0 +1,13 @@ +// Copyright 2014 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. + +fn main() { + let x: [int ..3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `..` +} diff --git a/src/test/compile-fail/column-offset-1-based.rs b/src/test/compile-fail/column-offset-1-based.rs index a00ded61758..621b480fe77 100644 --- a/src/test/compile-fail/column-offset-1-based.rs +++ b/src/test/compile-fail/column-offset-1-based.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -# //~ ERROR 11:1: 11:2 error: expected `[`, found `` +# //~ ERROR 11:1: 11:2 error: expected one of `!` or `[`, found `` diff --git a/src/test/compile-fail/empty-impl-semicolon.rs b/src/test/compile-fail/empty-impl-semicolon.rs index b5f17eef886..a598252f1b6 100644 --- a/src/test/compile-fail/empty-impl-semicolon.rs +++ b/src/test/compile-fail/empty-impl-semicolon.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -impl Foo; //~ ERROR expected `{`, found `;` +impl Foo; //~ ERROR expected one of `(`, `+`, `::`, or `{`, found `;` diff --git a/src/test/compile-fail/issue-1655.rs b/src/test/compile-fail/issue-1655.rs index 6bdcf5c5edc..a8704f7545f 100644 --- a/src/test/compile-fail/issue-1655.rs +++ b/src/test/compile-fail/issue-1655.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:expected `[`, found `vec` +// error-pattern:expected one of `!` or `[`, found `vec` mod blade_runner { #vec[doc( brief = "Blade Runner is probably the best movie ever", diff --git a/src/test/compile-fail/issue-19096.rs b/src/test/compile-fail/issue-19096.rs index 7f42abb3acc..6b67814aab3 100644 --- a/src/test/compile-fail/issue-19096.rs +++ b/src/test/compile-fail/issue-19096.rs @@ -12,5 +12,5 @@ fn main() { let t = (42i, 42i); - t.0::; //~ ERROR expected one of `;`, `}`, found `::` + t.0::; //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `::` } diff --git a/src/test/compile-fail/issue-3036.rs b/src/test/compile-fail/issue-3036.rs index 5f56f6b8b6b..16834f49165 100644 --- a/src/test/compile-fail/issue-3036.rs +++ b/src/test/compile-fail/issue-3036.rs @@ -13,4 +13,4 @@ fn main() { let x = 3 -} //~ ERROR: expected `;`, found `}` +} //~ ERROR: expected one of `.`, `;`, or an operator, found `}` diff --git a/src/test/compile-fail/match-vec-invalid.rs b/src/test/compile-fail/match-vec-invalid.rs index 51e83c14aa0..3e073d34f32 100644 --- a/src/test/compile-fail/match-vec-invalid.rs +++ b/src/test/compile-fail/match-vec-invalid.rs @@ -11,7 +11,7 @@ fn main() { let a = Vec::new(); match a { - [1, tail.., tail..] => {}, //~ ERROR: expected `,`, found `..` + [1, tail.., tail..] => {}, //~ ERROR: expected one of `!`, `,`, or `@`, found `..` _ => () } } diff --git a/src/test/compile-fail/multitrait.rs b/src/test/compile-fail/multitrait.rs index 795e3807d5e..7add747fbfa 100644 --- a/src/test/compile-fail/multitrait.rs +++ b/src/test/compile-fail/multitrait.rs @@ -12,7 +12,7 @@ struct S { y: int } -impl Cmp, ToString for S { //~ ERROR: expected `{`, found `,` +impl Cmp, ToString for S { //~ ERROR: expected one of `(`, `+`, `::`, or `{`, found `,` fn eq(&&other: S) { false } fn to_string(&self) -> String { "hi".to_string() } } diff --git a/src/test/compile-fail/mut-patterns.rs b/src/test/compile-fail/mut-patterns.rs index a33a603f7f5..a78e82bb73c 100644 --- a/src/test/compile-fail/mut-patterns.rs +++ b/src/test/compile-fail/mut-patterns.rs @@ -12,5 +12,5 @@ pub fn main() { struct Foo { x: int } - let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected `;`, found `{` + let mut Foo { x: x } = Foo { x: 3 }; //~ ERROR: expected one of `:`, `;`, `=`, or `@`, found `{` } diff --git a/src/test/compile-fail/omitted-arg-in-item-fn.rs b/src/test/compile-fail/omitted-arg-in-item-fn.rs index c5ff885997b..729b45df8b4 100644 --- a/src/test/compile-fail/omitted-arg-in-item-fn.rs +++ b/src/test/compile-fail/omitted-arg-in-item-fn.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo(x) { //~ ERROR expected `:`, found `)` +fn foo(x) { //~ ERROR expected one of `!`, `:`, or `@`, found `)` } diff --git a/src/test/compile-fail/pat-range-bad-dots.rs b/src/test/compile-fail/pat-range-bad-dots.rs index 5605caaeeed..7fe073a4c3d 100644 --- a/src/test/compile-fail/pat-range-bad-dots.rs +++ b/src/test/compile-fail/pat-range-bad-dots.rs @@ -10,7 +10,7 @@ pub fn main() { match 22i { - 0 .. 3 => {} //~ ERROR expected `=>`, found `..` + 0 .. 3 => {} //~ ERROR expected one of `...`, `=>`, or `|`, found `..` _ => {} } } diff --git a/src/test/compile-fail/raw-str-unbalanced.rs b/src/test/compile-fail/raw-str-unbalanced.rs index 4f3fb7d5b8a..3403b28fdc9 100644 --- a/src/test/compile-fail/raw-str-unbalanced.rs +++ b/src/test/compile-fail/raw-str-unbalanced.rs @@ -10,5 +10,5 @@ static s: &'static str = r#" - "## //~ ERROR expected `;`, found `#` + "## //~ ERROR expected one of `.`, `;`, or an operator, found `#` ; diff --git a/src/test/compile-fail/removed-syntax-closure-lifetime.rs b/src/test/compile-fail/removed-syntax-closure-lifetime.rs index a726e30b1de..a07832d5bb7 100644 --- a/src/test/compile-fail/removed-syntax-closure-lifetime.rs +++ b/src/test/compile-fail/removed-syntax-closure-lifetime.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type closure = Box; //~ ERROR expected `,`, found `/` +type closure = Box; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `>`, found `/` diff --git a/src/test/compile-fail/removed-syntax-enum-newtype.rs b/src/test/compile-fail/removed-syntax-enum-newtype.rs index b9c9c5f0a53..ba1b5a616df 100644 --- a/src/test/compile-fail/removed-syntax-enum-newtype.rs +++ b/src/test/compile-fail/removed-syntax-enum-newtype.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum e = int; //~ ERROR expected `{`, found `=` +enum e = int; //~ ERROR expected one of `<` or `{`, found `=` diff --git a/src/test/compile-fail/removed-syntax-fixed-vec.rs b/src/test/compile-fail/removed-syntax-fixed-vec.rs index 917b4e03ad0..fe49d1f4a8d 100644 --- a/src/test/compile-fail/removed-syntax-fixed-vec.rs +++ b/src/test/compile-fail/removed-syntax-fixed-vec.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type v = [int * 3]; //~ ERROR expected `]`, found `*` +type v = [int * 3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `*` diff --git a/src/test/compile-fail/removed-syntax-larrow-init.rs b/src/test/compile-fail/removed-syntax-larrow-init.rs index b2e856750df..1474cc9dd39 100644 --- a/src/test/compile-fail/removed-syntax-larrow-init.rs +++ b/src/test/compile-fail/removed-syntax-larrow-init.rs @@ -11,5 +11,5 @@ fn removed_moves() { let mut x = 0; let y <- x; - //~^ ERROR expected `;`, found `<-` + //~^ ERROR expected one of `!`, `:`, `;`, `=`, or `@`, found `<-` } diff --git a/src/test/compile-fail/removed-syntax-larrow-move.rs b/src/test/compile-fail/removed-syntax-larrow-move.rs index e39fbe0f950..552c9f2efa2 100644 --- a/src/test/compile-fail/removed-syntax-larrow-move.rs +++ b/src/test/compile-fail/removed-syntax-larrow-move.rs @@ -12,5 +12,5 @@ fn removed_moves() { let mut x = 0; let y = 0; y <- x; - //~^ ERROR expected one of `;`, `}`, found `<-` + //~^ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `<-` } diff --git a/src/test/compile-fail/removed-syntax-mut-vec-expr.rs b/src/test/compile-fail/removed-syntax-mut-vec-expr.rs index b20da6346f7..437f871f8ea 100644 --- a/src/test/compile-fail/removed-syntax-mut-vec-expr.rs +++ b/src/test/compile-fail/removed-syntax-mut-vec-expr.rs @@ -11,5 +11,5 @@ fn f() { let v = [mut 1, 2, 3, 4]; //~^ ERROR expected identifier, found keyword `mut` - //~^^ ERROR expected `]`, found `1` + //~^^ ERROR expected one of `!`, `,`, `.`, `::`, `]`, `{`, or an operator, found `1` } diff --git a/src/test/compile-fail/removed-syntax-mut-vec-ty.rs b/src/test/compile-fail/removed-syntax-mut-vec-ty.rs index c5eec2ef6e1..af469fadf98 100644 --- a/src/test/compile-fail/removed-syntax-mut-vec-ty.rs +++ b/src/test/compile-fail/removed-syntax-mut-vec-ty.rs @@ -10,4 +10,4 @@ type v = [mut int]; //~^ ERROR expected identifier, found keyword `mut` - //~^^ ERROR expected `]`, found `int` + //~^^ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `int` diff --git a/src/test/compile-fail/removed-syntax-ptr-lifetime.rs b/src/test/compile-fail/removed-syntax-ptr-lifetime.rs index 0468ddd389a..1a1c4c9b40a 100644 --- a/src/test/compile-fail/removed-syntax-ptr-lifetime.rs +++ b/src/test/compile-fail/removed-syntax-ptr-lifetime.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type bptr = &lifetime/int; //~ ERROR expected `;`, found `/` +type bptr = &lifetime/int; //~ ERROR expected one of `(`, `+`, `::`, or `;`, found `/` diff --git a/src/test/compile-fail/removed-syntax-record.rs b/src/test/compile-fail/removed-syntax-record.rs index b31e2538ab9..ae5a68575f7 100644 --- a/src/test/compile-fail/removed-syntax-record.rs +++ b/src/test/compile-fail/removed-syntax-record.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type t = { f: () }; //~ ERROR expected type, found token OpenDelim(Brace) +type t = { f: () }; //~ ERROR expected type, found `{` diff --git a/src/test/compile-fail/removed-syntax-uniq-mut-expr.rs b/src/test/compile-fail/removed-syntax-uniq-mut-expr.rs index 124b3738fab..c5559c4ea96 100644 --- a/src/test/compile-fail/removed-syntax-uniq-mut-expr.rs +++ b/src/test/compile-fail/removed-syntax-uniq-mut-expr.rs @@ -11,5 +11,5 @@ fn f() { let a_box = box mut 42; //~^ ERROR expected identifier, found keyword `mut` - //~^^ ERROR expected `;`, found `42` + //~^^ ERROR expected one of `!`, `.`, `::`, `;`, `{`, or an operator, found `42` } diff --git a/src/test/compile-fail/removed-syntax-uniq-mut-ty.rs b/src/test/compile-fail/removed-syntax-uniq-mut-ty.rs index 579bfed1331..8c3db89bad2 100644 --- a/src/test/compile-fail/removed-syntax-uniq-mut-ty.rs +++ b/src/test/compile-fail/removed-syntax-uniq-mut-ty.rs @@ -10,4 +10,4 @@ type mut_box = Box; //~^ ERROR expected identifier, found keyword `mut` - //~^^ ERROR expected `,`, found `int` + //~^^ ERROR expected one of `(`, `+`, `,`, `::`, or `>`, found `int` diff --git a/src/test/compile-fail/removed-syntax-with-1.rs b/src/test/compile-fail/removed-syntax-with-1.rs index fd8cdb7b10e..c7f31045cb6 100644 --- a/src/test/compile-fail/removed-syntax-with-1.rs +++ b/src/test/compile-fail/removed-syntax-with-1.rs @@ -16,5 +16,5 @@ fn removed_with() { let a = S { foo: (), bar: () }; let b = S { foo: () with a }; - //~^ ERROR expected one of `,`, `}`, found `with` + //~^ ERROR expected one of `,`, `.`, `}`, or an operator, found `with` } diff --git a/src/test/compile-fail/struct-literal-in-for.rs b/src/test/compile-fail/struct-literal-in-for.rs index ccd711d8375..a37197b889d 100644 --- a/src/test/compile-fail/struct-literal-in-for.rs +++ b/src/test/compile-fail/struct-literal-in-for.rs @@ -20,7 +20,7 @@ impl Foo { fn main() { for x in Foo { - x: 3 //~ ERROR expected one of `;`, `}` + x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:` }.hi() { println!("yo"); } diff --git a/src/test/compile-fail/struct-literal-in-if.rs b/src/test/compile-fail/struct-literal-in-if.rs index d63c216c3be..9759e4f7bda 100644 --- a/src/test/compile-fail/struct-literal-in-if.rs +++ b/src/test/compile-fail/struct-literal-in-if.rs @@ -20,7 +20,7 @@ impl Foo { fn main() { if Foo { - x: 3 //~ ERROR expected one of `;`, `}` + x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:` }.hi() { println!("yo"); } diff --git a/src/test/compile-fail/struct-literal-in-match-discriminant.rs b/src/test/compile-fail/struct-literal-in-match-discriminant.rs index c740ba02062..297d3f7347f 100644 --- a/src/test/compile-fail/struct-literal-in-match-discriminant.rs +++ b/src/test/compile-fail/struct-literal-in-match-discriminant.rs @@ -14,7 +14,7 @@ struct Foo { fn main() { match Foo { - x: 3 //~ ERROR expected `=>` + x: 3 //~ ERROR expected one of `!`, `=>`, `@`, or `|`, found `:` } { Foo { x: x diff --git a/src/test/compile-fail/struct-literal-in-while.rs b/src/test/compile-fail/struct-literal-in-while.rs index 7b2c11e2597..5b1679cf9a1 100644 --- a/src/test/compile-fail/struct-literal-in-while.rs +++ b/src/test/compile-fail/struct-literal-in-while.rs @@ -20,7 +20,7 @@ impl Foo { fn main() { while Foo { - x: 3 //~ ERROR expected one of `;`, `}` + x: 3 //~ ERROR expected one of `!`, `.`, `::`, `;`, `{`, `}`, or an operator, found `:` }.hi() { println!("yo"); } -- cgit 1.4.1-3-g733a5 From 096a28607fb80c91e6e2ca64d9ef44c4e550e96c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 5 Dec 2014 17:01:33 -0800 Subject: librustc: Make `Copy` opt-in. This change makes the compiler no longer infer whether types (structures and enumerations) implement the `Copy` trait (and thus are implicitly copyable). Rather, you must implement `Copy` yourself via `impl Copy for MyType {}`. A new warning has been added, `missing_copy_implementations`, to warn you if a non-generic public type has been added that could have implemented `Copy` but didn't. For convenience, you may *temporarily* opt out of this behavior by using `#![feature(opt_out_copy)]`. Note though that this feature gate will never be accepted and will be removed by the time that 1.0 is released, so you should transition your code away from using it. This breaks code like: #[deriving(Show)] struct Point2D { x: int, y: int, } fn main() { let mypoint = Point2D { x: 1, y: 1, }; let otherpoint = mypoint; println!("{}{}", mypoint, otherpoint); } Change this code to: #[deriving(Show)] struct Point2D { x: int, y: int, } impl Copy for Point2D {} fn main() { let mypoint = Point2D { x: 1, y: 1, }; let otherpoint = mypoint; println!("{}{}", mypoint, otherpoint); } This is the backwards-incompatible part of #13231. Part of RFC #3. [breaking-change] --- src/compiletest/common.rs | 2 + src/doc/guide-unsafe.md | 3 + src/doc/reference.md | 4 + src/libarena/lib.rs | 2 +- src/libcollections/binary_heap.rs | 2 + src/libcollections/dlist.rs | 9 +- src/libcollections/enum_set.rs | 7 + src/libcollections/hash/sip.rs | 3 + src/libcollections/slice.rs | 16 +- src/libcollections/str.rs | 34 +-- src/libcore/atomic.rs | 3 + src/libcore/char.rs | 1 + src/libcore/cmp.rs | 7 +- src/libcore/fmt/mod.rs | 4 + src/libcore/fmt/num.rs | 5 + src/libcore/fmt/rt.rs | 13 ++ src/libcore/intrinsics.rs | 6 + src/libcore/iter.rs | 11 +- src/libcore/kinds.rs | 17 ++ src/libcore/lib.rs | 2 +- src/libcore/num/mod.rs | 2 + src/libcore/ops.rs | 32 +++ src/libcore/option.rs | 7 +- src/libcore/ptr.rs | 1 + src/libcore/raw.rs | 9 + src/libcore/result.rs | 5 + src/libcore/simd.rs | 23 ++ src/libcore/slice.rs | 6 + src/libcore/str.rs | 9 +- src/libfmt_macros/lib.rs | 14 ++ src/libgetopts/lib.rs | 26 ++- src/liblibc/lib.rs | 248 +++++++++++---------- src/liblog/lib.rs | 4 + src/librand/chacha.rs | 2 + src/librand/distributions/exponential.rs | 5 + src/librand/distributions/normal.rs | 7 + src/librand/isaac.rs | 5 + src/librand/lib.rs | 12 + src/librand/reseeding.rs | 2 + src/librbml/lib.rs | 6 + src/libregex/parse.rs | 2 + src/libregex/re.rs | 8 +- src/libregex/vm.rs | 4 + src/librustc/lint/builtin.rs | 102 ++++++++- src/librustc/lint/context.rs | 1 + src/librustc/lint/mod.rs | 8 + src/librustc/metadata/common.rs | 2 + src/librustc/metadata/creader.rs | 6 +- src/librustc/metadata/csearch.rs | 7 +- src/librustc/metadata/cstore.rs | 17 +- src/librustc/metadata/decoder.rs | 6 +- src/librustc/metadata/filesearch.rs | 7 +- src/librustc/metadata/tydecode.rs | 2 + src/librustc/middle/borrowck/check_loans.rs | 14 +- src/librustc/middle/borrowck/gather_loans/mod.rs | 12 +- src/librustc/middle/borrowck/graphviz.rs | 2 + src/librustc/middle/borrowck/mod.rs | 37 ++- src/librustc/middle/borrowck/move_data.rs | 16 ++ src/librustc/middle/cfg/construct.rs | 2 + src/librustc/middle/cfg/mod.rs | 2 + src/librustc/middle/check_loop.rs | 4 + src/librustc/middle/check_match.rs | 26 ++- src/librustc/middle/check_rvalues.rs | 6 +- src/librustc/middle/check_static.rs | 10 +- src/librustc/middle/const_eval.rs | 2 + src/librustc/middle/dataflow.rs | 7 +- src/librustc/middle/def.rs | 4 + src/librustc/middle/effect.rs | 2 + src/librustc/middle/expr_use_visitor.rs | 69 ++++-- src/librustc/middle/fast_reject.rs | 2 + src/librustc/middle/graph.rs | 6 + src/librustc/middle/infer/mod.rs | 6 + src/librustc/middle/infer/region_inference/mod.rs | 16 ++ src/librustc/middle/infer/type_variable.rs | 2 + src/librustc/middle/infer/unify.rs | 2 + src/librustc/middle/lang_items.rs | 2 + src/librustc/middle/liveness.rs | 15 ++ src/librustc/middle/mem_categorization.rs | 22 ++ src/librustc/middle/region.rs | 4 + src/librustc/middle/resolve.rs | 40 ++++ src/librustc/middle/resolve_lifetime.rs | 2 + src/librustc/middle/subst.rs | 2 + src/librustc/middle/traits/mod.rs | 8 +- src/librustc/middle/traits/select.rs | 29 ++- src/librustc/middle/ty.rs | 229 +++++++++++++++---- src/librustc/session/config.rs | 12 +- src/librustc/util/common.rs | 2 + src/librustc/util/nodemap.rs | 3 + src/librustc_driver/pretty.rs | 4 + src/librustc_llvm/diagnostic.rs | 6 + src/librustc_llvm/lib.rs | 65 ++++++ src/librustc_trans/back/write.rs | 11 + src/librustc_trans/save/mod.rs | 2 +- src/librustc_trans/save/recorder.rs | 7 +- src/librustc_trans/save/span_utils.rs | 1 + src/librustc_trans/trans/_match.rs | 27 ++- src/librustc_trans/trans/adt.rs | 5 +- src/librustc_trans/trans/base.rs | 24 +- src/librustc_trans/trans/basic_block.rs | 2 + src/librustc_trans/trans/cabi.rs | 4 + src/librustc_trans/trans/cabi_x86_64.rs | 2 + src/librustc_trans/trans/callee.rs | 4 + src/librustc_trans/trans/cleanup.rs | 18 ++ src/librustc_trans/trans/closure.rs | 2 + src/librustc_trans/trans/common.rs | 9 +- src/librustc_trans/trans/datum.rs | 24 +- src/librustc_trans/trans/debuginfo.rs | 6 + src/librustc_trans/trans/expr.rs | 4 + src/librustc_trans/trans/mod.rs | 2 + src/librustc_trans/trans/tvec.rs | 4 +- src/librustc_trans/trans/type_.rs | 2 + src/librustc_trans/trans/type_of.rs | 5 +- src/librustc_trans/trans/value.rs | 10 +- src/librustc_typeck/check/method/mod.rs | 2 + src/librustc_typeck/check/mod.rs | 8 + src/librustc_typeck/check/wf.rs | 5 + src/librustc_typeck/check/writeback.rs | 2 + src/librustc_typeck/coherence/mod.rs | 80 ++++++- src/librustc_typeck/collect.rs | 2 + src/librustc_typeck/rscope.rs | 3 + src/librustc_typeck/variance.rs | 10 +- src/librustdoc/clean/mod.rs | 6 + src/librustdoc/doctree.rs | 2 + src/librustdoc/html/format.rs | 5 + src/librustdoc/html/item_type.rs | 2 + src/librustdoc/html/render.rs | 8 +- src/librustdoc/stability_summary.rs | 2 + src/librustrt/bookkeeping.rs | 1 + src/librustrt/c_str.rs | 1 + src/librustrt/mutex.rs | 12 + src/librustrt/unwind.rs | 1 + src/librustrt/util.rs | 3 + src/libserialize/base64.rs | 6 + src/libserialize/hex.rs | 2 + src/libserialize/json.rs | 4 + src/libstd/ascii.rs | 3 + src/libstd/bitflags.rs | 9 + src/libstd/collections/hash/table.rs | 6 +- src/libstd/comm/mod.rs | 2 + src/libstd/dynamic_lib.rs | 8 +- src/libstd/io/mod.rs | 17 ++ src/libstd/io/net/addrinfo.rs | 11 + src/libstd/io/net/ip.rs | 5 + src/libstd/io/process.rs | 4 + src/libstd/io/util.rs | 6 + src/libstd/num/strconv.rs | 51 +++-- src/libstd/os.rs | 12 + src/libstd/path/windows.rs | 3 + src/libstd/rand/mod.rs | 7 +- src/libstd/time/duration.rs | 3 + src/libsyntax/abi.rs | 22 +- src/libsyntax/ast.rs | 65 +++++- src/libsyntax/ast_map/blocks.rs | 4 + src/libsyntax/ast_map/mod.rs | 6 + src/libsyntax/ast_util.rs | 2 + src/libsyntax/attr.rs | 8 + src/libsyntax/codemap.rs | 14 ++ src/libsyntax/diagnostic.rs | 10 + src/libsyntax/ext/base.rs | 10 +- src/libsyntax/ext/deriving/cmp/ord.rs | 2 + src/libsyntax/ext/mtwt.rs | 2 + src/libsyntax/feature_gate.rs | 2 + src/libsyntax/parse/lexer/comments.rs | 2 + src/libsyntax/parse/obsolete.rs | 2 + src/libsyntax/parse/parser.rs | 4 + src/libsyntax/parse/token.rs | 12 + src/libsyntax/print/pp.rs | 10 + src/libsyntax/print/pprust.rs | 4 + src/libsyntax/visit.rs | 2 + src/libterm/lib.rs | 3 + src/libterm/terminfo/parm.rs | 8 + src/libtest/lib.rs | 19 +- src/libtime/lib.rs | 12 +- src/libunicode/tables.rs | 3 + src/test/auxiliary/issue-14422.rs | 2 + src/test/auxiliary/issue13213aux.rs | 4 + src/test/auxiliary/lang-item-public.rs | 5 + src/test/auxiliary/method_self_arg1.rs | 2 + src/test/auxiliary/method_self_arg2.rs | 2 + src/test/auxiliary/xcrate_unit_struct.rs | 11 + src/test/bench/noise.rs | 2 + src/test/bench/shootout-chameneos-redux.rs | 11 +- src/test/bench/shootout-fannkuch-redux.rs | 4 + src/test/bench/shootout-fasta-redux.rs | 2 + src/test/bench/shootout-k-nucleotide.rs | 2 + src/test/bench/shootout-nbody.rs | 2 + .../compile-fail/borrowck-borrow-from-owned-ptr.rs | 4 + .../borrowck-borrow-from-stack-variable.rs | 4 + .../borrowck-loan-local-as-both-mut-and-imm.rs | 35 --- src/test/compile-fail/borrowck-use-mut-borrow.rs | 3 + src/test/compile-fail/dst-index.rs | 7 +- src/test/compile-fail/dst-rvalue.rs | 2 + src/test/compile-fail/issue-17651.rs | 3 +- src/test/compile-fail/kindck-copy.rs | 3 + src/test/compile-fail/lint-dead-code-1.rs | 1 + src/test/compile-fail/lint-missing-doc.rs | 1 + src/test/compile-fail/opt-in-copy.rs | 33 +++ .../stage0-clone-contravariant-lifetime.rs | 43 ---- src/test/compile-fail/stage0-cmp.rs | 39 ---- src/test/debuginfo/c-style-enum.rs | 3 + .../debuginfo/generic-method-on-generic-struct.rs | 3 + src/test/debuginfo/method-on-enum.rs | 3 + src/test/debuginfo/method-on-generic-struct.rs | 3 + src/test/debuginfo/method-on-struct.rs | 3 + src/test/debuginfo/method-on-trait.rs | 3 + src/test/debuginfo/method-on-tuple-struct.rs | 3 + src/test/debuginfo/self-in-default-method.rs | 3 + .../debuginfo/self-in-generic-default-method.rs | 3 + src/test/pretty/block-disambig.rs | 2 + .../run-make/extern-fn-with-packed-struct/test.rs | 2 + src/test/run-make/target-specs/foo.rs | 3 + src/test/run-pass/borrowck-univariant-enum.rs | 2 + .../run-pass/builtin-superkinds-in-metadata.rs | 8 +- src/test/run-pass/cell-does-not-clone.rs | 2 + .../class-impl-very-parameterized-trait.rs | 2 + src/test/run-pass/coherence-impl-in-fn.rs | 1 + src/test/run-pass/coherence-where-clause.rs | 2 + src/test/run-pass/const-nullary-univariant-enum.rs | 2 + src/test/run-pass/dst-struct-sole.rs | 2 + src/test/run-pass/dst-struct.rs | 2 + src/test/run-pass/dst-trait.rs | 4 + src/test/run-pass/empty-tag.rs | 2 + src/test/run-pass/enum-discrim-width-stuff.rs | 1 + src/test/run-pass/explicit-self-generic.rs | 4 + src/test/run-pass/export-unexported-dep.rs | 2 + src/test/run-pass/expr-copy.rs | 2 + src/test/run-pass/expr-if-struct.rs | 4 + src/test/run-pass/expr-match-struct.rs | 4 + src/test/run-pass/exterior.rs | 2 + src/test/run-pass/extern-pass-TwoU16s.rs | 2 + src/test/run-pass/extern-pass-TwoU32s.rs | 2 + src/test/run-pass/extern-pass-TwoU64s.rs | 2 + src/test/run-pass/extern-pass-TwoU8s.rs | 2 + src/test/run-pass/foreign-fn-with-byval.rs | 2 + src/test/run-pass/generic-fn.rs | 2 + src/test/run-pass/guards-not-exhaustive.rs | 2 + src/test/run-pass/guards.rs | 2 + src/test/run-pass/issue-12860.rs | 2 + src/test/run-pass/issue-19100.rs | 2 + src/test/run-pass/issue-2288.rs | 3 + src/test/run-pass/issue-2633.rs | 4 + src/test/run-pass/issue-3121.rs | 4 + src/test/run-pass/issue-3563-3.rs | 6 + src/test/run-pass/issue-3743.rs | 2 + src/test/run-pass/issue-3753.rs | 4 + src/test/run-pass/issue-5688.rs | 4 + src/test/run-pass/lang-item-public.rs | 1 + src/test/run-pass/match-arm-statics.rs | 2 + src/test/run-pass/method-self-arg-trait.rs | 2 + src/test/run-pass/method-self-arg.rs | 2 + src/test/run-pass/monomorphize-abi-alignment.rs | 15 +- src/test/run-pass/multidispatch1.rs | 2 + src/test/run-pass/multidispatch2.rs | 2 + src/test/run-pass/newtype.rs | 9 +- src/test/run-pass/out-pointer-aliasing.rs | 2 + src/test/run-pass/overloaded-autoderef-order.rs | 4 + src/test/run-pass/packed-struct-vec.rs | 2 + src/test/run-pass/rec-tup.rs | 2 + src/test/run-pass/rec.rs | 2 + src/test/run-pass/regions-dependent-addr-of.rs | 2 + .../regions-early-bound-used-in-bound-method.rs | 2 + .../run-pass/regions-early-bound-used-in-bound.rs | 2 + .../regions-early-bound-used-in-type-param.rs | 2 + src/test/run-pass/regions-mock-tcx.rs | 9 + .../run-pass/self-in-mut-slot-immediate-value.rs | 2 + src/test/run-pass/shape_intrinsic_tag_then_rec.rs | 67 ------ src/test/run-pass/simd-generics.rs | 2 + src/test/run-pass/small-enum-range-edge.rs | 6 + src/test/run-pass/struct-return.rs | 5 + src/test/run-pass/structured-compare.rs | 2 + src/test/run-pass/tag-variant-disr-val.rs | 2 + src/test/run-pass/trait-coercion-generic.rs | 2 + src/test/run-pass/trait-coercion.rs | 2 + src/test/run-pass/typeclasses-eq-example-static.rs | 11 +- src/test/run-pass/typeclasses-eq-example.rs | 8 +- src/test/run-pass/ufcs-explicit-self.rs | 4 + .../run-pass/unboxed-closures-monomorphization.rs | 3 + 277 files changed, 2182 insertions(+), 513 deletions(-) delete mode 100644 src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs create mode 100644 src/test/compile-fail/opt-in-copy.rs delete mode 100644 src/test/compile-fail/stage0-clone-contravariant-lifetime.rs delete mode 100644 src/test/compile-fail/stage0-cmp.rs delete mode 100644 src/test/run-pass/shape_intrinsic_tag_then_rec.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index 0a902d970ef..62b757529dc 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -25,6 +25,8 @@ pub enum Mode { Codegen } +impl Copy for Mode {} + impl FromStr for Mode { fn from_str(s: &str) -> Option { match s { diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md index 5b248126c80..bda1b345632 100644 --- a/src/doc/guide-unsafe.md +++ b/src/doc/guide-unsafe.md @@ -661,6 +661,9 @@ extern { fn abort() -> !; } +#[lang = "owned_box"] +pub struct Box(*mut T); + #[lang="exchange_malloc"] unsafe fn allocate(size: uint, _align: uint) -> *mut u8 { let p = libc::malloc(size as libc::size_t) as *mut u8; diff --git a/src/doc/reference.md b/src/doc/reference.md index 9ac4469d549..f6ee5cadbc6 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1660,6 +1660,7 @@ Implementations are defined with the keyword `impl`. ``` # struct Point {x: f64, y: f64}; +# impl Copy for Point {} # type Surface = int; # struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; # trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; } @@ -1669,6 +1670,8 @@ struct Circle { center: Point, } +impl Copy for Circle {} + impl Shape for Circle { fn draw(&self, s: Surface) { do_draw_circle(s, *self); } fn bounding_box(&self) -> BoundingBox { @@ -1791,6 +1794,7 @@ default visibility with the `priv` keyword. When an item is declared as `pub`, it can be thought of as being accessible to the outside world. For example: ``` +# #![allow(missing_copy_implementations)] # fn main() {} // Declare a private struct struct Foo; diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 8b84ecb6904..95c4dff323e 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -466,7 +466,7 @@ impl TypedArena { } let ptr: &mut T = unsafe { - let ptr: &mut T = mem::transmute(self.ptr); + let ptr: &mut T = mem::transmute(self.ptr.clone()); ptr::write(ptr, object); self.ptr.set(self.ptr.get().offset(1)); ptr diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index e321ef16f66..a4722c340dd 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -35,6 +35,8 @@ //! position: uint //! } //! +//! impl Copy for State {} +//! //! // The priority queue depends on `Ord`. //! // Explicitly implement the trait so the queue becomes a min-heap //! // instead of a max-heap. diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index a30bb9e978b..4309e96bec4 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -39,7 +39,12 @@ pub struct DList { } type Link = Option>>; -struct Rawlink { p: *mut T } + +struct Rawlink { + p: *mut T, +} + +impl Copy for Rawlink {} struct Node { next: Link, @@ -59,6 +64,8 @@ impl<'a, T> Clone for Items<'a, T> { fn clone(&self) -> Items<'a, T> { *self } } +impl<'a,T> Copy for Items<'a,T> {} + /// An iterator over mutable references to the items of a `DList`. pub struct MutItems<'a, T:'a> { list: &'a mut DList, diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 5e77cf66726..28514b99192 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -27,6 +27,8 @@ pub struct EnumSet { bits: uint } +impl Copy for EnumSet {} + impl fmt::Show for EnumSet { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(write!(fmt, "{{")); @@ -269,6 +271,8 @@ mod test { A, B, C } + impl Copy for Foo {} + impl CLike for Foo { fn to_uint(&self) -> uint { *self as uint @@ -477,6 +481,9 @@ mod test { V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, } + + impl Copy for Bar {} + impl CLike for Bar { fn to_uint(&self) -> uint { *self as uint diff --git a/src/libcollections/hash/sip.rs b/src/libcollections/hash/sip.rs index ab69a3ad8b8..9a7aa8c20d3 100644 --- a/src/libcollections/hash/sip.rs +++ b/src/libcollections/hash/sip.rs @@ -43,6 +43,8 @@ pub struct SipState { ntail: uint, // how many bytes in tail are valid } +impl Copy for SipState {} + // sadly, these macro definitions can't appear later, // because they're needed in the following defs; // this design could be improved. @@ -211,6 +213,7 @@ impl Default for SipState { /// `SipHasher` computes the SipHash algorithm from a stream of bytes. #[deriving(Clone)] +#[allow(missing_copy_implementations)] pub struct SipHasher { k0: u64, k1: u64, diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 03b8ea8f20f..c230c48d222 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -91,7 +91,7 @@ use self::Direction::*; use alloc::boxed::Box; use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned}; use core::cmp; -use core::kinds::Sized; +use core::kinds::{Copy, Sized}; use core::mem::size_of; use core::mem; use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option}; @@ -177,12 +177,16 @@ impl ElementSwaps { enum Direction { Pos, Neg } +impl Copy for Direction {} + /// An `Index` and `Direction` together. struct SizeDirection { size: uint, dir: Direction, } +impl Copy for SizeDirection {} + impl Iterator<(uint, uint)> for ElementSwaps { #[inline] fn next(&mut self) -> Option<(uint, uint)> { @@ -1482,11 +1486,17 @@ mod tests { fn clone(&self) -> S { self.f.set(self.f.get() + 1); if self.f.get() == 10 { panic!() } - S { f: self.f, boxes: self.boxes.clone() } + S { + f: self.f.clone(), + boxes: self.boxes.clone(), + } } } - let s = S { f: Cell::new(0), boxes: (box 0, Rc::new(0)) }; + let s = S { + f: Cell::new(0), + boxes: (box 0, Rc::new(0)), + }; let _ = Vec::from_elem(100, s); } diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 28027198143..419d7f270ad 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -228,24 +228,32 @@ impl<'a> Iterator for Decompositions<'a> { _ => self.sorted = false } - let decomposer = match self.kind { - Canonical => unicode::char::decompose_canonical, - Compatible => unicode::char::decompose_compatible - }; - if !self.sorted { for ch in self.iter { let buffer = &mut self.buffer; let sorted = &mut self.sorted; - decomposer(ch, |d| { - let class = unicode::char::canonical_combining_class(d); - if class == 0 && !*sorted { - canonical_sort(buffer.as_mut_slice()); - *sorted = true; + { + let callback = |d| { + let class = + unicode::char::canonical_combining_class(d); + if class == 0 && !*sorted { + canonical_sort(buffer.as_mut_slice()); + *sorted = true; + } + buffer.push((d, class)); + }; + match self.kind { + Canonical => { + unicode::char::decompose_canonical(ch, callback) + } + Compatible => { + unicode::char::decompose_compatible(ch, callback) + } } - buffer.push((d, class)); - }); - if *sorted { break } + } + if *sorted { + break + } } } diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index e930f353b52..748f5d774a4 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -17,6 +17,7 @@ pub use self::Ordering::*; use intrinsics; use std::kinds::marker; use cell::UnsafeCell; +use kinds::Copy; /// A boolean type which can be safely shared between threads. #[stable] @@ -81,6 +82,8 @@ pub enum Ordering { SeqCst, } +impl Copy for Ordering {} + /// An `AtomicBool` initialized to `false`. #[unstable = "may be renamed, pending conventions for static initalizers"] pub const INIT_ATOMIC_BOOL: AtomicBool = diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 2bebe87a14c..8485e40819b 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -519,3 +519,4 @@ impl Iterator for DefaultEscapedChars { } } } + diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index a5ba2b03b15..87fa44cea66 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -43,9 +43,8 @@ pub use self::Ordering::*; -use kinds::Sized; -use option::Option; -use option::Option::{Some, None}; +use kinds::{Copy, Sized}; +use option::{Option, Some, None}; /// Trait for values that can be compared for equality and inequality. /// @@ -106,6 +105,8 @@ pub enum Ordering { Greater = 1i, } +impl Copy for Ordering {} + impl Ordering { /// Reverse the `Ordering`, so that `Less` becomes `Greater` and /// vice versa. diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8b2ffd90ef7..88ea811cfd6 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -46,6 +46,8 @@ pub type Result = result::Result<(), Error>; #[experimental = "core and I/O reconciliation may alter this definition"] pub struct Error; +impl Copy for Error {} + /// A collection of methods that are required to format a message into a stream. /// /// This trait is the type which this modules requires when formatting @@ -135,6 +137,8 @@ impl<'a> Argument<'a> { } } +impl<'a> Copy for Argument<'a> {} + impl<'a> Arguments<'a> { /// When using the format_args!() macro, this function is used to generate the /// Arguments structure. diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index a441ced03b2..fa6f48326b5 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -16,6 +16,7 @@ use fmt; use iter::DoubleEndedIteratorExt; +use kinds::Copy; use num::{Int, cast}; use slice::SlicePrelude; @@ -114,6 +115,8 @@ pub struct Radix { base: u8, } +impl Copy for Radix {} + impl Radix { fn new(base: u8) -> Radix { assert!(2 <= base && base <= 36, "the base must be in the range of 2..36: {}", base); @@ -136,6 +139,8 @@ impl GenericRadix for Radix { #[unstable = "may be renamed or move to a different module"] pub struct RadixFmt(T, R); +impl Copy for RadixFmt where T: Copy, R: Copy {} + /// Constructs a radix formatter in the range of `2..36`. /// /// # Example diff --git a/src/libcore/fmt/rt.rs b/src/libcore/fmt/rt.rs index 145e78dc668..748bd0bc4bd 100644 --- a/src/libcore/fmt/rt.rs +++ b/src/libcore/fmt/rt.rs @@ -20,6 +20,7 @@ pub use self::Alignment::*; pub use self::Count::*; pub use self::Position::*; pub use self::Flag::*; +use kinds::Copy; #[doc(hidden)] pub struct Argument<'a> { @@ -27,6 +28,8 @@ pub struct Argument<'a> { pub format: FormatSpec, } +impl<'a> Copy for Argument<'a> {} + #[doc(hidden)] pub struct FormatSpec { pub fill: char, @@ -36,6 +39,8 @@ pub struct FormatSpec { pub width: Count, } +impl Copy for FormatSpec {} + /// Possible alignments that can be requested as part of a formatting directive. #[deriving(PartialEq)] pub enum Alignment { @@ -49,16 +54,22 @@ pub enum Alignment { AlignUnknown, } +impl Copy for Alignment {} + #[doc(hidden)] pub enum Count { CountIs(uint), CountIsParam(uint), CountIsNextParam, CountImplied, } +impl Copy for Count {} + #[doc(hidden)] pub enum Position { ArgumentNext, ArgumentIs(uint) } +impl Copy for Position {} + /// Flags which can be passed to formatting via a directive. /// /// These flags are discovered through the `flags` field of the `Formatter` @@ -78,3 +89,5 @@ pub enum Flag { /// being aware of the sign to be printed. FlagSignAwareZeroPad, } + +impl Copy for Flag {} diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ece2ac6975e..2fc4d23e7fd 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -42,6 +42,8 @@ #![experimental] #![allow(missing_docs)] +use kinds::Copy; + pub type GlueFn = extern "Rust" fn(*const i8); #[lang="ty_desc"] @@ -59,6 +61,8 @@ pub struct TyDesc { pub name: &'static str, } +impl Copy for TyDesc {} + extern "rust-intrinsic" { // NB: These intrinsics take unsafe pointers because they mutate aliased @@ -539,6 +543,8 @@ pub struct TypeId { t: u64, } +impl Copy for TypeId {} + impl TypeId { /// Returns the `TypeId` of the type this generic function has been instantiated with pub fn of() -> TypeId { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 49865bd3c7d..ddca9d36bed 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -59,6 +59,7 @@ pub use self::MinMaxResult::*; use clone::Clone; use cmp; use cmp::Ord; +use kinds::Copy; use mem; use num::{ToPrimitive, Int}; use ops::{Add, Deref}; @@ -1166,7 +1167,8 @@ pub struct Cycle { iter: T, } -#[unstable = "trait is unstable"] +impl Copy for Cycle {} + impl> Iterator
for Cycle { #[inline] fn next(&mut self) -> Option { @@ -1576,7 +1578,8 @@ pub struct Peekable { peeked: Option, } -#[unstable = "trait is unstable"] +impl Copy for Peekable {} + impl> Iterator for Peekable { #[inline] fn next(&mut self) -> Option { @@ -2115,6 +2118,8 @@ pub struct Counter { step: A, } +impl Copy for Counter {} + /// Creates a new counter with the specified start/step #[inline] #[unstable = "may be renamed"] @@ -2146,6 +2151,8 @@ pub struct Range { one: A, } +impl Copy for Range {} + /// Returns an iterator over the given range [start, stop) (that is, starting /// at start (inclusive), and ending at stop (exclusive)). /// diff --git a/src/libcore/kinds.rs b/src/libcore/kinds.rs index 0c2cb9d5910..f932acffd3c 100644 --- a/src/libcore/kinds.rs +++ b/src/libcore/kinds.rs @@ -91,6 +91,8 @@ pub trait Sync for Sized? { /// implemented using unsafe code. In that case, you may want to embed /// some of the marker types below into your type. pub mod marker { + use super::Copy; + /// A marker type whose type parameter `T` is considered to be /// covariant with respect to the type itself. This is (typically) /// used to indicate that an instance of the type `T` is being stored @@ -132,6 +134,8 @@ pub mod marker { #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct CovariantType; + impl Copy for CovariantType {} + /// A marker type whose type parameter `T` is considered to be /// contravariant with respect to the type itself. This is (typically) /// used to indicate that an instance of the type `T` will be consumed @@ -175,6 +179,8 @@ pub mod marker { #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct ContravariantType; + impl Copy for ContravariantType {} + /// A marker type whose type parameter `T` is considered to be /// invariant with respect to the type itself. This is (typically) /// used to indicate that instances of the type `T` may be read or @@ -200,6 +206,8 @@ pub mod marker { #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct InvariantType; + impl Copy for InvariantType {} + /// As `CovariantType`, but for lifetime parameters. Using /// `CovariantLifetime<'a>` indicates that it is ok to substitute /// a *longer* lifetime for `'a` than the one you originally @@ -220,6 +228,8 @@ pub mod marker { #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct CovariantLifetime<'a>; + impl<'a> Copy for CovariantLifetime<'a> {} + /// As `ContravariantType`, but for lifetime parameters. Using /// `ContravariantLifetime<'a>` indicates that it is ok to /// substitute a *shorter* lifetime for `'a` than the one you @@ -236,6 +246,8 @@ pub mod marker { #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct ContravariantLifetime<'a>; + impl<'a> Copy for ContravariantLifetime<'a> {} + /// As `InvariantType`, but for lifetime parameters. Using /// `InvariantLifetime<'a>` indicates that it is not ok to /// substitute any other lifetime for `'a` besides its original @@ -253,6 +265,7 @@ pub mod marker { /// their instances remain thread-local. #[lang="no_send_bound"] #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] + #[allow(missing_copy_implementations)] pub struct NoSend; /// A type which is considered "not POD", meaning that it is not @@ -260,6 +273,7 @@ pub mod marker { /// ensure that they are never copied, even if they lack a destructor. #[lang="no_copy_bound"] #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] + #[allow(missing_copy_implementations)] pub struct NoCopy; /// A type which is considered "not sync", meaning that @@ -267,11 +281,14 @@ pub mod marker { /// shared between tasks. #[lang="no_sync_bound"] #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] + #[allow(missing_copy_implementations)] pub struct NoSync; /// A type which is considered managed by the GC. This is typically /// embedded in other types. #[lang="managed_bound"] #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)] + #[allow(missing_copy_implementations)] pub struct Managed; } + diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5ad9462daf2..09d5061a02f 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -56,7 +56,7 @@ html_playground_url = "http://play.rust-lang.org/")] #![no_std] -#![allow(unknown_features)] +#![allow(unknown_features, raw_pointer_deriving)] #![feature(globs, intrinsics, lang_items, macro_rules, phase)] #![feature(simd, unsafe_destructor, slicing_syntax)] #![feature(default_type_params)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index e6946c83ceb..3c9b68b350b 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1240,6 +1240,8 @@ pub enum FPCategory { FPNormal, } +impl Copy for FPCategory {} + /// A built-in floating point number. // FIXME(#5527): In a future version of Rust, many of these functions will // become constants. diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index ce774a66381..e16b24923a8 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -90,6 +90,8 @@ pub trait Drop { /// ```rust /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Add for Foo { /// fn add(&self, _rhs: &Foo) -> Foo { /// println!("Adding!"); @@ -128,6 +130,8 @@ add_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) /// ```rust /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Sub for Foo { /// fn sub(&self, _rhs: &Foo) -> Foo { /// println!("Subtracting!"); @@ -166,6 +170,8 @@ sub_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) /// ```rust /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Mul for Foo { /// fn mul(&self, _rhs: &Foo) -> Foo { /// println!("Multiplying!"); @@ -204,6 +210,8 @@ mul_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Div for Foo { /// fn div(&self, _rhs: &Foo) -> Foo { /// println!("Dividing!"); @@ -242,6 +250,8 @@ div_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Rem for Foo { /// fn rem(&self, _rhs: &Foo) -> Foo { /// println!("Remainder-ing!"); @@ -294,6 +304,8 @@ rem_float_impl!(f64, fmod) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Neg for Foo { /// fn neg(&self) -> Foo { /// println!("Negating!"); @@ -348,6 +360,8 @@ neg_uint_impl!(u64, i64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Not for Foo { /// fn not(&self) -> Foo { /// println!("Not-ing!"); @@ -387,6 +401,8 @@ not_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl BitAnd for Foo { /// fn bitand(&self, _rhs: &Foo) -> Foo { /// println!("Bitwise And-ing!"); @@ -425,6 +441,8 @@ bitand_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl BitOr for Foo { /// fn bitor(&self, _rhs: &Foo) -> Foo { /// println!("Bitwise Or-ing!"); @@ -463,6 +481,8 @@ bitor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl BitXor for Foo { /// fn bitxor(&self, _rhs: &Foo) -> Foo { /// println!("Bitwise Xor-ing!"); @@ -501,6 +521,8 @@ bitxor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Shl for Foo { /// fn shl(&self, _rhs: &Foo) -> Foo { /// println!("Shifting left!"); @@ -541,6 +563,8 @@ shl_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Shr for Foo { /// fn shr(&self, _rhs: &Foo) -> Foo { /// println!("Shifting right!"); @@ -580,6 +604,8 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64) /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Index for Foo { /// fn index<'a>(&'a self, _index: &Foo) -> &'a Foo { /// println!("Indexing!"); @@ -608,6 +634,8 @@ pub trait Index for Sized? { /// ``` /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl IndexMut for Foo { /// fn index_mut<'a>(&'a mut self, _index: &Foo) -> &'a mut Foo { /// println!("Indexing!"); @@ -636,6 +664,8 @@ pub trait IndexMut for Sized? { /// ```ignore /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl Slice for Foo { /// fn as_slice_<'a>(&'a self) -> &'a Foo { /// println!("Slicing!"); @@ -682,6 +712,8 @@ pub trait Slice for Sized? { /// ```ignore /// struct Foo; /// +/// impl Copy for Foo {} +/// /// impl SliceMut for Foo { /// fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Foo { /// println!("Slicing!"); diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 8ba41c3575f..0a8fa28e52c 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -147,7 +147,9 @@ pub use self::Option::*; use cmp::{Eq, Ord}; use default::Default; -use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator}; +use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator}; +use iter::{ExactSizeIterator}; +use kinds::Copy; use mem; use result::Result; use result::Result::{Ok, Err}; @@ -857,3 +859,6 @@ impl> FromIterator> for Option { } } } + +impl Copy for Option {} + diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 3f6ac49786d..5c61a1ed103 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -437,3 +437,4 @@ impl PartialOrd for *mut T { #[inline] fn ge(&self, other: &*mut T) -> bool { *self >= *other } } + diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index d156f71462d..db1be94b2b8 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -18,6 +18,7 @@ //! //! Their definition should always match the ABI defined in `rustc::back::abi`. +use kinds::Copy; use mem; use kinds::Sized; @@ -28,6 +29,8 @@ pub struct Slice { pub len: uint, } +impl Copy for Slice {} + /// The representation of a Rust closure #[repr(C)] pub struct Closure { @@ -35,6 +38,8 @@ pub struct Closure { pub env: *mut (), } +impl Copy for Closure {} + /// The representation of a Rust procedure (`proc()`) #[repr(C)] pub struct Procedure { @@ -42,6 +47,8 @@ pub struct Procedure { pub env: *mut (), } +impl Copy for Procedure {} + /// The representation of a Rust trait object. /// /// This struct does not have a `Repr` implementation @@ -52,6 +59,8 @@ pub struct TraitObject { pub vtable: *mut (), } +impl Copy for TraitObject {} + /// This trait is meant to map equivalences between raw structs and their /// corresponding rust values. pub trait Repr for Sized? { diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 0cf8e6affd7..c5d69b16987 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -232,6 +232,7 @@ pub use self::Result::*; +use kinds::Copy; use std::fmt::Show; use slice; use slice::AsSlice; @@ -916,3 +917,7 @@ pub fn fold Copy for Result {} + diff --git a/src/libcore/simd.rs b/src/libcore/simd.rs index 2b6f97cf6a5..369a7106583 100644 --- a/src/libcore/simd.rs +++ b/src/libcore/simd.rs @@ -37,6 +37,8 @@ #![allow(non_camel_case_types)] #![allow(missing_docs)] +use kinds::Copy; + #[experimental] #[simd] #[deriving(Show)] @@ -46,6 +48,8 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8); +impl Copy for i8x16 {} + #[experimental] #[simd] #[deriving(Show)] @@ -53,18 +57,24 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8, pub struct i16x8(pub i16, pub i16, pub i16, pub i16, pub i16, pub i16, pub i16, pub i16); +impl Copy for i16x8 {} + #[experimental] #[simd] #[deriving(Show)] #[repr(C)] pub struct i32x4(pub i32, pub i32, pub i32, pub i32); +impl Copy for i32x4 {} + #[experimental] #[simd] #[deriving(Show)] #[repr(C)] pub struct i64x2(pub i64, pub i64); +impl Copy for i64x2 {} + #[experimental] #[simd] #[deriving(Show)] @@ -74,6 +84,8 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8); +impl Copy for u8x16 {} + #[experimental] #[simd] #[deriving(Show)] @@ -81,26 +93,37 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8, pub struct u16x8(pub u16, pub u16, pub u16, pub u16, pub u16, pub u16, pub u16, pub u16); +impl Copy for u16x8 {} + #[experimental] #[simd] #[deriving(Show)] #[repr(C)] pub struct u32x4(pub u32, pub u32, pub u32, pub u32); +impl Copy for u32x4 {} + #[experimental] #[simd] #[deriving(Show)] #[repr(C)] pub struct u64x2(pub u64, pub u64); +impl Copy for u64x2 {} + #[experimental] #[simd] #[deriving(Show)] #[repr(C)] pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +impl Copy for f32x4 {} + #[experimental] #[simd] #[deriving(Show)] #[repr(C)] pub struct f64x2(pub f64, pub f64); + +impl Copy for f64x2 {} + diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index b8df36c91bc..4e3007b55fe 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -41,6 +41,7 @@ use cmp::Ordering::{Less, Equal, Greater}; use cmp; use default::Default; use iter::*; +use kinds::Copy; use num::Int; use ops; use option::Option; @@ -1157,6 +1158,8 @@ impl<'a, T> Items<'a, T> { } } +impl<'a,T> Copy for Items<'a,T> {} + iterator!{struct Items -> *const T, &'a T} #[experimental = "needs review"] @@ -1607,6 +1610,8 @@ pub enum BinarySearchResult { NotFound(uint) } +impl Copy for BinarySearchResult {} + #[experimental = "needs review"] impl BinarySearchResult { /// Converts a `Found` to `Some`, `NotFound` to `None`. @@ -1920,3 +1925,4 @@ impl_int_slice!(u16, i16) impl_int_slice!(u32, i32) impl_int_slice!(u64, i64) impl_int_slice!(uint, int) + diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 1d59567cbe4..8f9eeaddfb5 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -26,7 +26,7 @@ use default::Default; use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator}; use iter::{DoubleEndedIteratorExt, ExactSizeIterator}; use iter::range; -use kinds::Sized; +use kinds::{Copy, Sized}; use mem; use num::Int; use option::Option; @@ -176,6 +176,8 @@ pub struct Chars<'a> { iter: slice::Items<'a, u8> } +impl<'a> Copy for Chars<'a> {} + // Return the initial codepoint accumulator for the first byte. // The first byte is special, only want bottom 5 bits for width 2, 4 bits // for width 3, and 3 bits for width 4 @@ -996,6 +998,8 @@ pub enum Utf16Item { LoneSurrogate(u16) } +impl Copy for Utf16Item {} + impl Utf16Item { /// Convert `self` to a `char`, taking `LoneSurrogate`s to the /// replacement character (U+FFFD). @@ -1139,6 +1143,8 @@ pub struct CharRange { pub next: uint, } +impl Copy for CharRange {} + /// Mask of the value bits of a continuation byte const CONT_MASK: u8 = 0b0011_1111u8; /// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte @@ -2315,3 +2321,4 @@ impl StrPrelude for str { impl<'a> Default for &'a str { fn default() -> &'a str { "" } } + diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index d88551eb855..db389457a1e 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -44,6 +44,8 @@ pub enum Piece<'a> { NextArgument(Argument<'a>), } +impl<'a> Copy for Piece<'a> {} + /// Representation of an argument specification. #[deriving(PartialEq)] pub struct Argument<'a> { @@ -53,6 +55,8 @@ pub struct Argument<'a> { pub format: FormatSpec<'a>, } +impl<'a> Copy for Argument<'a> {} + /// Specification for the formatting of an argument in the format string. #[deriving(PartialEq)] pub struct FormatSpec<'a> { @@ -72,6 +76,8 @@ pub struct FormatSpec<'a> { pub ty: &'a str } +impl<'a> Copy for FormatSpec<'a> {} + /// Enum describing where an argument for a format can be located. #[deriving(PartialEq)] pub enum Position<'a> { @@ -83,6 +89,8 @@ pub enum Position<'a> { ArgumentNamed(&'a str), } +impl<'a> Copy for Position<'a> {} + /// Enum of alignments which are supported. #[deriving(PartialEq)] pub enum Alignment { @@ -96,6 +104,8 @@ pub enum Alignment { AlignUnknown, } +impl Copy for Alignment {} + /// Various flags which can be applied to format strings. The meaning of these /// flags is defined by the formatters themselves. #[deriving(PartialEq)] @@ -112,6 +122,8 @@ pub enum Flag { FlagSignAwareZeroPad, } +impl Copy for Flag {} + /// A count is used for the precision and width parameters of an integer, and /// can reference either an argument or a literal integer. #[deriving(PartialEq)] @@ -128,6 +140,8 @@ pub enum Count<'a> { CountImplied, } +impl<'a> Copy for Count<'a> {} + /// The parser structure for interpreting the input format string. This is /// modelled as an iterator over `Piece` structures to form a stream of tokens /// being output. diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index ffcc0eb22f6..9174f8e8456 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -97,6 +97,9 @@ use self::HasArg::*; use self::Occur::*; use self::Fail::*; use self::Optval::*; +use self::SplitWithinState::*; +use self::Whitespace::*; +use self::LengthLimit::*; use std::fmt; use std::result::Result::{Err, Ok}; @@ -125,6 +128,8 @@ pub enum HasArg { Maybe, } +impl Copy for HasArg {} + /// Describes how often an option may occur. #[deriving(Clone, PartialEq, Eq)] pub enum Occur { @@ -136,6 +141,8 @@ pub enum Occur { Multi, } +impl Copy for Occur {} + /// A description of a possible option. #[deriving(Clone, PartialEq, Eq)] pub struct Opt { @@ -203,6 +210,19 @@ pub enum Fail { UnexpectedArgument(String), } +/// The type of failure that occurred. +#[deriving(PartialEq, Eq)] +#[allow(missing_docs)] +pub enum FailType { + ArgumentMissing_, + UnrecognizedOption_, + OptionMissing_, + OptionDuplicated_, + UnexpectedArgument_, +} + +impl Copy for FailType {} + /// The result of parsing a command line with a set of options. pub type Result = result::Result; @@ -824,14 +844,17 @@ enum SplitWithinState { B, // words C, // internal and trailing whitespace } +impl Copy for SplitWithinState {} enum Whitespace { Ws, // current char is whitespace Cr // current char is not whitespace } +impl Copy for Whitespace {} enum LengthLimit { UnderLim, // current char makes current substring still fit in limit OverLim // current char makes current substring no longer fit in limit } +impl Copy for LengthLimit {} /// Splits a string into substrings with possibly internal whitespace, @@ -847,9 +870,6 @@ enum LengthLimit { /// sequence longer than the limit. fn each_split_within<'a>(ss: &'a str, lim: uint, it: |&'a str| -> bool) -> bool { - use self::SplitWithinState::*; - use self::Whitespace::*; - use self::LengthLimit::*; // Just for fun, let's write this as a state machine: let mut slice_start = 0; diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 18e9d832c00..8825099e36c 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -76,6 +76,7 @@ #![allow(non_upper_case_globals)] #![allow(missing_docs)] #![allow(non_snake_case)] +#![allow(raw_pointer_deriving)] extern crate core; @@ -340,12 +341,15 @@ pub mod types { /// variants, because the compiler complains about the repr attribute /// otherwise. #[repr(u8)] + #[allow(missing_copy_implementations)] pub enum c_void { __variant1, __variant2, } + #[allow(missing_copy_implementations)] pub enum FILE {} + #[allow(missing_copy_implementations)] pub enum fpos_t {} } pub mod c99 { @@ -359,7 +363,9 @@ pub mod types { pub type uint64_t = u64; } pub mod posix88 { + #[allow(missing_copy_implementations)] pub enum DIR {} + #[allow(missing_copy_implementations)] pub enum dirent_t {} } pub mod posix01 {} @@ -380,7 +386,7 @@ pub mod types { pub type pthread_t = c_ulong; #[repr(C)] - pub struct glob_t { + #[deriving(Copy)] pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, @@ -393,18 +399,18 @@ pub mod types { } #[repr(C)] - pub struct timeval { + #[deriving(Copy)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - pub struct timespec { + #[deriving(Copy)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - pub enum timezone {} + #[deriving(Copy)] pub enum timezone {} pub type sighandler_t = size_t; } @@ -417,29 +423,29 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - pub struct sockaddr { + #[deriving(Copy)] pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } #[repr(C)] - pub struct sockaddr_storage { + #[deriving(Copy)] pub struct sockaddr_storage { pub ss_family: sa_family_t, pub __ss_align: i64, pub __ss_pad2: [u8, ..112], } #[repr(C)] - pub struct sockaddr_in { + #[deriving(Copy)] pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8, ..8], } #[repr(C)] - pub struct in_addr { + #[deriving(Copy)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - pub struct sockaddr_in6 { + #[deriving(Copy)] pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, @@ -447,21 +453,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - pub struct in6_addr { + #[deriving(Copy)] pub struct in6_addr { pub s6_addr: [u16, ..8] } #[repr(C)] - pub struct ip_mreq { + #[deriving(Copy)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - pub struct ip6_mreq { + #[deriving(Copy)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - pub struct addrinfo { + #[deriving(Copy)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -483,13 +489,13 @@ pub mod types { pub ai_next: *mut addrinfo, } #[repr(C)] - pub struct sockaddr_un { + #[deriving(Copy)] pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char, ..108] } #[repr(C)] - pub struct ifaddrs { + #[deriving(Copy)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, @@ -572,7 +578,7 @@ pub mod types { pub type blkcnt_t = i32; #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_dev: dev_t, pub __pad1: c_short, pub st_ino: ino_t, @@ -596,13 +602,13 @@ pub mod types { } #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - pub struct pthread_attr_t { + #[deriving(Copy)] pub struct pthread_attr_t { pub __size: [u32, ..9] } } @@ -617,7 +623,7 @@ pub mod types { pub type blkcnt_t = u32; #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_dev: c_ulonglong, pub __pad0: [c_uchar, ..4], pub __st_ino: ino_t, @@ -640,13 +646,13 @@ pub mod types { } #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - pub struct pthread_attr_t { + #[deriving(Copy)] pub struct pthread_attr_t { pub __size: [u32, ..9] } } @@ -662,7 +668,7 @@ pub mod types { pub type blkcnt_t = i32; #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_dev: c_ulong, pub st_pad1: [c_long, ..3], pub st_ino: ino_t, @@ -686,13 +692,13 @@ pub mod types { } #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - pub struct pthread_attr_t { + #[deriving(Copy)] pub struct pthread_attr_t { pub __size: [u32, ..9] } } @@ -701,7 +707,7 @@ pub mod types { pub mod extra { use types::os::arch::c95::{c_ushort, c_int, c_uchar}; #[repr(C)] - pub struct sockaddr_ll { + #[deriving(Copy)] pub struct sockaddr_ll { pub sll_family: c_ushort, pub sll_protocol: c_ushort, pub sll_ifindex: c_int, @@ -764,7 +770,7 @@ pub mod types { pub type blksize_t = i64; pub type blkcnt_t = i64; #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_nlink: nlink_t, @@ -786,13 +792,13 @@ pub mod types { } #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - pub struct pthread_attr_t { + #[deriving(Copy)] pub struct pthread_attr_t { pub __size: [u64, ..7] } } @@ -802,7 +808,7 @@ pub mod types { } pub mod extra { use types::os::arch::c95::{c_ushort, c_int, c_uchar}; - pub struct sockaddr_ll { + #[deriving(Copy)] pub struct sockaddr_ll { pub sll_family: c_ushort, pub sll_protocol: c_ushort, pub sll_ifindex: c_int, @@ -828,7 +834,7 @@ pub mod types { pub type pthread_t = uintptr_t; #[repr(C)] - pub struct glob_t { + #[deriving(Copy)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: size_t, pub gl_offs: size_t, @@ -845,18 +851,18 @@ pub mod types { } #[repr(C)] - pub struct timeval { + #[deriving(Copy)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - pub struct timespec { + #[deriving(Copy)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - pub enum timezone {} + #[deriving(Copy)] pub enum timezone {} pub type sighandler_t = size_t; } @@ -869,13 +875,13 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - pub struct sockaddr { + #[deriving(Copy)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } #[repr(C)] - pub struct sockaddr_storage { + #[deriving(Copy)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, pub __ss_pad1: [u8, ..6], @@ -883,7 +889,7 @@ pub mod types { pub __ss_pad2: [u8, ..112], } #[repr(C)] - pub struct sockaddr_in { + #[deriving(Copy)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, @@ -891,11 +897,11 @@ pub mod types { pub sin_zero: [u8, ..8], } #[repr(C)] - pub struct in_addr { + #[deriving(Copy)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - pub struct sockaddr_in6 { + #[deriving(Copy)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -904,21 +910,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - pub struct in6_addr { + #[deriving(Copy)] pub struct in6_addr { pub s6_addr: [u16, ..8] } #[repr(C)] - pub struct ip_mreq { + #[deriving(Copy)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - pub struct ip6_mreq { + #[deriving(Copy)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - pub struct addrinfo { + #[deriving(Copy)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -929,13 +935,13 @@ pub mod types { pub ai_next: *mut addrinfo, } #[repr(C)] - pub struct sockaddr_un { + #[deriving(Copy)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char, ..104] } #[repr(C)] - pub struct ifaddrs { + #[deriving(Copy)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, @@ -1002,7 +1008,7 @@ pub mod types { pub type blkcnt_t = i64; pub type fflags_t = u32; #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, @@ -1028,7 +1034,7 @@ pub mod types { } #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } @@ -1056,7 +1062,7 @@ pub mod types { pub type pthread_t = uintptr_t; #[repr(C)] - pub struct glob_t { + #[deriving(Copy)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: size_t, pub gl_offs: size_t, @@ -1073,18 +1079,18 @@ pub mod types { } #[repr(C)] - pub struct timeval { + #[deriving(Copy)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - pub struct timespec { + #[deriving(Copy)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - pub enum timezone {} + #[deriving(Copy)] pub enum timezone {} pub type sighandler_t = size_t; } @@ -1096,13 +1102,13 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - pub struct sockaddr { + #[deriving(Copy)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } #[repr(C)] - pub struct sockaddr_storage { + #[deriving(Copy)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, pub __ss_pad1: [u8, ..6], @@ -1110,7 +1116,7 @@ pub mod types { pub __ss_pad2: [u8, ..112], } #[repr(C)] - pub struct sockaddr_in { + #[deriving(Copy)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, @@ -1118,11 +1124,11 @@ pub mod types { pub sin_zero: [u8, ..8], } #[repr(C)] - pub struct in_addr { + #[deriving(Copy)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - pub struct sockaddr_in6 { + #[deriving(Copy)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -1131,21 +1137,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - pub struct in6_addr { + #[deriving(Copy)] pub struct in6_addr { pub s6_addr: [u16, ..8] } #[repr(C)] - pub struct ip_mreq { + #[deriving(Copy)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - pub struct ip6_mreq { + #[deriving(Copy)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - pub struct addrinfo { + #[deriving(Copy)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -1156,7 +1162,7 @@ pub mod types { pub ai_next: *mut addrinfo, } #[repr(C)] - pub struct sockaddr_un { + #[deriving(Copy)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char, ..104] @@ -1219,7 +1225,7 @@ pub mod types { pub type fflags_t = u32; #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_ino: ino_t, pub st_nlink: nlink_t, pub st_dev: dev_t, @@ -1244,7 +1250,7 @@ pub mod types { pub st_qspare2: int64_t, } #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } @@ -1271,7 +1277,7 @@ pub mod types { // pub Note: this is the struct called stat64 in Windows. Not stat, // nor stati64. #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: u16, @@ -1287,24 +1293,24 @@ pub mod types { // note that this is called utimbuf64 in Windows #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time64_t, pub modtime: time64_t, } #[repr(C)] - pub struct timeval { + #[deriving(Copy)] pub struct timeval { pub tv_sec: c_long, pub tv_usec: c_long, } #[repr(C)] - pub struct timespec { + #[deriving(Copy)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - pub enum timezone {} + #[deriving(Copy)] pub enum timezone {} } pub mod bsd44 { @@ -1317,30 +1323,30 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - pub struct sockaddr { + #[deriving(Copy)] pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } #[repr(C)] - pub struct sockaddr_storage { + #[deriving(Copy)] pub struct sockaddr_storage { pub ss_family: sa_family_t, pub __ss_pad1: [u8, ..6], pub __ss_align: i64, pub __ss_pad2: [u8, ..112], } #[repr(C)] - pub struct sockaddr_in { + #[deriving(Copy)] pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8, ..8], } #[repr(C)] - pub struct in_addr { + #[deriving(Copy)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - pub struct sockaddr_in6 { + #[deriving(Copy)] pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, @@ -1348,21 +1354,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - pub struct in6_addr { + #[deriving(Copy)] pub struct in6_addr { pub s6_addr: [u16, ..8] } #[repr(C)] - pub struct ip_mreq { + #[deriving(Copy)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - pub struct ip6_mreq { + #[deriving(Copy)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - pub struct addrinfo { + #[deriving(Copy)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -1373,7 +1379,7 @@ pub mod types { pub ai_next: *mut addrinfo, } #[repr(C)] - pub struct sockaddr_un { + #[deriving(Copy)] pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char, ..108] } @@ -1501,7 +1507,7 @@ pub mod types { pub type LPCH = *mut CHAR; #[repr(C)] - pub struct SECURITY_ATTRIBUTES { + #[deriving(Copy)] pub struct SECURITY_ATTRIBUTES { pub nLength: DWORD, pub lpSecurityDescriptor: LPVOID, pub bInheritHandle: BOOL, @@ -1525,7 +1531,7 @@ pub mod types { pub type int64 = i64; #[repr(C)] - pub struct STARTUPINFO { + #[deriving(Copy)] pub struct STARTUPINFO { pub cb: DWORD, pub lpReserved: LPWSTR, pub lpDesktop: LPWSTR, @@ -1548,7 +1554,7 @@ pub mod types { pub type LPSTARTUPINFO = *mut STARTUPINFO; #[repr(C)] - pub struct PROCESS_INFORMATION { + #[deriving(Copy)] pub struct PROCESS_INFORMATION { pub hProcess: HANDLE, pub hThread: HANDLE, pub dwProcessId: DWORD, @@ -1557,7 +1563,7 @@ pub mod types { pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION; #[repr(C)] - pub struct SYSTEM_INFO { + #[deriving(Copy)] pub struct SYSTEM_INFO { pub wProcessorArchitecture: WORD, pub wReserved: WORD, pub dwPageSize: DWORD, @@ -1573,7 +1579,7 @@ pub mod types { pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; #[repr(C)] - pub struct MEMORY_BASIC_INFORMATION { + #[deriving(Copy)] pub struct MEMORY_BASIC_INFORMATION { pub BaseAddress: LPVOID, pub AllocationBase: LPVOID, pub AllocationProtect: DWORD, @@ -1585,7 +1591,7 @@ pub mod types { pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION; #[repr(C)] - pub struct OVERLAPPED { + #[deriving(Copy)] pub struct OVERLAPPED { pub Internal: *mut c_ulong, pub InternalHigh: *mut c_ulong, pub Offset: DWORD, @@ -1596,7 +1602,7 @@ pub mod types { pub type LPOVERLAPPED = *mut OVERLAPPED; #[repr(C)] - pub struct FILETIME { + #[deriving(Copy)] pub struct FILETIME { pub dwLowDateTime: DWORD, pub dwHighDateTime: DWORD, } @@ -1604,7 +1610,7 @@ pub mod types { pub type LPFILETIME = *mut FILETIME; #[repr(C)] - pub struct GUID { + #[deriving(Copy)] pub struct GUID { pub Data1: DWORD, pub Data2: WORD, pub Data3: WORD, @@ -1612,7 +1618,7 @@ pub mod types { } #[repr(C)] - pub struct WSAPROTOCOLCHAIN { + #[deriving(Copy)] pub struct WSAPROTOCOLCHAIN { pub ChainLen: c_int, pub ChainEntries: [DWORD, ..MAX_PROTOCOL_CHAIN as uint], } @@ -1620,7 +1626,7 @@ pub mod types { pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN; #[repr(C)] - pub struct WSAPROTOCOL_INFO { + #[deriving(Copy)] pub struct WSAPROTOCOL_INFO { pub dwServiceFlags1: DWORD, pub dwServiceFlags2: DWORD, pub dwServiceFlags3: DWORD, @@ -1648,7 +1654,7 @@ pub mod types { pub type GROUP = c_uint; #[repr(C)] - pub struct WIN32_FIND_DATAW { + #[deriving(Copy)] pub struct WIN32_FIND_DATAW { pub dwFileAttributes: DWORD, pub ftCreationTime: FILETIME, pub ftLastAccessTime: FILETIME, @@ -1671,14 +1677,14 @@ pub mod types { pub mod common { pub mod posix01 { use types::common::c95::c_void; - use types::os::arch::c95::{c_char, c_int, size_t, - time_t, suseconds_t, c_long}; + use types::os::arch::c95::{c_char, c_int, size_t, time_t}; + use types::os::arch::c95::{suseconds_t, c_long}; use types::os::arch::c99::{uintptr_t}; pub type pthread_t = uintptr_t; #[repr(C)] - pub struct glob_t { + #[deriving(Copy)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: c_int, pub gl_offs: size_t, @@ -1695,18 +1701,18 @@ pub mod types { } #[repr(C)] - pub struct timeval { + #[deriving(Copy)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - pub struct timespec { + #[deriving(Copy)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - pub enum timezone {} + #[deriving(Copy)] pub enum timezone {} pub type sighandler_t = size_t; } @@ -1720,33 +1726,37 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - pub struct sockaddr { + #[deriving(Copy)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } + #[repr(C)] - pub struct sockaddr_storage { + #[deriving(Copy)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, pub __ss_pad1: [u8, ..6], pub __ss_align: i64, pub __ss_pad2: [u8, ..112], } + #[repr(C)] - pub struct sockaddr_in { + #[deriving(Copy)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8, ..8], } + #[repr(C)] - pub struct in_addr { + #[deriving(Copy)] pub struct in_addr { pub s_addr: in_addr_t, } + #[repr(C)] - pub struct sockaddr_in6 { + #[deriving(Copy)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -1754,22 +1764,26 @@ pub mod types { pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } + #[repr(C)] - pub struct in6_addr { + #[deriving(Copy)] pub struct in6_addr { pub s6_addr: [u16, ..8] } + #[repr(C)] - pub struct ip_mreq { + #[deriving(Copy)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } + #[repr(C)] - pub struct ip6_mreq { + #[deriving(Copy)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } + #[repr(C)] - pub struct addrinfo { + #[deriving(Copy)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -1779,14 +1793,16 @@ pub mod types { pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } + #[repr(C)] - pub struct sockaddr_un { + #[deriving(Copy)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char, ..104] } + #[repr(C)] - pub struct ifaddrs { + #[deriving(Copy)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, @@ -1849,7 +1865,7 @@ pub mod types { pub type blkcnt_t = i32; #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_dev: dev_t, pub st_mode: mode_t, pub st_nlink: nlink_t, @@ -1875,13 +1891,13 @@ pub mod types { } #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - pub struct pthread_attr_t { + #[deriving(Copy)] pub struct pthread_attr_t { pub __sig: c_long, pub __opaque: [c_char, ..36] } @@ -1892,7 +1908,7 @@ pub mod types { } pub mod extra { #[repr(C)] - pub struct mach_timebase_info { + #[deriving(Copy)] pub struct mach_timebase_info { pub numer: u32, pub denom: u32, } @@ -1953,7 +1969,7 @@ pub mod types { pub type blkcnt_t = i32; #[repr(C)] - pub struct stat { + #[deriving(Copy)] pub struct stat { pub st_dev: dev_t, pub st_mode: mode_t, pub st_nlink: nlink_t, @@ -1979,13 +1995,13 @@ pub mod types { } #[repr(C)] - pub struct utimbuf { + #[deriving(Copy)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - pub struct pthread_attr_t { + #[deriving(Copy)] pub struct pthread_attr_t { pub __sig: c_long, pub __opaque: [c_char, ..56] } @@ -1996,7 +2012,7 @@ pub mod types { } pub mod extra { #[repr(C)] - pub struct mach_timebase_info { + #[deriving(Copy)] pub struct mach_timebase_info { pub numer: u32, pub denom: u32, } @@ -4990,3 +5006,9 @@ pub mod funcs { pub fn issue_14344_workaround() {} // FIXME #14344 force linkage to happen correctly #[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows + +#[doc(hidden)] +#[cfg(not(test))] +mod std { + pub use core::kinds; +} diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 5642ec91ba3..8b79078eac6 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -234,6 +234,8 @@ struct DefaultLogger { #[deriving(PartialEq, PartialOrd)] pub struct LogLevel(pub u32); +impl Copy for LogLevel {} + impl fmt::Show for LogLevel { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let LogLevel(level) = *self; @@ -344,6 +346,8 @@ pub struct LogLocation { pub line: uint, } +impl Copy for LogLocation {} + /// Tests whether a given module's name is enabled for a particular level of /// logging. This is the second layer of defense about determining whether a /// module's log statement should be emitted or not. diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 2693f183644..83a410674ee 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -35,6 +35,8 @@ pub struct ChaChaRng { index: uint, // Index into state } +impl Copy for ChaChaRng {} + static EMPTY: ChaChaRng = ChaChaRng { buffer: [0, ..STATE_WORDS], state: [0, ..STATE_WORDS], diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs index d874f1deed3..9a9f31e9339 100644 --- a/src/librand/distributions/exponential.rs +++ b/src/librand/distributions/exponential.rs @@ -10,6 +10,7 @@ //! The exponential distribution. +use core::kinds::Copy; use core::num::Float; use {Rng, Rand}; @@ -31,6 +32,8 @@ use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; /// College, Oxford pub struct Exp1(pub f64); +impl Copy for Exp1 {} + // This could be done via `-rng.gen::().ln()` but that is slower. impl Rand for Exp1 { #[inline] @@ -71,6 +74,8 @@ pub struct Exp { lambda_inverse: f64 } +impl Copy for Exp {} + impl Exp { /// Construct a new `Exp` with the given shape parameter /// `lambda`. Panics if `lambda <= 0`. diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index b3dc20819bc..f5261f1db82 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -10,6 +10,7 @@ //! The normal and derived distributions. +use core::kinds::Copy; use core::num::Float; use {Rng, Rand, Open01}; @@ -30,6 +31,8 @@ use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; /// College, Oxford pub struct StandardNormal(pub f64); +impl Copy for StandardNormal {} + impl Rand for StandardNormal { fn rand(rng: &mut R) -> StandardNormal { #[inline] @@ -88,6 +91,8 @@ pub struct Normal { std_dev: f64, } +impl Copy for Normal {} + impl Normal { /// Construct a new `Normal` distribution with the given mean and /// standard deviation. @@ -134,6 +139,8 @@ pub struct LogNormal { norm: Normal } +impl Copy for LogNormal {} + impl LogNormal { /// Construct a new `LogNormal` distribution with the given mean /// and standard deviation. diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 517b50c49c7..2c1853b1951 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -37,6 +37,9 @@ pub struct IsaacRng { b: u32, c: u32 } + +impl Copy for IsaacRng {} + static EMPTY: IsaacRng = IsaacRng { cnt: 0, rsl: [0, ..RAND_SIZE_UINT], @@ -271,6 +274,8 @@ pub struct Isaac64Rng { c: u64, } +impl Copy for Isaac64Rng {} + static EMPTY_64: Isaac64Rng = Isaac64Rng { cnt: 0, rsl: [0, .. RAND_SIZE_64], diff --git a/src/librand/lib.rs b/src/librand/lib.rs index de40ee4893d..d357f247f1b 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -377,6 +377,7 @@ pub trait SeedableRng: Rng { /// [1]: Marsaglia, George (July 2003). ["Xorshift /// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of /// Statistical Software*. Vol. 8 (Issue 14). +#[allow(missing_copy_implementations)] pub struct XorShiftRng { x: u32, y: u32, @@ -384,6 +385,17 @@ pub struct XorShiftRng { w: u32, } +impl Clone for XorShiftRng { + fn clone(&self) -> XorShiftRng { + XorShiftRng { + x: self.x, + y: self.y, + z: self.z, + w: self.w, + } + } +} + impl XorShiftRng { /// Creates a new XorShiftRng instance which is not seeded. /// diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index 64c6b1739eb..88c870579e6 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -135,6 +135,8 @@ pub trait Reseeder { /// replacing the RNG with the result of a `Default::default` call. pub struct ReseedWithDefault; +impl Copy for ReseedWithDefault {} + impl Reseeder for ReseedWithDefault { fn reseed(&mut self, rng: &mut R) { *rng = Default::default(); diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index f65c4f4e3ed..426a987d25d 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -47,6 +47,8 @@ pub struct Doc<'a> { pub end: uint, } +impl<'doc> Copy for Doc<'doc> {} + impl<'doc> Doc<'doc> { pub fn new(data: &'doc [u8]) -> Doc<'doc> { Doc { data: data, start: 0u, end: data.len() } @@ -104,6 +106,8 @@ pub enum EbmlEncoderTag { EsLabel, // Used only when debugging } +impl Copy for EbmlEncoderTag {} + #[deriving(Show)] pub enum Error { IntTooBig(uint), @@ -151,6 +155,8 @@ pub mod reader { pub next: uint } + impl Copy for Res {} + #[inline(never)] fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult { let a = data[start]; diff --git a/src/libregex/parse.rs b/src/libregex/parse.rs index 5cd833e2797..55e533aadee 100644 --- a/src/libregex/parse.rs +++ b/src/libregex/parse.rs @@ -83,6 +83,8 @@ pub enum Greed { Ungreedy, } +impl Copy for Greed {} + impl Greed { pub fn is_greedy(&self) -> bool { match *self { diff --git a/src/libregex/re.rs b/src/libregex/re.rs index 58ce72a3173..2a1fda06431 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -135,8 +135,12 @@ pub struct ExNative { pub prog: fn(MatchKind, &str, uint, uint) -> Vec> } +impl Copy for ExNative {} + impl Clone for ExNative { - fn clone(&self) -> ExNative { *self } + fn clone(&self) -> ExNative { + *self + } } impl fmt::Show for Regex { @@ -917,7 +921,7 @@ fn exec_slice(re: &Regex, which: MatchKind, input: &str, s: uint, e: uint) -> CaptureLocs { match *re { Dynamic(ExDynamic { ref prog, .. }) => vm::run(which, prog, input, s, e), - Native(ExNative { prog, .. }) => prog(which, input, s, e), + Native(ExNative { ref prog, .. }) => (*prog)(which, input, s, e), } } diff --git a/src/libregex/vm.rs b/src/libregex/vm.rs index 4315c0f7b40..44cf2249b8e 100644 --- a/src/libregex/vm.rs +++ b/src/libregex/vm.rs @@ -60,6 +60,8 @@ pub enum MatchKind { Submatches, } +impl Copy for MatchKind {} + /// Runs an NFA simulation on the compiled expression given on the search text /// `input`. The search begins at byte index `start` and ends at byte index /// `end`. (The range is specified here so that zero-width assertions will work @@ -107,6 +109,8 @@ pub enum StepState { StepContinue, } +impl Copy for StepState {} + impl<'r, 't> Nfa<'r, 't> { fn run(&mut self) -> CaptureLocs { let ncaps = match self.which { diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index c474820c3c9..e19fa01b2e4 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -28,6 +28,7 @@ use self::MethodContext::*; use metadata::csearch; use middle::def::*; +use middle::subst::Substs; use middle::ty::{mod, Ty}; use middle::{def, pat_util, stability}; use middle::const_eval::{eval_const_expr_partial, const_int, const_uint}; @@ -40,11 +41,12 @@ use std::collections::hash_map::{Occupied, Vacant}; use std::num::SignedInt; use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; use syntax::{abi, ast, ast_map}; -use syntax::ast_util::{mod, is_shift_binop}; +use syntax::ast_util::is_shift_binop; use syntax::attr::{mod, AttrMetaMethods}; use syntax::codemap::{Span, DUMMY_SP}; use syntax::parse::token; use syntax::ast::{TyI, TyU, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; +use syntax::ast_util; use syntax::ptr::P; use syntax::visit::{mod, Visitor}; @@ -53,6 +55,8 @@ declare_lint!(WHILE_TRUE, Warn, pub struct WhileTrue; +impl Copy for WhileTrue {} + impl LintPass for WhileTrue { fn get_lints(&self) -> LintArray { lint_array!(WHILE_TRUE) @@ -75,6 +79,8 @@ declare_lint!(UNUSED_TYPECASTS, Allow, pub struct UnusedCasts; +impl Copy for UnusedCasts {} + impl LintPass for UnusedCasts { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_TYPECASTS) @@ -107,6 +113,8 @@ pub struct TypeLimits { negated_expr_id: ast::NodeId, } +impl Copy for TypeLimits {} + impl TypeLimits { pub fn new() -> TypeLimits { TypeLimits { @@ -415,6 +423,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> { pub struct ImproperCTypes; +impl Copy for ImproperCTypes {} + impl LintPass for ImproperCTypes { fn get_lints(&self) -> LintArray { lint_array!(IMPROPER_CTYPES) @@ -454,6 +464,8 @@ declare_lint!(BOX_POINTERS, Allow, pub struct BoxPointers; +impl Copy for BoxPointers {} + impl BoxPointers { fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>, span: Span, ty: Ty<'tcx>) { @@ -587,6 +599,8 @@ declare_lint!(UNUSED_ATTRIBUTES, Warn, pub struct UnusedAttributes; +impl Copy for UnusedAttributes {} + impl LintPass for UnusedAttributes { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_ATTRIBUTES) @@ -666,6 +680,8 @@ declare_lint!(pub PATH_STATEMENTS, Warn, pub struct PathStatements; +impl Copy for PathStatements {} + impl LintPass for PathStatements { fn get_lints(&self) -> LintArray { lint_array!(PATH_STATEMENTS) @@ -693,6 +709,8 @@ declare_lint!(pub UNUSED_RESULTS, Allow, pub struct UnusedResults; +impl Copy for UnusedResults {} + impl LintPass for UnusedResults { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS) @@ -757,6 +775,8 @@ declare_lint!(pub NON_CAMEL_CASE_TYPES, Warn, pub struct NonCamelCaseTypes; +impl Copy for NonCamelCaseTypes {} + impl NonCamelCaseTypes { fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { fn is_camel_case(ident: ast::Ident) -> bool { @@ -876,6 +896,8 @@ declare_lint!(pub NON_SNAKE_CASE, Warn, pub struct NonSnakeCase; +impl Copy for NonSnakeCase {} + impl NonSnakeCase { fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { fn is_snake_case(ident: ast::Ident) -> bool { @@ -985,6 +1007,8 @@ declare_lint!(pub NON_UPPER_CASE_GLOBALS, Warn, pub struct NonUpperCaseGlobals; +impl Copy for NonUpperCaseGlobals {} + impl LintPass for NonUpperCaseGlobals { fn get_lints(&self) -> LintArray { lint_array!(NON_UPPER_CASE_GLOBALS) @@ -1034,6 +1058,8 @@ declare_lint!(UNUSED_PARENS, Warn, pub struct UnusedParens; +impl Copy for UnusedParens {} + impl UnusedParens { fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str, struct_lit_needs_parens: bool) { @@ -1124,6 +1150,8 @@ declare_lint!(UNUSED_IMPORT_BRACES, Allow, pub struct UnusedImportBraces; +impl Copy for UnusedImportBraces {} + impl LintPass for UnusedImportBraces { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_IMPORT_BRACES) @@ -1159,6 +1187,8 @@ declare_lint!(NON_SHORTHAND_FIELD_PATTERNS, Warn, pub struct NonShorthandFieldPatterns; +impl Copy for NonShorthandFieldPatterns {} + impl LintPass for NonShorthandFieldPatterns { fn get_lints(&self) -> LintArray { lint_array!(NON_SHORTHAND_FIELD_PATTERNS) @@ -1188,6 +1218,8 @@ declare_lint!(pub UNUSED_UNSAFE, Warn, pub struct UnusedUnsafe; +impl Copy for UnusedUnsafe {} + impl LintPass for UnusedUnsafe { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_UNSAFE) @@ -1209,6 +1241,8 @@ declare_lint!(UNSAFE_BLOCKS, Allow, pub struct UnsafeBlocks; +impl Copy for UnsafeBlocks {} + impl LintPass for UnsafeBlocks { fn get_lints(&self) -> LintArray { lint_array!(UNSAFE_BLOCKS) @@ -1229,6 +1263,8 @@ declare_lint!(pub UNUSED_MUT, Warn, pub struct UnusedMut; +impl Copy for UnusedMut {} + impl UnusedMut { fn check_unused_mut_pat(&self, cx: &Context, pats: &[P]) { // collect all mutable pattern and group their NodeIDs by their Identifier to @@ -1294,6 +1330,8 @@ declare_lint!(UNUSED_ALLOCATION, Warn, pub struct UnusedAllocation; +impl Copy for UnusedAllocation {} + impl LintPass for UnusedAllocation { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_ALLOCATION) @@ -1479,6 +1517,61 @@ impl LintPass for MissingDoc { } } +pub struct MissingCopyImplementations; + +impl Copy for MissingCopyImplementations {} + +impl LintPass for MissingCopyImplementations { + fn get_lints(&self) -> LintArray { + lint_array!(MISSING_COPY_IMPLEMENTATIONS) + } + + fn check_item(&mut self, cx: &Context, item: &ast::Item) { + if !cx.exported_items.contains(&item.id) { + return + } + if cx.tcx + .destructor_for_type + .borrow() + .contains_key(&ast_util::local_def(item.id)) { + return + } + let ty = match item.node { + ast::ItemStruct(_, ref ast_generics) => { + if ast_generics.is_parameterized() { + return + } + ty::mk_struct(cx.tcx, + ast_util::local_def(item.id), + Substs::empty()) + } + ast::ItemEnum(_, ref ast_generics) => { + if ast_generics.is_parameterized() { + return + } + ty::mk_enum(cx.tcx, + ast_util::local_def(item.id), + Substs::empty()) + } + _ => return, + }; + let parameter_environment = ty::empty_parameter_environment(); + if !ty::type_moves_by_default(cx.tcx, + ty, + ¶meter_environment) { + return + } + if ty::can_type_implement_copy(cx.tcx, + ty, + ¶meter_environment).is_ok() { + cx.span_lint(MISSING_COPY_IMPLEMENTATIONS, + item.span, + "type could implement `Copy`; consider adding `impl \ + Copy`") + } + } +} + declare_lint!(DEPRECATED, Warn, "detects use of #[deprecated] items") @@ -1493,6 +1586,8 @@ declare_lint!(UNSTABLE, Allow, /// `#[unstable]` attributes, or no stability attribute. pub struct Stability; +impl Copy for Stability {} + impl Stability { fn lint(&self, cx: &Context, id: ast::DefId, span: Span) { let stability = stability::lookup(cx.tcx, id); @@ -1682,10 +1777,15 @@ declare_lint!(pub VARIANT_SIZE_DIFFERENCES, Allow, declare_lint!(pub FAT_PTR_TRANSMUTES, Allow, "detects transmutes of fat pointers") +declare_lint!(pub MISSING_COPY_IMPLEMENTATIONS, Warn, + "detects potentially-forgotten implementations of `Copy`") + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. pub struct HardwiredLints; +impl Copy for HardwiredLints {} + impl LintPass for HardwiredLints { fn get_lints(&self) -> LintArray { lint_array!( diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 442d3aab92d..153a00e5617 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -204,6 +204,7 @@ impl LintStore { UnusedMut, UnusedAllocation, Stability, + MissingCopyImplementations, ) add_builtin_with_new!(sess, diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index d6b83752cc5..4b4ba2ab94c 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -64,6 +64,8 @@ pub struct Lint { pub desc: &'static str, } +impl Copy for Lint {} + impl Lint { /// Get the lint's name, with ASCII letters converted to lowercase. pub fn name_lower(&self) -> String { @@ -179,6 +181,8 @@ pub struct LintId { lint: &'static Lint, } +impl Copy for LintId {} + impl PartialEq for LintId { fn eq(&self, other: &LintId) -> bool { (self.lint as *const Lint) == (other.lint as *const Lint) @@ -214,6 +218,8 @@ pub enum Level { Allow, Warn, Deny, Forbid } +impl Copy for Level {} + impl Level { /// Convert a level to a lower-case string. pub fn as_str(self) -> &'static str { @@ -251,6 +257,8 @@ pub enum LintSource { CommandLine, } +impl Copy for LintSource {} + pub type LevelSource = (Level, LintSource); pub mod builtin; diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 0da3b1b7a4e..315e0eea9b7 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -144,6 +144,8 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f tag_table_capture_modes = 0x56, tag_table_object_cast_map = 0x57, } + +impl Copy for astencode_tag {} static first_astencode_tag: uint = tag_ast as uint; static last_astencode_tag: uint = tag_table_object_cast_map as uint; impl astencode_tag { diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index deeab18de7c..9e87153e64a 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -275,8 +275,10 @@ fn visit_item(e: &Env, i: &ast::Item) { } } -fn register_native_lib(sess: &Session, span: Option, name: String, - kind: cstore::NativeLibaryKind) { +fn register_native_lib(sess: &Session, + span: Option, + name: String, + kind: cstore::NativeLibraryKind) { if name.is_empty() { match span { Some(span) => { diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index ebf5cca6a31..b864dc39603 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -40,6 +40,8 @@ pub struct MethodInfo { pub vis: ast::Visibility, } +impl Copy for MethodInfo {} + pub fn get_symbol(cstore: &cstore::CStore, def: ast::DefId) -> String { let cdata = cstore.get_crate_data(def.krate); decoder::get_symbol(cdata.data(), def.node) @@ -273,9 +275,8 @@ pub fn get_impl_vtables<'tcx>(tcx: &ty::ctxt<'tcx>, decoder::get_impl_vtables(&*cdata, def.node, tcx) } -pub fn get_native_libraries(cstore: &cstore::CStore, - crate_num: ast::CrateNum) - -> Vec<(cstore::NativeLibaryKind, String)> { +pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum) + -> Vec<(cstore::NativeLibraryKind, String)> { let cdata = cstore.get_crate_data(crate_num); decoder::get_native_libraries(&*cdata) } diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index f93a1699e18..91f360a7a38 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -15,7 +15,7 @@ pub use self::MetadataBlob::*; pub use self::LinkagePreference::*; -pub use self::NativeLibaryKind::*; +pub use self::NativeLibraryKind::*; use back::svh::Svh; use metadata::decoder; @@ -54,13 +54,17 @@ pub enum LinkagePreference { RequireStatic, } -#[deriving(PartialEq, FromPrimitive, Clone)] -pub enum NativeLibaryKind { +impl Copy for LinkagePreference {} + +#[deriving(Clone, PartialEq, FromPrimitive)] +pub enum NativeLibraryKind { NativeStatic, // native static library (.a archive) NativeFramework, // OSX-specific NativeUnknown, // default way to specify a dynamic library } +impl Copy for NativeLibraryKind {} + // Where a crate came from on the local filesystem. One of these two options // must be non-None. #[deriving(PartialEq, Clone)] @@ -75,7 +79,7 @@ pub struct CStore { /// Map from NodeId's of local extern crate statements to crate numbers extern_mod_crate_map: RefCell>, used_crate_sources: RefCell>, - used_libraries: RefCell>, + used_libraries: RefCell>, used_link_args: RefCell>, pub intr: Rc, } @@ -186,13 +190,14 @@ impl CStore { libs } - pub fn add_used_library(&self, lib: String, kind: NativeLibaryKind) { + pub fn add_used_library(&self, lib: String, kind: NativeLibraryKind) { assert!(!lib.is_empty()); self.used_libraries.borrow_mut().push((lib, kind)); } pub fn get_used_libraries<'a>(&'a self) - -> &'a RefCell > { + -> &'a RefCell> { &self.used_libraries } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index f352a28df69..0d51e044de9 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -442,6 +442,8 @@ pub enum DefLike { DlField } +impl Copy for DefLike {} + /// Iterates over the language items in the given crate. pub fn each_lang_item(cdata: Cmd, f: |ast::NodeId, uint| -> bool) -> bool { let root = rbml::Doc::new(cdata.data()); @@ -1267,14 +1269,14 @@ pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) pub fn get_native_libraries(cdata: Cmd) - -> Vec<(cstore::NativeLibaryKind, String)> { + -> Vec<(cstore::NativeLibraryKind, String)> { let libraries = reader::get_doc(rbml::Doc::new(cdata.data()), tag_native_libraries); let mut result = Vec::new(); reader::tagged_docs(libraries, tag_native_libraries_lib, |lib_doc| { let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind); let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name); - let kind: cstore::NativeLibaryKind = + let kind: cstore::NativeLibraryKind = FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap(); let name = name_doc.as_str().to_string(); result.push((kind, name)); diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 63fc2af492c..2d23a61813a 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -20,7 +20,12 @@ use std::os; use util::fs as myfs; -pub enum FileMatch { FileMatches, FileDoesntMatch } +pub enum FileMatch { + FileMatches, + FileDoesntMatch, +} + +impl Copy for FileMatch {} // A module for searching for libraries // FIXME (#2658): I'm not happy how this module turned out. Should diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 00d12ad6a38..e29741fb4a1 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -61,6 +61,8 @@ pub enum DefIdSource { // Identifies an unboxed closure UnboxedClosureSource } + +impl Copy for DefIdSource {} pub type conv_did<'a> = |source: DefIdSource, ast::DefId|: 'a -> ast::DefId; diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 72c6256dcb5..5f030324d42 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -24,7 +24,9 @@ use middle::borrowck::LoanPathKind::*; use middle::expr_use_visitor as euv; use middle::mem_categorization as mc; use middle::region; +use middle::ty::ParameterEnvironment; use middle::ty; +use syntax::ast::NodeId; use syntax::ast; use syntax::codemap::Span; use util::ppaux::Repr; @@ -89,6 +91,7 @@ struct CheckLoanCtxt<'a, 'tcx: 'a> { dfcx_loans: &'a LoanDataFlow<'a, 'tcx>, move_data: move_data::FlowedMoveData<'a, 'tcx>, all_loans: &'a [Loan<'tcx>], + param_env: &'a ParameterEnvironment<'tcx>, } impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { @@ -193,19 +196,25 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, dfcx_loans: &LoanDataFlow<'b, 'tcx>, move_data: move_data::FlowedMoveData<'c, 'tcx>, all_loans: &[Loan<'tcx>], + fn_id: NodeId, decl: &ast::FnDecl, body: &ast::Block) { debug!("check_loans(body id={})", body.id); + let param_env = ParameterEnvironment::for_item(bccx.tcx, fn_id); + let mut clcx = CheckLoanCtxt { bccx: bccx, dfcx_loans: dfcx_loans, move_data: move_data, all_loans: all_loans, + param_env: ¶m_env, }; { - let mut euv = euv::ExprUseVisitor::new(&mut clcx, bccx.tcx); + let mut euv = euv::ExprUseVisitor::new(&mut clcx, + bccx.tcx, + param_env.clone()); euv.walk_fn(decl, body); } } @@ -700,7 +709,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { use_kind, &**lp, the_move, - moved_lp); + moved_lp, + self.param_env); false }); } diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index edffe59fff5..ca9d4b512b3 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -22,6 +22,7 @@ use middle::borrowck::move_data::MoveData; use middle::expr_use_visitor as euv; use middle::mem_categorization as mc; use middle::region; +use middle::ty::ParameterEnvironment; use middle::ty; use util::ppaux::{Repr}; @@ -37,10 +38,11 @@ mod gather_moves; mod move_error; pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, + fn_id: NodeId, decl: &ast::FnDecl, body: &ast::Block) - -> (Vec>, move_data::MoveData<'tcx>) -{ + -> (Vec>, + move_data::MoveData<'tcx>) { let mut glcx = GatherLoanCtxt { bccx: bccx, all_loans: Vec::new(), @@ -49,8 +51,12 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_error_collector: move_error::MoveErrorCollector::new(), }; + let param_env = ParameterEnvironment::for_item(bccx.tcx, fn_id); + { - let mut euv = euv::ExprUseVisitor::new(&mut glcx, bccx.tcx); + let mut euv = euv::ExprUseVisitor::new(&mut glcx, + bccx.tcx, + param_env); euv.walk_fn(decl, body); } diff --git a/src/librustc/middle/borrowck/graphviz.rs b/src/librustc/middle/borrowck/graphviz.rs index a209b1a28f2..32fa5f8c3a9 100644 --- a/src/librustc/middle/borrowck/graphviz.rs +++ b/src/librustc/middle/borrowck/graphviz.rs @@ -34,6 +34,8 @@ pub enum Variant { Assigns, } +impl Copy for Variant {} + impl Variant { pub fn short_name(&self) -> &'static str { match *self { diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 0bbcdfe61bb..e90de1b6912 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -25,7 +25,7 @@ use middle::dataflow::DataFlowOperator; use middle::expr_use_visitor as euv; use middle::mem_categorization as mc; use middle::region; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, ParameterEnvironment, Ty}; use util::ppaux::{note_and_explain_region, Repr, UserString}; use std::rc::Rc; @@ -62,6 +62,8 @@ pub mod move_data; #[deriving(Clone)] pub struct LoanDataFlowOperator; +impl Copy for LoanDataFlowOperator {} + pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>; impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> { @@ -146,8 +148,13 @@ fn borrowck_fn(this: &mut BorrowckCtxt, move_data::fragments::instrument_move_fragments(&flowed_moves.move_data, this.tcx, sp, id); - check_loans::check_loans(this, &loan_dfcx, flowed_moves, - all_loans.as_slice(), decl, body); + check_loans::check_loans(this, + &loan_dfcx, + flowed_moves, + all_loans.as_slice(), + id, + decl, + body); visit::walk_fn(this, fk, decl, body, sp); } @@ -162,7 +169,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, // Check the body of fn items. let id_range = ast_util::compute_id_range_for_fn_body(fk, decl, body, sp, id); let (all_loans, move_data) = - gather_loans::gather_loans_in_fn(this, decl, body); + gather_loans::gather_loans_in_fn(this, id, decl, body); let mut loan_dfcx = DataFlowContext::new(this.tcx, @@ -339,6 +346,8 @@ pub enum LoanPathElem { LpInterior(mc::InteriorKind) // `LV.f` in doc.rs } +impl Copy for LoanPathElem {} + pub fn closure_to_block(closure_id: ast::NodeId, tcx: &ty::ctxt) -> ast::NodeId { match tcx.map.get(closure_id) { @@ -484,6 +493,7 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option>> { // Errors that can occur #[deriving(PartialEq)] +#[allow(missing_copy_implementations)] pub enum bckerr_code { err_mutbl, err_out_of_scope(ty::Region, ty::Region), // superscope, subscope @@ -505,12 +515,16 @@ pub enum AliasableViolationKind { BorrowViolation(euv::LoanCause) } +impl Copy for AliasableViolationKind {} + #[deriving(Show)] pub enum MovedValueUseKind { MovedInUse, MovedInCapture, } +impl Copy for MovedValueUseKind {} + /////////////////////////////////////////////////////////////////////////// // Misc @@ -545,7 +559,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { use_kind: MovedValueUseKind, lp: &LoanPath<'tcx>, the_move: &move_data::Move, - moved_lp: &LoanPath<'tcx>) { + moved_lp: &LoanPath<'tcx>, + param_env: &ParameterEnvironment<'tcx>) { let verb = match use_kind { MovedInUse => "use", MovedInCapture => "capture", @@ -621,7 +636,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { r).as_slice()) } }; - let (suggestion, _) = move_suggestion(self.tcx, expr_ty, + let (suggestion, _) = move_suggestion(self.tcx, param_env, expr_ty, ("moved by default", "")); self.tcx.sess.span_note( expr_span, @@ -659,7 +674,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { r).as_slice()) } }; - let (suggestion, help) = move_suggestion(self.tcx, expr_ty, + let (suggestion, help) = move_suggestion(self.tcx, + param_env, + expr_ty, ("moved by default", "make a copy and \ capture that instead to override")); self.tcx.sess.span_note( @@ -674,7 +691,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } } - fn move_suggestion<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, + fn move_suggestion<'tcx>(tcx: &ty::ctxt<'tcx>, + param_env: &ty::ParameterEnvironment<'tcx>, + ty: Ty<'tcx>, default_msgs: (&'static str, &'static str)) -> (&'static str, &'static str) { match ty.sty { @@ -684,7 +703,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { }) => ("a non-copyable stack closure", "capture it in a new closure, e.g. `|x| f(x)`, to override"), - _ if ty::type_moves_by_default(tcx, ty) => + _ if ty::type_moves_by_default(tcx, ty, param_env) => ("non-copyable", "perhaps you meant to use `clone()`?"), _ => default_msgs, diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index 7bf3458f0ae..3bb6145c5ca 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -81,6 +81,8 @@ pub struct FlowedMoveData<'a, 'tcx: 'a> { #[deriving(PartialEq, Eq, PartialOrd, Ord, Show)] pub struct MovePathIndex(uint); +impl Copy for MovePathIndex {} + impl MovePathIndex { fn get(&self) -> uint { let MovePathIndex(v) = *self; v @@ -101,6 +103,8 @@ static InvalidMovePathIndex: MovePathIndex = #[deriving(PartialEq)] pub struct MoveIndex(uint); +impl Copy for MoveIndex {} + impl MoveIndex { fn get(&self) -> uint { let MoveIndex(v) = *self; v @@ -138,6 +142,8 @@ pub enum MoveKind { Captured // Closure creation that moves a value } +impl Copy for MoveKind {} + pub struct Move { /// Path being moved. pub path: MovePathIndex, @@ -152,6 +158,8 @@ pub struct Move { pub next_move: MoveIndex } +impl Copy for Move {} + pub struct Assignment { /// Path being assigned. pub path: MovePathIndex, @@ -163,6 +171,8 @@ pub struct Assignment { pub span: Span, } +impl Copy for Assignment {} + pub struct VariantMatch { /// downcast to the variant. pub path: MovePathIndex, @@ -177,14 +187,20 @@ pub struct VariantMatch { pub mode: euv::MatchMode } +impl Copy for VariantMatch {} + #[deriving(Clone)] pub struct MoveDataFlowOperator; +impl Copy for MoveDataFlowOperator {} + pub type MoveDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, MoveDataFlowOperator>; #[deriving(Clone)] pub struct AssignDataFlowOperator; +impl Copy for AssignDataFlowOperator {} + pub type AssignDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, AssignDataFlowOperator>; fn loan_path_is_precise(loan_path: &LoanPath) -> bool { diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 90919609e2e..0dcb78f6bb0 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -32,6 +32,8 @@ struct LoopScope { break_index: CFGIndex, // where to go on a `break } +impl Copy for LoopScope {} + pub fn construct(tcx: &ty::ctxt, blk: &ast::Block) -> CFG { let mut graph = graph::Graph::new(); diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs index a2e8ba8d65c..bc512a73a4b 100644 --- a/src/librustc/middle/cfg/mod.rs +++ b/src/librustc/middle/cfg/mod.rs @@ -30,6 +30,8 @@ pub struct CFGNodeData { pub id: ast::NodeId } +impl Copy for CFGNodeData {} + pub struct CFGEdgeData { pub exiting_scopes: Vec } diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index 36742df9850..eb073e07b02 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -21,11 +21,15 @@ enum Context { Normal, Loop, Closure } +impl Copy for Context {} + struct CheckLoopVisitor<'a> { sess: &'a Session, cx: Context } +impl<'a> Copy for CheckLoopVisitor<'a> {} + pub fn check_crate(sess: &Session, krate: &ast::Crate) { visit::walk_crate(&mut CheckLoopVisitor { sess: sess, cx: Normal }, krate) } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index ed119081f78..2c437ae046b 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -99,7 +99,8 @@ impl<'a> FromIterator> for Matrix<'a> { } pub struct MatchCheckCtxt<'a, 'tcx: 'a> { - pub tcx: &'a ty::ctxt<'tcx> + pub tcx: &'a ty::ctxt<'tcx>, + pub param_env: ParameterEnvironment<'tcx>, } #[deriving(Clone, PartialEq)] @@ -131,6 +132,8 @@ enum WitnessPreference { LeaveOutWitness } +impl Copy for WitnessPreference {} + impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> { fn visit_expr(&mut self, ex: &ast::Expr) { check_expr(self, ex); @@ -145,7 +148,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> { } pub fn check_crate(tcx: &ty::ctxt) { - visit::walk_crate(&mut MatchCheckCtxt { tcx: tcx }, tcx.map.krate()); + visit::walk_crate(&mut MatchCheckCtxt { + tcx: tcx, + param_env: ty::empty_parameter_environment(), + }, tcx.map.krate()); tcx.sess.abort_if_errors(); } @@ -954,8 +960,14 @@ fn check_fn(cx: &mut MatchCheckCtxt, decl: &ast::FnDecl, body: &ast::Block, sp: Span, - _: NodeId) { + fn_id: NodeId) { + match kind { + visit::FkFnBlock => {} + _ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id), + } + visit::walk_fn(cx, kind, decl, body, sp); + for input in decl.inputs.iter() { is_refutable(cx, &*input.pat, |pat| { span_err!(cx.tcx.sess, input.pat.span, E0006, @@ -1020,7 +1032,9 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, match p.node { ast::PatIdent(ast::BindByValue(_), _, ref sub) => { let pat_ty = ty::node_id_to_type(tcx, p.id); - if ty::type_moves_by_default(tcx, pat_ty) { + if ty::type_moves_by_default(tcx, + pat_ty, + &cx.param_env) { check_move(p, sub.as_ref().map(|p| &**p)); } } @@ -1048,7 +1062,9 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>, let mut checker = MutationChecker { cx: cx, }; - let mut visitor = ExprUseVisitor::new(&mut checker, checker.cx.tcx); + let mut visitor = ExprUseVisitor::new(&mut checker, + checker.cx.tcx, + cx.param_env.clone()); visitor.walk_expr(guard); } diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs index dae76ba125e..a14307b90ee 100644 --- a/src/librustc/middle/check_rvalues.rs +++ b/src/librustc/middle/check_rvalues.rs @@ -13,6 +13,7 @@ use middle::expr_use_visitor as euv; use middle::mem_categorization as mc; +use middle::ty::ParameterEnvironment; use middle::ty; use util::ppaux::ty_to_string; @@ -36,9 +37,10 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> { fd: &'v ast::FnDecl, b: &'v ast::Block, s: Span, - _: ast::NodeId) { + fn_id: ast::NodeId) { { - let mut euv = euv::ExprUseVisitor::new(self, self.tcx); + let param_env = ParameterEnvironment::for_item(self.tcx, fn_id); + let mut euv = euv::ExprUseVisitor::new(self, self.tcx, param_env); euv.walk_fn(fd, b); } visit::walk_fn(self, fk, fd, b, s) diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs index 2fc85afd393..a495d1e049d 100644 --- a/src/librustc/middle/check_static.rs +++ b/src/librustc/middle/check_static.rs @@ -47,13 +47,16 @@ enum Mode { InNothing, } +impl Copy for Mode {} + struct CheckStaticVisitor<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, mode: Mode, checker: &'a mut GlobalChecker, } -struct GlobalVisitor<'a, 'b, 'tcx: 'b>(euv::ExprUseVisitor<'a, 'b, 'tcx, ty::ctxt<'tcx>>); +struct GlobalVisitor<'a,'b,'tcx:'a+'b>( + euv::ExprUseVisitor<'a,'b,'tcx,ty::ctxt<'tcx>>); struct GlobalChecker { static_consumptions: NodeSet, const_borrows: NodeSet, @@ -69,7 +72,8 @@ pub fn check_crate(tcx: &ty::ctxt) { static_local_borrows: NodeSet::new(), }; { - let visitor = euv::ExprUseVisitor::new(&mut checker, tcx); + let param_env = ty::empty_parameter_environment(); + let visitor = euv::ExprUseVisitor::new(&mut checker, tcx, param_env); visit::walk_crate(&mut GlobalVisitor(visitor), tcx.map.krate()); } visit::walk_crate(&mut CheckStaticVisitor { @@ -242,7 +246,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> { } } -impl<'a, 'b, 't, 'v> Visitor<'v> for GlobalVisitor<'a, 'b, 't> { +impl<'a,'b,'t,'v> Visitor<'v> for GlobalVisitor<'a,'b,'t> { fn visit_item(&mut self, item: &ast::Item) { match item.node { ast::ItemConst(_, ref e) | diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 43726f55bb9..150bcbdd688 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -68,6 +68,8 @@ pub enum constness { non_const } +impl Copy for constness {} + type constness_cache = DefIdMap; pub fn join(a: constness, b: constness) -> constness { diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 53fea8ffc86..db8fd999f38 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -28,7 +28,12 @@ use syntax::print::{pp, pprust}; use util::nodemap::NodeMap; #[deriving(Show)] -pub enum EntryOrExit { Entry, Exit } +pub enum EntryOrExit { + Entry, + Exit, +} + +impl Copy for EntryOrExit {} #[deriving(Clone)] pub struct DataFlowContext<'a, 'tcx: 'a, O> { diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 4a4298f62f2..b3e4dd25adc 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -52,6 +52,8 @@ pub enum Def { DefMethod(ast::DefId /* method */, Option /* trait */, MethodProvenance), } +impl Copy for Def {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum MethodProvenance { FromTrait(ast::DefId), @@ -67,6 +69,8 @@ impl MethodProvenance { } } +impl Copy for MethodProvenance {} + impl Def { pub fn def_id(&self) -> ast::DefId { match *self { diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index dbec69f4205..8bf43c70c26 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -30,6 +30,8 @@ enum UnsafeContext { UnsafeBlock(ast::NodeId), } +impl Copy for UnsafeContext {} + fn type_is_unsafe_function(ty: Ty) -> bool { match ty.sty { ty::ty_bare_fn(ref f) => f.fn_style == ast::UnsafeFn, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 7d2bb7458ac..8e00c96535b 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -23,12 +23,13 @@ use self::OverloadedCallType::*; use middle::{def, region, pat_util}; use middle::mem_categorization as mc; use middle::mem_categorization::Typer; -use middle::ty::{mod, Ty}; +use middle::ty::{mod, ParameterEnvironment, Ty}; use middle::ty::{MethodCall, MethodObject, MethodTraitObject}; use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam}; use middle::ty::{MethodStatic, MethodStaticUnboxedClosure}; use util::ppaux::Repr; +use std::kinds; use syntax::ast; use syntax::ptr::P; use syntax::codemap::Span; @@ -106,12 +107,16 @@ pub enum LoanCause { MatchDiscriminant } +impl kinds::Copy for LoanCause {} + #[deriving(PartialEq, Show)] pub enum ConsumeMode { Copy, // reference to x where x has a type that copies Move(MoveReason), // reference to x where x has a type that moves } +impl kinds::Copy for ConsumeMode {} + #[deriving(PartialEq,Show)] pub enum MoveReason { DirectRefMove, @@ -119,6 +124,8 @@ pub enum MoveReason { CaptureMove, } +impl kinds::Copy for MoveReason {} + #[deriving(PartialEq,Show)] pub enum MatchMode { NonBindingMatch, @@ -127,11 +134,17 @@ pub enum MatchMode { MovingMatch, } +impl kinds::Copy for MatchMode {} + #[deriving(PartialEq,Show)] enum TrackMatchMode { - Unknown, Definite(MatchMode), Conflicting, + Unknown, + Definite(MatchMode), + Conflicting, } +impl kinds::Copy for TrackMatchMode {} + impl TrackMatchMode { // Builds up the whole match mode for a pattern from its constituent // parts. The lattice looks like this: @@ -199,12 +212,16 @@ pub enum MutateMode { WriteAndRead, // x += y } +impl kinds::Copy for MutateMode {} + enum OverloadedCallType { FnOverloadedCall, FnMutOverloadedCall, FnOnceOverloadedCall, } +impl kinds::Copy for OverloadedCallType {} + impl OverloadedCallType { fn from_trait_id(tcx: &ty::ctxt, trait_id: ast::DefId) -> OverloadedCallType { @@ -293,6 +310,7 @@ pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> { typer: &'t TYPER, mc: mc::MemCategorizationContext<'t,TYPER>, delegate: &'d mut (Delegate<'tcx>+'d), + param_env: ParameterEnvironment<'tcx>, } // If the TYPER results in an error, it's because the type check @@ -313,11 +331,15 @@ macro_rules! return_if_err( impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { pub fn new(delegate: &'d mut Delegate<'tcx>, - typer: &'t TYPER) + typer: &'t TYPER, + param_env: ParameterEnvironment<'tcx>) -> ExprUseVisitor<'d,'t,'tcx,TYPER> { - ExprUseVisitor { typer: typer, - mc: mc::MemCategorizationContext::new(typer), - delegate: delegate } + ExprUseVisitor { + typer: typer, + mc: mc::MemCategorizationContext::new(typer), + delegate: delegate, + param_env: param_env, + } } pub fn walk_fn(&mut self, @@ -352,7 +374,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { consume_id: ast::NodeId, consume_span: Span, cmt: mc::cmt<'tcx>) { - let mode = copy_or_move(self.tcx(), cmt.ty, DirectRefMove); + let mode = copy_or_move(self.tcx(), + cmt.ty, + &self.param_env, + DirectRefMove); self.delegate.consume(consume_id, consume_span, cmt, mode); } @@ -954,7 +979,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { ast::PatIdent(ast::BindByRef(_), _, _) => mode.lub(BorrowingMatch), ast::PatIdent(ast::BindByValue(_), _, _) => { - match copy_or_move(tcx, cmt_pat.ty, PatBindingMove) { + match copy_or_move(tcx, + cmt_pat.ty, + &self.param_env, + PatBindingMove) { Copy => mode.lub(CopyingMatch), Move(_) => mode.lub(MovingMatch), } @@ -984,7 +1012,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { let tcx = typer.tcx(); let def_map = &self.typer.tcx().def_map; let delegate = &mut self.delegate; - + let param_env = &mut self.param_env; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { if pat_util::pat_is_binding(def_map, pat) { let tcx = typer.tcx(); @@ -1018,7 +1046,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { r, bk, RefBinding); } ast::PatIdent(ast::BindByValue(_), _, _) => { - let mode = copy_or_move(typer.tcx(), cmt_pat.ty, PatBindingMove); + let mode = copy_or_move(typer.tcx(), + cmt_pat.ty, + param_env, + PatBindingMove); debug!("walk_pat binding consuming pat"); delegate.consume_pat(pat, cmt_pat, mode); } @@ -1211,7 +1242,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, closure_expr.span, freevar.def)); - let mode = copy_or_move(self.tcx(), cmt_var.ty, CaptureMove); + let mode = copy_or_move(self.tcx(), + cmt_var.ty, + &self.param_env, + CaptureMove); self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode); } } @@ -1229,8 +1263,15 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } } -fn copy_or_move<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, - move_reason: MoveReason) -> ConsumeMode { - if ty::type_moves_by_default(tcx, ty) { Move(move_reason) } else { Copy } +fn copy_or_move<'tcx>(tcx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>, + param_env: &ParameterEnvironment<'tcx>, + move_reason: MoveReason) + -> ConsumeMode { + if ty::type_moves_by_default(tcx, ty, param_env) { + Move(move_reason) + } else { + Copy + } } diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs index 888f01f9118..6780177933f 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -33,6 +33,8 @@ pub enum SimplifiedType { ParameterSimplifiedType, } +impl Copy for SimplifiedType {} + /// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc. /// The idea is to get something simple that we can use to quickly decide if two types could unify /// during method lookup. diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs index 2f50a964023..e45232a3c30 100644 --- a/src/librustc/middle/graph.rs +++ b/src/librustc/middle/graph.rs @@ -65,11 +65,15 @@ pub struct NodeIndex(pub uint); #[allow(non_upper_case_globals)] pub const InvalidNodeIndex: NodeIndex = NodeIndex(uint::MAX); +impl Copy for NodeIndex {} + #[deriving(PartialEq, Show)] pub struct EdgeIndex(pub uint); #[allow(non_upper_case_globals)] pub const InvalidEdgeIndex: EdgeIndex = EdgeIndex(uint::MAX); +impl Copy for EdgeIndex {} + // Use a private field here to guarantee no more instances are created: #[deriving(Show)] pub struct Direction { repr: uint } @@ -78,6 +82,8 @@ pub const Outgoing: Direction = Direction { repr: 0 }; #[allow(non_upper_case_globals)] pub const Incoming: Direction = Direction { repr: 1 }; +impl Copy for Direction {} + impl NodeIndex { fn get(&self) -> uint { let NodeIndex(v) = *self; v } /// Returns unique id (unique with respect to the graph holding associated node). diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index c5845b143af..81cd8dd20d2 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -132,6 +132,8 @@ pub enum TypeOrigin { IfExpressionWithNoElse(Span) } +impl Copy for TypeOrigin {} + /// See `error_reporting.rs` for more details #[deriving(Clone, Show)] pub enum ValuePairs<'tcx> { @@ -237,6 +239,8 @@ pub enum LateBoundRegionConversionTime { HigherRankedType, } +impl Copy for LateBoundRegionConversionTime {} + /// Reasons to create a region inference variable /// /// See `error_reporting.rs` for more details @@ -280,6 +284,8 @@ pub enum fixup_err { unresolved_ty(TyVid) } +impl Copy for fixup_err {} + pub fn fixup_err_to_string(f: fixup_err) -> String { match f { unresolved_int_ty(_) => { diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 9155c18cb3b..391e37e8b9c 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -51,6 +51,8 @@ pub enum Constraint { ConstrainVarSubReg(RegionVid, Region), } +impl Copy for Constraint {} + // Something we have to verify after region inference is done, but // which does not directly influence the inference process pub enum Verify<'tcx> { @@ -72,6 +74,8 @@ pub struct TwoRegions { b: Region, } +impl Copy for TwoRegions {} + #[deriving(PartialEq)] pub enum UndoLogEntry { OpenSnapshot, @@ -84,11 +88,15 @@ pub enum UndoLogEntry { AddCombination(CombineMapType, TwoRegions) } +impl Copy for UndoLogEntry {} + #[deriving(PartialEq)] pub enum CombineMapType { Lub, Glb } +impl Copy for CombineMapType {} + #[deriving(Clone, Show)] pub enum RegionResolutionError<'tcx> { /// `ConcreteFailure(o, a, b)`: @@ -220,11 +228,15 @@ pub struct RegionSnapshot { length: uint } +impl Copy for RegionSnapshot {} + #[deriving(Show)] pub struct RegionMark { length: uint } +impl Copy for RegionMark {} + impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { pub fn new(tcx: &'a ty::ctxt<'tcx>) -> RegionVarBindings<'a, 'tcx> { RegionVarBindings { @@ -926,8 +938,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { #[deriving(PartialEq, Show)] enum Classification { Expanding, Contracting } +impl Copy for Classification {} + pub enum VarValue { NoValue, Value(Region), ErrorValue } +impl Copy for VarValue {} + struct VarData { classification: Classification, value: VarValue, diff --git a/src/librustc/middle/infer/type_variable.rs b/src/librustc/middle/infer/type_variable.rs index 3058f09a83a..766e930486c 100644 --- a/src/librustc/middle/infer/type_variable.rs +++ b/src/librustc/middle/infer/type_variable.rs @@ -49,6 +49,8 @@ pub enum RelationDir { SubtypeOf, SupertypeOf, EqTo } +impl Copy for RelationDir {} + impl RelationDir { fn opposite(self) -> RelationDir { match self { diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs index 6f6adb84a75..a2dd4d62913 100644 --- a/src/librustc/middle/infer/unify.rs +++ b/src/librustc/middle/infer/unify.rs @@ -92,6 +92,8 @@ pub struct Node { pub struct Delegate; +impl Copy for Delegate {} + // We can't use V:LatticeValue, much as I would like to, // because frequently the pattern is that V=Option for some // other type parameter U, and we have no way to say diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index da1c0bd649a..4a20c92d8e2 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -50,6 +50,8 @@ pub enum LangItem { $($variant),* } +impl Copy for LangItem {} + pub struct LanguageItems { pub items: Vec>, pub missing: Vec, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index a6d3c15df8a..5edbafc4e0b 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -137,9 +137,14 @@ enum LoopKind<'a> { #[deriving(PartialEq)] struct Variable(uint); + +impl Copy for Variable {} + #[deriving(PartialEq)] struct LiveNode(uint); +impl Copy for LiveNode {} + impl Variable { fn get(&self) -> uint { let Variable(v) = *self; v } } @@ -162,6 +167,8 @@ enum LiveNodeKind { ExitNode } +impl Copy for LiveNodeKind {} + fn live_node_kind_to_string(lnk: LiveNodeKind, cx: &ty::ctxt) -> String { let cm = cx.sess.codemap(); match lnk { @@ -246,6 +253,8 @@ struct LocalInfo { ident: ast::Ident } +impl Copy for LocalInfo {} + #[deriving(Show)] enum VarKind { Arg(NodeId, ast::Ident), @@ -254,6 +263,8 @@ enum VarKind { CleanExit } +impl Copy for VarKind {} + struct IrMaps<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, @@ -532,6 +543,8 @@ struct Users { used: bool } +impl Copy for Users {} + fn invalid_users() -> Users { Users { reader: invalid_node(), @@ -547,6 +560,8 @@ struct Specials { clean_exit_var: Variable } +impl Copy for Specials {} + static ACC_READ: uint = 1u; static ACC_WRITE: uint = 2u; static ACC_USE: uint = 4u; diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index cd70d8e2b48..302fbd53dd5 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -110,6 +110,8 @@ pub struct Upvar { pub is_unboxed: bool } +impl Copy for Upvar {} + // different kinds of pointers: #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub enum PointerKind { @@ -119,6 +121,8 @@ pub enum PointerKind { UnsafePtr(ast::Mutability) } +impl Copy for PointerKind {} + // We use the term "interior" to mean "something reachable from the // base without a pointer dereference", e.g. a field #[deriving(Clone, PartialEq, Eq, Hash, Show)] @@ -127,18 +131,24 @@ pub enum InteriorKind { InteriorElement(ElementKind), } +impl Copy for InteriorKind {} + #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub enum FieldName { NamedField(ast::Name), PositionalField(uint) } +impl Copy for FieldName {} + #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub enum ElementKind { VecElement, OtherElement, } +impl Copy for ElementKind {} + #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub enum MutabilityCategory { McImmutable, // Immutable. @@ -146,6 +156,8 @@ pub enum MutabilityCategory { McInherited, // Inherited from the fact that owner is mutable. } +impl Copy for MutabilityCategory {} + // A note about the provenance of a `cmt`. This is used for // special-case handling of upvars such as mutability inference. // Upvar categorization can generate a variable number of nested @@ -158,6 +170,8 @@ pub enum Note { NoteNone // Nothing special } +impl Copy for Note {} + // `cmt`: "Category, Mutability, and Type". // // a complete categorization of a value indicating where it originated @@ -191,6 +205,8 @@ pub enum deref_kind { deref_interior(InteriorKind), } +impl Copy for deref_kind {} + // Categorizes a derefable type. Note that we include vectors and strings as // derefable (we model an index as the combination of a deref and then a // pointer adjustment). @@ -261,6 +277,8 @@ pub struct MemCategorizationContext<'t,TYPER:'t> { typer: &'t TYPER } +impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {} + pub type McResult = Result; /// The `Typer` trait provides the interface for the mem-categorization @@ -1384,6 +1402,8 @@ pub enum InteriorSafety { InteriorSafe } +impl Copy for InteriorSafety {} + pub enum AliasableReason { AliasableBorrowed, AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env @@ -1392,6 +1412,8 @@ pub enum AliasableReason { AliasableStaticMut(InteriorSafety), } +impl Copy for AliasableReason {} + impl<'tcx> cmt_<'tcx> { pub fn guarantor(&self) -> cmt<'tcx> { //! Returns `self` after stripping away any owned pointer derefs or diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 2b8dd8df249..370097004e9 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -41,6 +41,8 @@ pub enum CodeExtent { Misc(ast::NodeId) } +impl Copy for CodeExtent {} + impl CodeExtent { /// Creates a scope that represents the dynamic extent associated /// with `node_id`. @@ -120,6 +122,8 @@ pub struct Context { parent: Option, } +impl Copy for Context {} + struct RegionResolutionVisitor<'a> { sess: &'a Session, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 8c3aa22c5fc..36b87bbd423 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -94,6 +94,8 @@ struct binding_info { binding_mode: BindingMode, } +impl Copy for binding_info {} + // Map from the name in a pattern to its binding mode. type BindingMap = HashMap; @@ -130,12 +132,16 @@ pub enum LastPrivate { type_used: ImportUse}, } +impl Copy for LastPrivate {} + #[deriving(Show)] pub enum PrivateDep { AllPublic, DependsOn(DefId), } +impl Copy for PrivateDep {} + // How an import is used. #[deriving(PartialEq, Show)] pub enum ImportUse { @@ -143,6 +149,8 @@ pub enum ImportUse { Used, // The import is used. } +impl Copy for ImportUse {} + impl LastPrivate { fn or(self, other: LastPrivate) -> LastPrivate { match (self, other) { @@ -159,12 +167,16 @@ enum PatternBindingMode { ArgumentIrrefutableMode, } +impl Copy for PatternBindingMode {} + #[deriving(PartialEq, Eq, Hash, Show)] enum Namespace { TypeNS, ValueNS } +impl Copy for Namespace {} + #[deriving(PartialEq)] enum NamespaceError { NoError, @@ -173,6 +185,8 @@ enum NamespaceError { ValueError } +impl Copy for NamespaceError {} + /// A NamespaceResult represents the result of resolving an import in /// a particular namespace. The result is either definitely-resolved, /// definitely- unresolved, or unknown. @@ -238,6 +252,8 @@ enum ImportDirectiveSubclass { GlobImport } +impl Copy for ImportDirectiveSubclass {} + /// The context that we thread through while building the reduced graph. #[deriving(Clone)] enum ReducedGraphParent { @@ -294,6 +310,8 @@ enum TypeParameters<'a> { RibKind) } +impl<'a> Copy for TypeParameters<'a> {} + // The rib kind controls the translation of local // definitions (`DefLocal`) to upvars (`DefUpvar`). @@ -319,17 +337,23 @@ enum RibKind { ConstantItemRibKind } +impl Copy for RibKind {} + // Methods can be required or provided. RequiredMethod methods only occur in traits. enum MethodSort { RequiredMethod, ProvidedMethod(NodeId) } +impl Copy for MethodSort {} + enum UseLexicalScopeFlag { DontUseLexicalScope, UseLexicalScope } +impl Copy for UseLexicalScopeFlag {} + enum ModulePrefixResult { NoPrefixFound, PrefixFound(Rc, uint) @@ -342,6 +366,8 @@ pub enum TraitItemKind { TypeTraitItemKind, } +impl Copy for TraitItemKind {} + impl TraitItemKind { pub fn from_explicit_self_category(explicit_self_category: ExplicitSelfCategory) @@ -364,12 +390,16 @@ enum NameSearchType { PathSearch, } +impl Copy for NameSearchType {} + enum BareIdentifierPatternResolution { FoundStructOrEnumVariant(Def, LastPrivate), FoundConst(Def, LastPrivate), BareIdentifierPatternUnresolved } +impl Copy for BareIdentifierPatternResolution {} + // Specifies how duplicates should be handled when adding a child item if // another item exists with the same name in some namespace. #[deriving(PartialEq)] @@ -381,6 +411,8 @@ enum DuplicateCheckingMode { OverwriteDuplicates } +impl Copy for DuplicateCheckingMode {} + /// One local scope. struct Rib { bindings: HashMap, @@ -518,6 +550,8 @@ enum ModuleKind { AnonymousModuleKind, } +impl Copy for ModuleKind {} + /// One node in the tree of modules. struct Module { parent_link: ParentLink, @@ -599,6 +633,8 @@ bitflags! { } } +impl Copy for DefModifiers {} + // Records a possibly-private type definition. #[deriving(Clone)] struct TypeNsDef { @@ -616,6 +652,8 @@ struct ValueNsDef { value_span: Option, } +impl Copy for ValueNsDef {} + // Records the definitions (at most one for each namespace) that a name is // bound to. struct NameBindings { @@ -632,6 +670,8 @@ enum TraitReferenceType { TraitQPath, // :: } +impl Copy for TraitReferenceType {} + impl NameBindings { fn new() -> NameBindings { NameBindings { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index bd8db1d51df..2ba9ba5631d 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -46,6 +46,8 @@ pub enum DefRegion { /* lifetime decl */ ast::NodeId), } +impl Copy for DefRegion {} + // maps the id of each lifetime reference to the lifetime decl // that it corresponds to pub type NamedRegionMap = NodeMap; diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 21f57a9d573..bcc762a9640 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -190,6 +190,8 @@ pub enum ParamSpace { FnSpace, // Type parameters attached to a method or fn } +impl Copy for ParamSpace {} + impl ParamSpace { pub fn all() -> [ParamSpace, ..4] { [TypeSpace, SelfSpace, AssocSpace, FnSpace] diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index e12ec44ad87..d410a456dc9 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -60,6 +60,8 @@ pub struct ObligationCause<'tcx> { pub code: ObligationCauseCode<'tcx> } +impl<'tcx> Copy for ObligationCause<'tcx> {} + #[deriving(Clone)] pub enum ObligationCauseCode<'tcx> { /// Not well classified or should be obvious from span. @@ -95,6 +97,8 @@ pub enum ObligationCauseCode<'tcx> { pub type Obligations<'tcx> = subst::VecPerParamSpace>; +impl<'tcx> Copy for ObligationCauseCode<'tcx> {} + pub type Selection<'tcx> = Vtable<'tcx, Obligation<'tcx>>; #[deriving(Clone,Show)] @@ -338,7 +342,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()), VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()), VtableParam(ref p) => VtableParam((*p).clone()), - VtableBuiltin(ref i) => VtableBuiltin(i.map_nested(op)), + VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)), } } @@ -348,7 +352,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableFnPointer(sig) => VtableFnPointer(sig), VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s), VtableParam(p) => VtableParam(p), - VtableBuiltin(i) => VtableBuiltin(i.map_move_nested(op)), + VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)), } } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 0e6a0c19f70..5ad0d17ad13 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -80,6 +80,7 @@ struct ObligationStack<'prev, 'tcx: 'prev> { previous: Option<&'prev ObligationStack<'prev, 'tcx>> } +#[deriving(Clone)] pub struct SelectionCache<'tcx> { hashmap: RefCell>, SelectionResult<'tcx, Candidate<'tcx>>>>, @@ -102,6 +103,8 @@ pub enum MethodMatchedData { CoerciveMethodMatch(/* impl we matched */ ast::DefId) } +impl Copy for MethodMatchedData {} + /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes /// we'll be able to say definitively that (e.g.) an impl does not @@ -918,20 +921,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // and applicable impls. There is a certain set of precedence rules here. match self.tcx().lang_items.to_builtin_kind(obligation.trait_ref.def_id) { - Some(bound) => { - try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates)); + Some(ty::BoundCopy) => { + debug!("obligation self ty is {}", + obligation.self_ty().repr(self.tcx())); + try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); + try!(self.assemble_builtin_bound_candidates(ty::BoundCopy, + stack, + &mut candidates)); } None => { - // For the time being, we ignore user-defined impls for builtin-bounds. + // For the time being, we ignore user-defined impls for builtin-bounds, other than + // `Copy`. // (And unboxed candidates only apply to the Fn/FnMut/etc traits.) try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates)); try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates)); try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); } + + Some(bound) => { + try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates)); + } } try!(self.assemble_candidates_from_caller_bounds(obligation, &mut candidates)); + debug!("candidate list size: {}", candidates.vec.len()); Ok(candidates) } @@ -1519,13 +1533,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::BoundCopy => { - if - Some(def_id) == tcx.lang_items.no_copy_bound() || - Some(def_id) == tcx.lang_items.managed_bound() || - ty::has_dtor(tcx, def_id) - { - return Err(Unimplemented); - } + // This is an Opt-In Built-In Trait. + return Ok(ParameterBuiltin) } ty::BoundSync => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8a2529701bb..4c4b5d07f50 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -38,6 +38,7 @@ pub use self::IntVarValue::*; pub use self::ExprAdjustment::*; pub use self::vtable_origin::*; pub use self::MethodOrigin::*; +pub use self::CopyImplementationError::*; use back::svh::Svh; use session::Session; @@ -52,8 +53,10 @@ use middle::mem_categorization as mc; use middle::region; use middle::resolve; use middle::resolve_lifetime; +use middle::infer; use middle::stability; use middle::subst::{mod, Subst, Substs, VecPerParamSpace}; +use middle::traits::ObligationCause; use middle::traits; use middle::ty; use middle::ty_fold::{mod, TypeFoldable, TypeFolder, HigherRankedFoldable}; @@ -72,7 +75,7 @@ use std::hash::{Hash, sip, Writer}; use std::mem; use std::ops; use std::rc::Rc; -use std::collections::hash_map::{Occupied, Vacant}; +use std::collections::hash_map::{HashMap, Occupied, Vacant}; use arena::TypedArena; use syntax::abi; use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE}; @@ -81,7 +84,7 @@ use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField}; use syntax::ast::{Visibility}; use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod}; use syntax::attr::{mod, AttrMetaMethods}; -use syntax::codemap::Span; +use syntax::codemap::{DUMMY_SP, Span}; use syntax::parse::token::{mod, InternedString}; use syntax::{ast, ast_map}; use std::collections::enum_set::{EnumSet, CLike}; @@ -109,12 +112,16 @@ pub struct field<'tcx> { pub mt: mt<'tcx> } +impl<'tcx> Copy for field<'tcx> {} + #[deriving(Clone, Show)] pub enum ImplOrTraitItemContainer { TraitContainer(ast::DefId), ImplContainer(ast::DefId), } +impl Copy for ImplOrTraitItemContainer {} + impl ImplOrTraitItemContainer { pub fn id(&self) -> ast::DefId { match *self { @@ -175,6 +182,8 @@ pub enum ImplOrTraitItemId { TypeTraitItemId(ast::DefId), } +impl Copy for ImplOrTraitItemId {} + impl ImplOrTraitItemId { pub fn def_id(&self) -> ast::DefId { match *self { @@ -236,12 +245,16 @@ pub struct AssociatedType { pub container: ImplOrTraitItemContainer, } +impl Copy for AssociatedType {} + #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct mt<'tcx> { pub ty: Ty<'tcx>, pub mutbl: ast::Mutability, } +impl<'tcx> Copy for mt<'tcx> {} + #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)] pub enum TraitStore { /// Box @@ -250,6 +263,8 @@ pub enum TraitStore { RegionTraitStore(Region, ast::Mutability), } +impl Copy for TraitStore {} + #[deriving(Clone, Show)] pub struct field_ty { pub name: Name, @@ -258,6 +273,8 @@ pub struct field_ty { pub origin: ast::DefId, // The DefId of the struct in which the field is declared. } +impl Copy for field_ty {} + // Contains information needed to resolve types and (in the future) look up // the types of AST nodes. #[deriving(PartialEq, Eq, Hash)] @@ -267,11 +284,15 @@ pub struct creader_cache_key { pub len: uint } +impl Copy for creader_cache_key {} + pub enum ast_ty_to_ty_cache_entry<'tcx> { atttce_unresolved, /* not resolved yet */ atttce_resolved(Ty<'tcx>) /* resolved to a type, irrespective of region */ } +impl<'tcx> Copy for ast_ty_to_ty_cache_entry<'tcx> {} + #[deriving(Clone, PartialEq, Decodable, Encodable)] pub struct ItemVariances { pub types: VecPerParamSpace, @@ -286,6 +307,8 @@ pub enum Variance { Bivariant, // T <: T -- e.g., unused type parameter } +impl Copy for Variance {} + #[deriving(Clone, Show)] pub enum AutoAdjustment<'tcx> { AdjustAddEnv(ty::TraitStore), @@ -431,6 +454,8 @@ pub struct param_index { pub index: uint } +impl Copy for param_index {} + #[deriving(Clone, Show)] pub enum MethodOrigin<'tcx> { // fully statically resolved method @@ -485,6 +510,8 @@ pub struct MethodCallee<'tcx> { pub substs: subst::Substs<'tcx> } +impl Copy for MethodCall {} + /// With method calls, we store some extra information in /// side tables (i.e method_map). We use /// MethodCall as a key to index into these tables instead of @@ -510,6 +537,8 @@ pub enum ExprAdjustment { AutoObject } +impl Copy for ExprAdjustment {} + impl MethodCall { pub fn expr(id: ast::NodeId) -> MethodCall { MethodCall { @@ -594,6 +623,8 @@ pub struct TransmuteRestriction<'tcx> { pub id: ast::NodeId, } +impl<'tcx> Copy for TransmuteRestriction<'tcx> {} + /// The data structure to keep track of all the information that typechecker /// generates so that so that it can be reused and doesn't have to be redone /// later on. @@ -746,6 +777,9 @@ pub struct ctxt<'tcx> { /// Caches the representation hints for struct definitions. pub repr_hint_cache: RefCell>>>, + + /// Caches whether types move by default. + pub type_moves_by_default_cache: RefCell,bool>>, } // Flags that we track on types. These flags are propagated upwards @@ -766,6 +800,8 @@ bitflags! { } } +impl Copy for TypeFlags {} + #[deriving(Show)] pub struct TyS<'tcx> { pub sty: sty<'tcx>, @@ -807,6 +843,7 @@ impl<'tcx> PartialEq for InternedTy<'tcx> { self.ty.sty == other.ty.sty } } + impl<'tcx> Eq for InternedTy<'tcx> {} impl<'tcx, S: Writer> Hash for InternedTy<'tcx> { @@ -900,6 +937,8 @@ impl<'tcx> FnOutput<'tcx> { } } +impl<'tcx> Copy for FnOutput<'tcx> {} + /// Signature of a function type, which I have arbitrarily /// decided to use to refer to the input/output types. /// @@ -924,6 +963,8 @@ pub struct ParamTy { pub def_id: DefId } +impl Copy for ParamTy {} + /// A [De Bruijn index][dbi] is a standard means of representing /// regions (and perhaps later types) in a higher-ranked setting. In /// particular, imagine a type like this: @@ -1018,6 +1059,8 @@ pub struct UpvarId { pub closure_expr_id: ast::NodeId, } +impl Copy for UpvarId {} + #[deriving(Clone, PartialEq, Eq, Hash, Show, Encodable, Decodable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. @@ -1064,6 +1107,8 @@ pub enum BorrowKind { MutBorrow } +impl Copy for BorrowKind {} + /// Information describing the borrowing of an upvar. This is computed /// during `typeck`, specifically by `regionck`. The general idea is /// that the compiler analyses treat closures like: @@ -1119,6 +1164,8 @@ pub struct UpvarBorrow { pub type UpvarBorrowMap = FnvHashMap; +impl Copy for UpvarBorrow {} + impl Region { pub fn is_bound(&self) -> bool { match *self { @@ -1136,6 +1183,8 @@ impl Region { } } +impl Copy for Region {} + #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)] /// A "free" region `fr` can be interpreted as "some region /// at least as big as the scope `fr.scope`". @@ -1144,6 +1193,8 @@ pub struct FreeRegion { pub bound_region: BoundRegion } +impl Copy for FreeRegion {} + #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)] pub enum BoundRegion { /// An anonymous region parameter for a given fn (&T) @@ -1163,6 +1214,8 @@ pub enum BoundRegion { BrEnv } +impl Copy for BoundRegion {} + #[inline] pub fn mk_prim_t<'tcx>(primitive: &'tcx TyS<'static>) -> Ty<'tcx> { // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx. @@ -1302,6 +1355,8 @@ pub enum IntVarValue { UintType(ast::UintTy), } +impl Copy for IntVarValue {} + #[deriving(Clone, Show)] pub enum terr_vstore_kind { terr_vec, @@ -1310,12 +1365,16 @@ pub enum terr_vstore_kind { terr_trait } +impl Copy for terr_vstore_kind {} + #[deriving(Clone, Show)] pub struct expected_found { pub expected: T, pub found: T } +impl Copy for expected_found {} + // Data structures used in type unification #[deriving(Clone, Show)] pub enum type_err<'tcx> { @@ -1350,6 +1409,8 @@ pub enum type_err<'tcx> { terr_convergence_mismatch(expected_found) } +impl<'tcx> Copy for type_err<'tcx> {} + /// Bounds suitable for a named type parameter like `A` in `fn foo` /// as well as the existential type parameter in an object type. #[deriving(PartialEq, Eq, Hash, Clone, Show)] @@ -1370,6 +1431,8 @@ pub struct ExistentialBounds { pub builtin_bounds: BuiltinBounds } +impl Copy for ExistentialBounds {} + pub type BuiltinBounds = EnumSet; #[deriving(Clone, Encodable, PartialEq, Eq, Decodable, Hash, Show)] @@ -1381,6 +1444,8 @@ pub enum BuiltinBound { BoundSync, } +impl Copy for BuiltinBound {} + pub fn empty_builtin_bounds() -> BuiltinBounds { EnumSet::new() } @@ -1413,21 +1478,29 @@ pub struct TyVid { pub index: uint } +impl Copy for TyVid {} + #[deriving(Clone, PartialEq, Eq, Hash)] pub struct IntVid { pub index: uint } +impl Copy for IntVid {} + #[deriving(Clone, PartialEq, Eq, Hash)] pub struct FloatVid { pub index: uint } +impl Copy for FloatVid {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub struct RegionVid { pub index: uint } +impl Copy for RegionVid {} + #[deriving(Clone, PartialEq, Eq, Hash)] pub enum InferTy { TyVar(TyVid), @@ -1441,12 +1514,16 @@ pub enum InferTy { SkolemizedIntTy(uint), } +impl Copy for InferTy {} + #[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)] pub enum InferRegion { ReVar(RegionVid), ReSkolemized(uint, BoundRegion) } +impl Copy for InferRegion {} + impl cmp::PartialEq for InferRegion { fn eq(&self, other: &InferRegion) -> bool { match ((*self), *other) { @@ -1642,6 +1719,7 @@ impl<'tcx> TraitRef<'tcx> { /// bound lifetime parameters are replaced with free ones, but in the /// future I hope to refine the representation of types so as to make /// more distinctions clearer. +#[deriving(Clone)] pub struct ParameterEnvironment<'tcx> { /// A substitution that can be applied to move from /// the "outer" view of a type or method to the "inner" view. @@ -1690,14 +1768,14 @@ impl<'tcx> ParameterEnvironment<'tcx> { } TypeTraitItem(_) => { cx.sess - .bug("ParameterEnvironment::from_item(): \ + .bug("ParameterEnvironment::for_item(): \ can't create a parameter environment \ for type trait items") } } } ast::TypeImplItem(_) => { - cx.sess.bug("ParameterEnvironment::from_item(): \ + cx.sess.bug("ParameterEnvironment::for_item(): \ can't create a parameter environment \ for type impl items") } @@ -1707,7 +1785,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { match *trait_method { ast::RequiredMethod(ref required) => { cx.sess.span_bug(required.span, - "ParameterEnvironment::from_item(): + "ParameterEnvironment::for_item(): can't create a parameter \ environment for required trait \ methods") @@ -1725,7 +1803,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { } TypeTraitItem(_) => { cx.sess - .bug("ParameterEnvironment::from_item(): \ + .bug("ParameterEnvironment::for_item(): \ can't create a parameter environment \ for type trait items") } @@ -1768,6 +1846,10 @@ impl<'tcx> ParameterEnvironment<'tcx> { } } } + Some(ast_map::NodeExpr(..)) => { + // This is a convenience to allow closures to work. + ParameterEnvironment::for_item(cx, cx.map.get_parent(id)) + } _ => { cx.sess.bug(format!("ParameterEnvironment::from_item(): \ `{}` is not an item", @@ -1825,6 +1907,8 @@ pub enum UnboxedClosureKind { FnOnceUnboxedClosureKind, } +impl Copy for UnboxedClosureKind {} + impl UnboxedClosureKind { pub fn trait_did(&self, cx: &ctxt) -> ast::DefId { let result = match *self { @@ -1909,6 +1993,7 @@ pub fn mk_ctxt<'tcx>(s: Session, associated_types: RefCell::new(DefIdMap::new()), selection_cache: traits::SelectionCache::new(), repr_hint_cache: RefCell::new(DefIdMap::new()), + type_moves_by_default_cache: RefCell::new(HashMap::new()), } } @@ -2604,6 +2689,8 @@ pub struct TypeContents { pub bits: u64 } +impl Copy for TypeContents {} + macro_rules! def_type_content_sets( (mod $mname:ident { $($name:ident = $bits:expr),+ }) => { #[allow(non_snake_case)] @@ -2630,7 +2717,6 @@ def_type_content_sets!( OwnsOwned = 0b0000_0000__0000_0001__0000, OwnsDtor = 0b0000_0000__0000_0010__0000, OwnsManaged /* see [1] below */ = 0b0000_0000__0000_0100__0000, - OwnsAffine = 0b0000_0000__0000_1000__0000, OwnsAll = 0b0000_0000__1111_1111__0000, // Things that are reachable by the value in any way (fourth nibble): @@ -2640,24 +2726,12 @@ def_type_content_sets!( ReachesFfiUnsafe = 0b0010_0000__0000_0000__0000, ReachesAll = 0b0011_1111__0000_0000__0000, - // Things that cause values to *move* rather than *copy*. This - // is almost the same as the `Copy` trait, but for managed - // data -- atm, we consider managed data to copy, not move, - // but it does not impl Copy as a pure memcpy is not good - // enough. Yuck. - Moves = 0b0000_0000__0000_1011__0000, - // Things that mean drop glue is necessary NeedsDrop = 0b0000_0000__0000_0111__0000, // Things that prevent values from being considered sized Nonsized = 0b0000_0000__0000_0000__0001, - // Things that make values considered not POD (would be same - // as `Moves`, but for the fact that managed data `@` is - // not considered POD) - Noncopy = 0b0000_0000__0000_1111__0000, - // Bits to set when a managed value is encountered // // [1] Do not set the bits TC::OwnsManaged or @@ -2699,10 +2773,6 @@ impl TypeContents { self.intersects(TC::InteriorUnsized) } - pub fn moves_by_default(&self, _: &ctxt) -> bool { - self.intersects(TC::Moves) - } - pub fn needs_drop(&self, _: &ctxt) -> bool { self.intersects(TC::NeedsDrop) } @@ -2987,15 +3057,10 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { mc | tc_ty(cx, mt.ty, cache) } - fn apply_lang_items(cx: &ctxt, - did: ast::DefId, - tc: TypeContents) - -> TypeContents - { + fn apply_lang_items(cx: &ctxt, did: ast::DefId, tc: TypeContents) + -> TypeContents { if Some(did) == cx.lang_items.managed_bound() { tc | TC::Managed - } else if Some(did) == cx.lang_items.no_copy_bound() { - tc | TC::OwnsAffine } else if Some(did) == cx.lang_items.unsafe_type() { tc | TC::InteriorUnsafe } else { @@ -3008,7 +3073,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { mutbl: ast::Mutability) -> TypeContents { let b = match mutbl { - ast::MutMutable => TC::ReachesMutable | TC::OwnsAffine, + ast::MutMutable => TC::ReachesMutable, ast::MutImmutable => TC::None, }; b | (TC::ReachesBorrowed).when(region != ty::ReStatic) @@ -3028,14 +3093,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { } }; - // This also prohibits "@once fn" from being copied, which allows it to - // be called. Neither way really makes much sense. - let ot = match cty.onceness { - ast::Once => TC::OwnsAffine, - ast::Many => TC::None, - }; - - st | ot + st } fn object_contents(cx: &ctxt, @@ -3053,9 +3111,8 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { let mut tc = TC::All; each_inherited_builtin_bound(cx, bounds, traits, |bound| { tc = tc - match bound { - BoundSync | BoundSend => TC::None, + BoundSync | BoundSend | BoundCopy => TC::None, BoundSized => TC::Nonsized, - BoundCopy => TC::Noncopy, }; }); return tc; @@ -3081,8 +3138,38 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { } } -pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - type_contents(cx, ty).moves_by_default(cx) +pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, + ty: Ty<'tcx>, + param_env: &ParameterEnvironment<'tcx>) + -> bool { + if !type_has_params(ty) && !type_has_self(ty) { + match cx.type_moves_by_default_cache.borrow().get(&ty) { + None => {} + Some(&result) => { + debug!("determined whether {} moves by default (cached): {}", + ty_to_string(cx, ty), + result); + return result + } + } + } + + let infcx = infer::new_infer_ctxt(cx); + let mut fulfill_cx = traits::FulfillmentContext::new(); + let obligation = traits::obligation_for_builtin_bound( + cx, + ObligationCause::misc(DUMMY_SP), + ty, + ty::BoundCopy).unwrap(); + fulfill_cx.register_obligation(cx, obligation); + let result = !fulfill_cx.select_all_or_error(&infcx, + param_env, + cx).is_ok(); + cx.type_moves_by_default_cache.borrow_mut().insert(ty, result); + debug!("determined whether {} moves by default: {}", + ty_to_string(cx, ty), + result); + result } pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { @@ -3214,6 +3301,8 @@ pub enum Representability { SelfRecursive, } +impl Copy for Representability {} + /// Check whether a type is representable. This means it cannot contain unboxed /// structural recursion. This check is needed for structs and enums. pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>) @@ -3996,6 +4085,8 @@ pub enum ExprKind { RvalueStmtExpr } +impl Copy for ExprKind {} + pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { if tcx.method_map.borrow().contains_key(&MethodCall::expr(expr.id)) { // Overloaded operations are generally calls, and hence they are @@ -4555,6 +4646,8 @@ pub struct AssociatedTypeInfo { pub name: ast::Name, } +impl Copy for AssociatedTypeInfo {} + impl PartialOrd for AssociatedTypeInfo { fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option { Some(self.index.cmp(&other.index)) @@ -4738,6 +4831,8 @@ pub enum DtorKind { TraitDtor(DefId, bool) } +impl Copy for DtorKind {} + impl DtorKind { pub fn is_present(&self) -> bool { match *self { @@ -5125,6 +5220,8 @@ pub struct UnboxedClosureUpvar<'tcx> { pub ty: Ty<'tcx>, } +impl<'tcx> Copy for UnboxedClosureUpvar<'tcx> {} + // Returns a list of `UnboxedClosureUpvar`s for each upvar. pub fn unboxed_closure_upvars<'tcx>(tcx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &Substs<'tcx>) -> Vec> { @@ -5954,6 +6051,8 @@ pub enum ExplicitSelfCategory { ByBoxExplicitSelfCategory, } +impl Copy for ExplicitSelfCategory {} + /// Pushes all the lifetimes in the given type onto the given list. A /// "lifetime in a type" is a lifetime specified by a reference or a lifetime /// in a list of type substitutions. This does *not* traverse into nominal @@ -6023,6 +6122,8 @@ pub struct Freevar { pub span: Span } +impl Copy for Freevar {} + pub type FreevarMap = NodeMap>; pub type CaptureModeMap = NodeMap; @@ -6122,6 +6223,8 @@ impl DebruijnIndex { } } +impl Copy for DebruijnIndex {} + impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { match *self { @@ -6229,3 +6332,43 @@ pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref.substs.clone().with_method(meth_tps, meth_regions) } +pub enum CopyImplementationError { + FieldDoesNotImplementCopy(ast::Name), + VariantDoesNotImplementCopy(ast::Name), + TypeIsStructural, +} + +impl Copy for CopyImplementationError {} + +pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>, + self_type: Ty<'tcx>, + param_env: &ParameterEnvironment<'tcx>) + -> Result<(),CopyImplementationError> { + match self_type.sty { + ty::ty_struct(struct_did, ref substs) => { + let fields = ty::struct_fields(tcx, struct_did, substs); + for field in fields.iter() { + if type_moves_by_default(tcx, field.mt.ty, param_env) { + return Err(FieldDoesNotImplementCopy(field.name)) + } + } + } + ty::ty_enum(enum_did, ref substs) => { + let enum_variants = ty::enum_variants(tcx, enum_did); + for variant in enum_variants.iter() { + for variant_arg_type in variant.args.iter() { + let substd_arg_type = + variant_arg_type.subst(tcx, substs); + if type_moves_by_default(tcx, + substd_arg_type, + param_env) { + return Err(VariantDoesNotImplementCopy(variant.name)) + } + } + } + } + _ => return Err(TypeIsStructural), + } + + Ok(()) +} diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 981b58a3b7b..c7b5e1e8de9 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -55,6 +55,8 @@ pub enum OptLevel { Aggressive // -O3 } +impl Copy for OptLevel {} + #[deriving(Clone, PartialEq)] pub enum DebugInfoLevel { NoDebugInfo, @@ -62,6 +64,8 @@ pub enum DebugInfoLevel { FullDebugInfo, } +impl Copy for DebugInfoLevel {} + #[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)] pub enum OutputType { OutputTypeBitcode, @@ -71,6 +75,8 @@ pub enum OutputType { OutputTypeExe, } +impl Copy for OutputType {} + #[deriving(Clone)] pub struct Options { // The crate config requested for the session, which may be combined @@ -87,7 +93,7 @@ pub struct Options { // parsed code. It remains mutable in case its replacements wants to use // this. pub addl_lib_search_paths: RefCell>, - pub libs: Vec<(String, cstore::NativeLibaryKind)>, + pub libs: Vec<(String, cstore::NativeLibraryKind)>, pub maybe_sysroot: Option, pub target_triple: String, // User-specified cfg meta items. The compiler itself will add additional @@ -221,6 +227,8 @@ pub enum EntryFnType { EntryNone, } +impl Copy for EntryFnType {} + #[deriving(PartialEq, PartialOrd, Clone, Ord, Eq, Hash)] pub enum CrateType { CrateTypeExecutable, @@ -229,6 +237,8 @@ pub enum CrateType { CrateTypeStaticlib, } +impl Copy for CrateType {} + macro_rules! debugging_opts( ([ $opt:ident ] $cnt:expr ) => ( pub const $opt: u64 = 1 << $cnt; diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index ea252d9fd20..30318cc129c 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -25,6 +25,8 @@ use syntax::visit::Visitor; #[deriving(Clone,Show)] pub struct ErrorReported; +impl Copy for ErrorReported {} + pub fn time(do_it: bool, what: &str, u: U, f: |U| -> T) -> T { thread_local!(static DEPTH: Cell = Cell::new(0)); if !do_it { return f(u); } diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs index 4dd6306c3c0..d1816c655fa 100644 --- a/src/librustc/util/nodemap.rs +++ b/src/librustc/util/nodemap.rs @@ -71,6 +71,9 @@ pub mod DefIdSet { #[deriving(Clone, Default)] pub struct FnvHasher; +impl Copy for FnvHasher {} + +#[allow(missing_copy_implementations)] pub struct FnvState(u64); impl Hasher for FnvHasher { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index b6441ab4944..d143d05acfe 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -49,12 +49,16 @@ pub enum PpSourceMode { PpmExpandedHygiene, } +impl Copy for PpSourceMode {} + #[deriving(PartialEq, Show)] pub enum PpMode { PpmSource(PpSourceMode), PpmFlowGraph, } +impl Copy for PpMode {} + pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option) { let mut split = name.splitn(1, '='); let first = split.next().unwrap(); diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs index d705c82dd9a..04196feafd2 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_llvm/diagnostic.rs @@ -24,6 +24,8 @@ pub enum OptimizationDiagnosticKind { OptimizationFailure, } +impl Copy for OptimizationDiagnosticKind {} + impl OptimizationDiagnosticKind { pub fn describe(self) -> &'static str { match self { @@ -43,6 +45,8 @@ pub struct OptimizationDiagnostic { pub message: TwineRef, } +impl Copy for OptimizationDiagnostic {} + impl OptimizationDiagnostic { unsafe fn unpack(kind: OptimizationDiagnosticKind, di: DiagnosticInfoRef) -> OptimizationDiagnostic { @@ -72,6 +76,8 @@ pub enum Diagnostic { UnknownDiagnostic(DiagnosticInfoRef), } +impl Copy for Diagnostic {} + impl Diagnostic { pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic { let kind = super::LLVMGetDiagInfoKind(di); diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index a8211c0c9ea..23dad21e530 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -77,12 +77,16 @@ pub enum CallConv { X86_64_Win64 = 79, } +impl Copy for CallConv {} + pub enum Visibility { LLVMDefaultVisibility = 0, HiddenVisibility = 1, ProtectedVisibility = 2, } +impl Copy for Visibility {} + // This enum omits the obsolete (and no-op) linkage types DLLImportLinkage, // DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage. // LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either; @@ -101,6 +105,8 @@ pub enum Linkage { CommonLinkage = 14, } +impl Copy for Linkage {} + #[repr(C)] #[deriving(Show)] pub enum DiagnosticSeverity { @@ -110,6 +116,8 @@ pub enum DiagnosticSeverity { Note, } +impl Copy for DiagnosticSeverity {} + bitflags! { flags Attribute : u32 { const ZExtAttribute = 1 << 0, @@ -141,6 +149,8 @@ bitflags! { } } +impl Copy for Attribute {} + #[repr(u64)] pub enum OtherAttribute { // The following are not really exposed in @@ -162,16 +172,22 @@ pub enum OtherAttribute { NonNullAttribute = 1 << 44, } +impl Copy for OtherAttribute {} + pub enum SpecialAttribute { DereferenceableAttribute(u64) } +impl Copy for SpecialAttribute {} + #[repr(C)] pub enum AttributeSet { ReturnIndex = 0, FunctionIndex = !0 } +impl Copy for AttributeSet {} + pub trait AttrHelper { fn apply_llfn(&self, idx: c_uint, llfn: ValueRef); fn apply_callsite(&self, idx: c_uint, callsite: ValueRef); @@ -271,6 +287,8 @@ pub enum IntPredicate { IntSLE = 41, } +impl Copy for IntPredicate {} + // enum for the LLVM RealPredicate type pub enum RealPredicate { RealPredicateFalse = 0, @@ -291,6 +309,8 @@ pub enum RealPredicate { RealPredicateTrue = 15, } +impl Copy for RealPredicate {} + // The LLVM TypeKind type - must stay in sync with the def of // LLVMTypeKind in llvm/include/llvm-c/Core.h #[deriving(PartialEq)] @@ -314,6 +334,8 @@ pub enum TypeKind { X86_MMX = 15, } +impl Copy for TypeKind {} + #[repr(C)] pub enum AtomicBinOp { AtomicXchg = 0, @@ -329,6 +351,8 @@ pub enum AtomicBinOp { AtomicUMin = 10, } +impl Copy for AtomicBinOp {} + #[repr(C)] pub enum AtomicOrdering { NotAtomic = 0, @@ -341,6 +365,8 @@ pub enum AtomicOrdering { SequentiallyConsistent = 7 } +impl Copy for AtomicOrdering {} + // Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h) #[repr(C)] pub enum FileType { @@ -348,6 +374,8 @@ pub enum FileType { ObjectFileType = 1 } +impl Copy for FileType {} + pub enum MetadataType { MD_dbg = 0, MD_tbaa = 1, @@ -357,12 +385,16 @@ pub enum MetadataType { MD_tbaa_struct = 5 } +impl Copy for MetadataType {} + // Inline Asm Dialect pub enum AsmDialect { AD_ATT = 0, AD_Intel = 1 } +impl Copy for AsmDialect {} + #[deriving(PartialEq, Clone)] #[repr(C)] pub enum CodeGenOptLevel { @@ -372,6 +404,8 @@ pub enum CodeGenOptLevel { CodeGenLevelAggressive = 3, } +impl Copy for CodeGenOptLevel {} + #[deriving(PartialEq)] #[repr(C)] pub enum RelocMode { @@ -381,6 +415,8 @@ pub enum RelocMode { RelocDynamicNoPic = 3, } +impl Copy for RelocMode {} + #[repr(C)] pub enum CodeGenModel { CodeModelDefault = 0, @@ -391,6 +427,8 @@ pub enum CodeGenModel { CodeModelLarge = 5, } +impl Copy for CodeGenModel {} + #[repr(C)] pub enum DiagnosticKind { DK_InlineAsm = 0, @@ -403,47 +441,70 @@ pub enum DiagnosticKind { DK_OptimizationFailure, } +impl Copy for DiagnosticKind {} + // Opaque pointer types +#[allow(missing_copy_implementations)] pub enum Module_opaque {} pub type ModuleRef = *mut Module_opaque; +#[allow(missing_copy_implementations)] pub enum Context_opaque {} pub type ContextRef = *mut Context_opaque; +#[allow(missing_copy_implementations)] pub enum Type_opaque {} pub type TypeRef = *mut Type_opaque; +#[allow(missing_copy_implementations)] pub enum Value_opaque {} pub type ValueRef = *mut Value_opaque; +#[allow(missing_copy_implementations)] pub enum BasicBlock_opaque {} pub type BasicBlockRef = *mut BasicBlock_opaque; +#[allow(missing_copy_implementations)] pub enum Builder_opaque {} pub type BuilderRef = *mut Builder_opaque; +#[allow(missing_copy_implementations)] pub enum ExecutionEngine_opaque {} pub type ExecutionEngineRef = *mut ExecutionEngine_opaque; +#[allow(missing_copy_implementations)] pub enum MemoryBuffer_opaque {} pub type MemoryBufferRef = *mut MemoryBuffer_opaque; +#[allow(missing_copy_implementations)] pub enum PassManager_opaque {} pub type PassManagerRef = *mut PassManager_opaque; +#[allow(missing_copy_implementations)] pub enum PassManagerBuilder_opaque {} pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque; +#[allow(missing_copy_implementations)] pub enum Use_opaque {} pub type UseRef = *mut Use_opaque; +#[allow(missing_copy_implementations)] pub enum TargetData_opaque {} pub type TargetDataRef = *mut TargetData_opaque; +#[allow(missing_copy_implementations)] pub enum ObjectFile_opaque {} pub type ObjectFileRef = *mut ObjectFile_opaque; +#[allow(missing_copy_implementations)] pub enum SectionIterator_opaque {} pub type SectionIteratorRef = *mut SectionIterator_opaque; +#[allow(missing_copy_implementations)] pub enum Pass_opaque {} pub type PassRef = *mut Pass_opaque; +#[allow(missing_copy_implementations)] pub enum TargetMachine_opaque {} pub type TargetMachineRef = *mut TargetMachine_opaque; +#[allow(missing_copy_implementations)] pub enum Archive_opaque {} pub type ArchiveRef = *mut Archive_opaque; +#[allow(missing_copy_implementations)] pub enum Twine_opaque {} pub type TwineRef = *mut Twine_opaque; +#[allow(missing_copy_implementations)] pub enum DiagnosticInfo_opaque {} pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque; +#[allow(missing_copy_implementations)] pub enum DebugLoc_opaque {} pub type DebugLocRef = *mut DebugLoc_opaque; +#[allow(missing_copy_implementations)] pub enum SMDiagnostic_opaque {} pub type SMDiagnosticRef = *mut SMDiagnostic_opaque; @@ -454,6 +515,7 @@ pub mod debuginfo { pub use self::DIDescriptorFlags::*; use super::{ValueRef}; + #[allow(missing_copy_implementations)] pub enum DIBuilder_opaque {} pub type DIBuilderRef = *mut DIBuilder_opaque; @@ -490,6 +552,8 @@ pub mod debuginfo { FlagLValueReference = 1 << 14, FlagRValueReference = 1 << 15 } + + impl Copy for DIDescriptorFlags {} } @@ -2123,6 +2187,7 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef { } } +#[allow(missing_copy_implementations)] pub enum RustString_opaque {} pub type RustStringRef = *mut RustString_opaque; type RustStringRepr = *mut RefCell>; diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index a919fe686ab..0ed6ae31171 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -33,6 +33,17 @@ use std::sync::{Arc, Mutex}; use std::task::TaskBuilder; use libc::{c_uint, c_int, c_void}; +#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)] +pub enum OutputType { + OutputTypeBitcode, + OutputTypeAssembly, + OutputTypeLlvmAssembly, + OutputTypeObject, + OutputTypeExe, +} + +impl Copy for OutputType {} + pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { unsafe { let cstr = llvm::LLVMRustGetLastError(); diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 1482422b8d0..2a698a898fe 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -249,7 +249,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.collecting = true; self.visit_pat(&*arg.pat); self.collecting = false; - let span_utils = self.span; + let span_utils = self.span.clone(); for &(id, ref p, _, _) in self.collected_paths.iter() { let typ = ppaux::ty_to_string(&self.analysis.ty_cx, (*self.analysis.ty_cx.node_types.borrow())[id]); diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs index f0bb441145c..c15ff1d7f0a 100644 --- a/src/librustc_trans/save/recorder.rs +++ b/src/librustc_trans/save/recorder.rs @@ -87,6 +87,8 @@ pub enum Row { FnRef, } +impl Copy for Row {} + impl<'a> FmtStrs<'a> { pub fn new(rec: Box, span: SpanUtils<'a>, krate: String) -> FmtStrs<'a> { FmtStrs { @@ -223,7 +225,10 @@ impl<'a> FmtStrs<'a> { if self.recorder.dump_spans { if dump_spans { - self.recorder.dump_span(self.span, label, span, Some(sub_span)); + self.recorder.dump_span(self.span.clone(), + label, + span, + Some(sub_span)); } return; } diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index f76f2bea566..49e8e0fd347 100644 --- a/src/librustc_trans/save/span_utils.rs +++ b/src/librustc_trans/save/span_utils.rs @@ -21,6 +21,7 @@ use syntax::parse::lexer::{Reader,StringReader}; use syntax::parse::token; use syntax::parse::token::{keywords, Token}; +#[deriving(Clone)] pub struct SpanUtils<'a> { pub sess: &'a Session, pub err_count: Cell, diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index f5155852aa0..1ed06938e95 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -231,6 +231,8 @@ use syntax::ptr::P; #[deriving(Show)] struct ConstantExpr<'a>(&'a ast::Expr); +impl<'a> Copy for ConstantExpr<'a> {} + impl<'a> ConstantExpr<'a> { fn eq(self, other: ConstantExpr<'a>, tcx: &ty::ctxt) -> bool { let ConstantExpr(expr) = self; @@ -308,6 +310,8 @@ pub enum BranchKind { CompareSliceLength } +impl Copy for BranchKind {} + pub enum OptResult<'blk, 'tcx: 'blk> { SingleResult(Result<'blk, 'tcx>), RangeResult(Result<'blk, 'tcx>, Result<'blk, 'tcx>), @@ -321,6 +325,8 @@ pub enum TransBindingMode { TrByRef, } +impl Copy for TransBindingMode {} + /// Information about a pattern binding: /// - `llmatch` is a pointer to a stack slot. The stack slot contains a /// pointer into the value being matched. Hence, llmatch has type `T**` @@ -337,6 +343,8 @@ pub struct BindingInfo<'tcx> { pub ty: Ty<'tcx>, } +impl<'tcx> Copy for BindingInfo<'tcx> {} + type BindingsMap<'tcx> = FnvHashMap>; struct ArmData<'p, 'blk, 'tcx: 'blk> { @@ -543,7 +551,11 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( check_match::Constructor::Variant(def_id) }; - let mcx = check_match::MatchCheckCtxt { tcx: bcx.tcx() }; + let param_env = ty::empty_parameter_environment(); + let mcx = check_match::MatchCheckCtxt { + tcx: bcx.tcx(), + param_env: param_env, + }; enter_match(bcx, dm, m, col, val, |pats| check_match::specialize(&mcx, pats.as_slice(), &ctor, col, variant_size) ) @@ -1001,7 +1013,10 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, node_id_type(bcx, pat_id) }; - let mcx = check_match::MatchCheckCtxt { tcx: bcx.tcx() }; + let mcx = check_match::MatchCheckCtxt { + tcx: bcx.tcx(), + param_env: ty::empty_parameter_environment(), + }; let adt_vals = if any_irrefutable_adt_pat(bcx.tcx(), m, col) { let repr = adt::represent_type(bcx.ccx(), left_ty); let arg_count = adt::num_args(&*repr, 0); @@ -1254,7 +1269,8 @@ fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool reassigned: false }; { - let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx); + let param_env = ty::empty_parameter_environment(); + let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx, param_env); visitor.walk_expr(body); } rc.reassigned @@ -1312,12 +1328,15 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, let variable_ty = node_id_type(bcx, p_id); let llvariable_ty = type_of::type_of(ccx, variable_ty); let tcx = bcx.tcx(); + let param_env = ty::empty_parameter_environment(); let llmatch; let trmode; match bm { ast::BindByValue(_) - if !ty::type_moves_by_default(tcx, variable_ty) || reassigned => { + if !ty::type_moves_by_default(tcx, + variable_ty, + ¶m_env) || reassigned => { llmatch = alloca_no_lifetime(bcx, llvariable_ty.ptr_to(), "__llmatch"); diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 2f0f373325a..e273a56ce02 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -287,8 +287,11 @@ pub enum PointerField { FatPointer(uint) } +impl Copy for PointerField {} + impl<'tcx> Case<'tcx> { - fn is_zerolen<'a>(&self, cx: &CrateContext<'a, 'tcx>, scapegoat: Ty<'tcx>) -> bool { + fn is_zerolen<'a>(&self, cx: &CrateContext<'a, 'tcx>, scapegoat: Ty<'tcx>) + -> bool { mk_struct(cx, self.tys.as_slice(), false, scapegoat).size == 0 } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 3090119788c..cef12616cf2 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -90,6 +90,7 @@ use libc::{c_uint, uint64_t}; use std::c_str::ToCStr; use std::cell::{Cell, RefCell}; use std::collections::HashSet; +use std::mem; use std::rc::Rc; use std::{i8, i16, i32, i64}; use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi}; @@ -562,6 +563,8 @@ pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) { // Used only for creating scalar comparison glue. pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, } +impl Copy for scalar_type {} + pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, @@ -813,7 +816,10 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, in iter_structural_ty") } } - _ => cx.sess().unimpl("type in iter_structural_ty") + _ => { + cx.sess().unimpl(format!("type in iter_structural_ty: {}", + ty_to_string(cx.tcx(), t)).as_slice()) + } } return cx; } @@ -1778,6 +1784,14 @@ pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, } } +#[deriving(Clone, Eq, PartialEq)] +pub enum IsUnboxedClosureFlag { + NotUnboxedClosure, + IsUnboxedClosure, +} + +impl Copy for IsUnboxedClosureFlag {} + // trans_closure: Builds an LLVM function out of a source function. // If the function closes over its environment a closure will be // returned. @@ -2182,6 +2196,8 @@ pub enum ValueOrigin { InlinedCopy, } +impl Copy for ValueOrigin {} + /// Set the appropriate linkage for an LLVM `ValueRef` (function or global). /// If the `llval` is the direct translation of a specific Rust item, `id` /// should be set to the `NodeId` of that item. (This mapping should be @@ -3036,7 +3052,11 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { fn next(&mut self) -> Option { let old = self.cur; if !old.is_null() { - self.cur = unsafe { (self.step)(old) }; + self.cur = unsafe { + let step: unsafe extern "C" fn(ValueRef) -> ValueRef = + mem::transmute_copy(&self.step); + step(old) + }; Some(old) } else { None diff --git a/src/librustc_trans/trans/basic_block.rs b/src/librustc_trans/trans/basic_block.rs index 328c8e616c4..b55c268d9a9 100644 --- a/src/librustc_trans/trans/basic_block.rs +++ b/src/librustc_trans/trans/basic_block.rs @@ -15,6 +15,8 @@ use std::iter::{Filter, Map}; pub struct BasicBlock(pub BasicBlockRef); +impl Copy for BasicBlock {} + pub type Preds<'a> = Map<'a, Value, BasicBlock, Filter<'a, Value, Users>>; /// Wrapper for LLVM BasicBlockRef diff --git a/src/librustc_trans/trans/cabi.rs b/src/librustc_trans/trans/cabi.rs index 518b0ba73f8..7aabd998f7a 100644 --- a/src/librustc_trans/trans/cabi.rs +++ b/src/librustc_trans/trans/cabi.rs @@ -31,6 +31,8 @@ pub enum ArgKind { Ignore, } +impl Copy for ArgKind {} + /// Information about how a specific C type /// should be passed to or returned from a function /// @@ -48,6 +50,8 @@ pub struct ArgType { pub attr: option::Option } +impl Copy for ArgType {} + impl ArgType { pub fn direct(ty: Type, cast: option::Option, pad: option::Option, diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs index 69ee5301d18..00c91ddebb3 100644 --- a/src/librustc_trans/trans/cabi_x86_64.rs +++ b/src/librustc_trans/trans/cabi_x86_64.rs @@ -40,6 +40,8 @@ enum RegClass { Memory } +impl Copy for RegClass {} + trait TypeMethods { fn is_reg_ty(&self) -> bool; } diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 746109ef113..ff7ab91c39a 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -63,6 +63,8 @@ pub struct MethodData { pub llself: ValueRef, } +impl Copy for MethodData {} + pub enum CalleeData<'tcx> { Closure(Datum<'tcx, Lvalue>), @@ -1200,6 +1202,8 @@ pub enum AutorefArg { DoAutorefArg(ast::NodeId) } +impl Copy for AutorefArg {} + pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, formal_arg_ty: Ty<'tcx>, arg_datum: Datum<'tcx, Expr>, diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index 33393ba76c5..ba3e70fe036 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -55,6 +55,8 @@ pub struct CustomScopeIndex { index: uint } +impl Copy for CustomScopeIndex {} + pub const EXIT_BREAK: uint = 0; pub const EXIT_LOOP: uint = 1; pub const EXIT_MAX: uint = 2; @@ -88,11 +90,15 @@ pub enum EarlyExitLabel { LoopExit(ast::NodeId, uint) } +impl Copy for EarlyExitLabel {} + pub struct CachedEarlyExit { label: EarlyExitLabel, cleanup_block: BasicBlockRef, } +impl Copy for CachedEarlyExit {} + pub trait Cleanup<'tcx> { fn must_unwind(&self) -> bool; fn clean_on_unwind(&self) -> bool; @@ -111,6 +117,8 @@ pub enum ScopeId { CustomScope(CustomScopeIndex) } +impl Copy for ScopeId {} + impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// Invoked when we start to trans the code contained within a new cleanup scope. fn push_ast_cleanup_scope(&self, debug_loc: NodeInfo) { @@ -876,6 +884,8 @@ pub struct DropValue<'tcx> { zero: bool } +impl<'tcx> Copy for DropValue<'tcx> {} + impl<'tcx> Cleanup<'tcx> for DropValue<'tcx> { fn must_unwind(&self) -> bool { self.must_unwind @@ -910,12 +920,16 @@ pub enum Heap { HeapExchange } +impl Copy for Heap {} + pub struct FreeValue<'tcx> { ptr: ValueRef, heap: Heap, content_ty: Ty<'tcx> } +impl<'tcx> Copy for FreeValue<'tcx> {} + impl<'tcx> Cleanup<'tcx> for FreeValue<'tcx> { fn must_unwind(&self) -> bool { true @@ -950,6 +964,8 @@ pub struct FreeSlice { heap: Heap, } +impl Copy for FreeSlice {} + impl<'tcx> Cleanup<'tcx> for FreeSlice { fn must_unwind(&self) -> bool { true @@ -981,6 +997,8 @@ pub struct LifetimeEnd { ptr: ValueRef, } +impl Copy for LifetimeEnd {} + impl<'tcx> Cleanup<'tcx> for LifetimeEnd { fn must_unwind(&self) -> bool { false diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index bb4df00bd94..b03f5ff8ecc 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -107,6 +107,8 @@ pub struct EnvValue<'tcx> { datum: Datum<'tcx, Lvalue> } +impl<'tcx> Copy for EnvValue<'tcx> {} + impl<'tcx> EnvValue<'tcx> { pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String { format!("{}({})", self.action, self.datum.to_string(ccx)) diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index a8256176c26..77412b00299 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -127,6 +127,8 @@ pub struct tydesc_info<'tcx> { pub name: ValueRef, } +impl<'tcx> Copy for tydesc_info<'tcx> {} + /* * A note on nomenclature of linking: "extern", "foreign", and "upcall". * @@ -158,6 +160,8 @@ pub struct NodeInfo { pub span: Span, } +impl Copy for NodeInfo {} + pub fn expr_info(expr: &ast::Expr) -> NodeInfo { NodeInfo { id: expr.id, span: expr.span } } @@ -867,10 +871,11 @@ pub enum ExprOrMethodCall { MethodCall(ty::MethodCall) } +impl Copy for ExprOrMethodCall {} + pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, node: ExprOrMethodCall) - -> subst::Substs<'tcx> -{ + -> subst::Substs<'tcx> { let tcx = bcx.tcx(); let substs = match node { diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 532ef690818..23a261842b2 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -46,6 +46,8 @@ pub struct Datum<'tcx, K> { pub kind: K, } +impl<'tcx,K:Copy> Copy for Datum<'tcx,K> {} + pub struct DatumBlock<'blk, 'tcx: 'blk, K> { pub bcx: Block<'blk, 'tcx>, pub datum: Datum<'tcx, K>, @@ -66,6 +68,8 @@ pub enum Expr { #[deriving(Clone, Show)] pub struct Lvalue; +impl Copy for Lvalue {} + #[deriving(Show)] pub struct Rvalue { pub mode: RvalueMode @@ -91,6 +95,8 @@ pub enum RvalueMode { ByValue, } +impl Copy for RvalueMode {} + pub fn immediate_rvalue<'tcx>(val: ValueRef, ty: Ty<'tcx>) -> Datum<'tcx, Rvalue> { return Datum::new(val, ty, Rvalue::new(ByValue)); } @@ -529,11 +535,19 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { /// Copies the value into a new location. This function always preserves the existing datum as /// a valid value. Therefore, it does not consume `self` and, also, cannot be applied to affine /// values (since they must never be duplicated). - pub fn shallow_copy<'blk>(&self, - bcx: Block<'blk, 'tcx>, - dst: ValueRef) - -> Block<'blk, 'tcx> { - assert!(!ty::type_moves_by_default(bcx.tcx(), self.ty)); + pub fn shallow_copy<'blk, 'tcx>(&self, + bcx: Block<'blk, 'tcx>, + dst: ValueRef) + -> Block<'blk, 'tcx> { + /*! + * Copies the value into a new location. This function always + * preserves the existing datum as a valid value. Therefore, + * it does not consume `self` and, also, cannot be applied to + * affine values (since they must never be duplicated). + */ + + let param_env = ty::empty_parameter_environment(); + assert!(!ty::type_moves_by_default(bcx.tcx(), self.ty, ¶m_env)); self.shallow_copy_raw(bcx, dst) } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 6c75086fec6..88a66320c0e 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -251,6 +251,8 @@ static FLAGS_NONE: c_uint = 0; #[deriving(Show, Hash, Eq, PartialEq, Clone)] struct UniqueTypeId(ast::Name); +impl Copy for UniqueTypeId {} + // The TypeMap is where the CrateDebugContext holds the type metadata nodes // created so far. The metadata nodes are indexed by UniqueTypeId, and, for // faster lookup, also by Ty. The TypeMap is responsible for creating @@ -2323,6 +2325,8 @@ enum EnumDiscriminantInfo { NoDiscriminant } +impl Copy for EnumDiscriminantInfo {} + // Returns a tuple of (1) type_metadata_stub of the variant, (2) the llvm_type // of the variant, and (3) a MemberDescriptionFactory for producing the // descriptions of the fields of the variant. This is a rudimentary version of a @@ -3048,6 +3052,8 @@ enum DebugLocation { UnknownLocation } +impl Copy for DebugLocation {} + impl DebugLocation { fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation { KnownLocation { diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index d130dc0a55b..e3e6fff7234 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -79,6 +79,8 @@ pub enum Dest { Ignore, } +impl Copy for Dest {} + impl Dest { pub fn to_string(&self, ccx: &CrateContext) -> String { match *self { @@ -1882,6 +1884,8 @@ pub enum cast_kind { cast_other, } +impl Copy for cast_kind {} + pub fn cast_type_kind<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> cast_kind { match t.sty { ty::ty_char => cast_integral, diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index c00c477f4b8..9234dfc48bd 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -59,6 +59,8 @@ pub struct ModuleTranslation { pub llmod: ModuleRef, } +impl Copy for ModuleTranslation {} + pub struct CrateTranslation { pub modules: Vec, pub metadata_module: ModuleTranslation, diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 00f938191f8..18ea8055a4e 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -96,6 +96,8 @@ pub struct VecTypes<'tcx> { pub llunit_alloc_size: u64 } +impl<'tcx> Copy for VecTypes<'tcx> {} + impl<'tcx> VecTypes<'tcx> { pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String { format!("VecTypes {{unit_ty={}, llunit_ty={}, \ @@ -301,8 +303,6 @@ pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 1 => expr::trans_into(bcx, &**element, SaveIn(lldest)), count => { let elem = unpack_datum!(bcx, expr::trans(bcx, &**element)); - assert!(!ty::type_moves_by_default(bcx.tcx(), elem.ty)); - let bcx = iter_vec_loop(bcx, lldest, vt, C_uint(bcx.ccx(), count), |set_bcx, lleltptr, _| { diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index 8bff7602ddc..387af7390b2 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -31,6 +31,8 @@ pub struct Type { rf: TypeRef } +impl Copy for Type {} + macro_rules! ty ( ($e:expr) => ( Type::from_ref(unsafe { $e })) ) diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 005f6ca4c70..adc919c91bf 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -449,12 +449,13 @@ pub enum named_ty { an_unboxed_closure, } +impl Copy for named_ty {} + pub fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, what: named_ty, did: ast::DefId, tps: &[Ty<'tcx>]) - -> String -{ + -> String { let name = match what { a_struct => "struct", an_enum => "enum", diff --git a/src/librustc_trans/trans/value.rs b/src/librustc_trans/trans/value.rs index 33ea239412a..fa06e039023 100644 --- a/src/librustc_trans/trans/value.rs +++ b/src/librustc_trans/trans/value.rs @@ -16,6 +16,8 @@ use libc::c_uint; pub struct Value(pub ValueRef); +impl Copy for Value {} + macro_rules! opt_val ( ($e:expr) => ( unsafe { match $e { @@ -123,9 +125,14 @@ impl Value { } } +/// Wrapper for LLVM UseRef pub struct Use(UseRef); -/// Wrapper for LLVM UseRef +impl Copy for Use {} + +/** + * Wrapper for LLVM UseRef + */ impl Use { pub fn get(&self) -> UseRef { let Use(v) = *self; v @@ -148,6 +155,7 @@ impl Use { } /// Iterator for the users of a value +#[allow(missing_copy_implementations)] pub struct Users { next: Option } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f87a4c9294b..b6c9d8b2d21 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -52,6 +52,8 @@ pub enum CandidateSource { TraitSource(/* trait id */ ast::DefId), } +impl Copy for CandidateSource {} + type MethodIndex = uint; // just for doc purposes /// Determines whether the type `self_ty` supports a method name `method_name` or not. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index cdf34c7f4d2..e42c9c20011 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -209,6 +209,8 @@ enum Expectation<'tcx> { ExpectCastableToType(Ty<'tcx>), } +impl<'tcx> Copy for Expectation<'tcx> {} + #[deriving(Clone)] pub struct FnStyleState { pub def: ast::NodeId, @@ -216,6 +218,8 @@ pub struct FnStyleState { from_fn: bool } +impl Copy for FnStyleState {} + impl FnStyleState { pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState { FnStyleState { def: def, fn_style: fn_style, from_fn: true } @@ -2117,6 +2121,8 @@ pub enum LvaluePreference { NoPreference } +impl Copy for LvaluePreference {} + /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide /// whether to terminate the loop. Returns the final type and number of derefs that it performed. /// @@ -2993,6 +2999,8 @@ pub enum DerefArgs { DoDerefArgs } +impl Copy for DerefArgs {} + /// Controls whether the arguments are tupled. This is used for the call /// operator. /// diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 1769c588ec1..a011982a1fc 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -203,6 +203,11 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { } } + if fcx.tcx().lang_items.copy_trait() == Some(trait_ref.def_id) { + // This is checked in coherence. + return + } + // We are stricter on the trait-ref in an impl than the // self-type. In particular, we enforce region // relationships. The reason for this is that (at least diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 777f354bec1..48f1ef8da1d 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -354,6 +354,8 @@ enum ResolveReason { ResolvingUnboxedClosure(ast::DefId), } +impl Copy for ResolveReason {} + impl ResolveReason { fn span(&self, tcx: &ty::ctxt) -> Span { match *self { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index b8642ddde40..578ed916541 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -18,17 +18,15 @@ use metadata::csearch::{each_impl, get_impl_trait}; use metadata::csearch; -use middle::subst; +use middle::subst::{mod, Subst}; use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId}; -use middle::ty::{TypeTraitItemId, lookup_item_type}; -use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err}; -use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open}; +use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type}; +use middle::ty::{Ty, ty_bool, ty_char, ty_closure, ty_enum, ty_err}; use middle::ty::{ty_param, Polytype, ty_ptr}; use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup}; +use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open}; use middle::ty::{ty_uint, ty_unboxed_closure, ty_uniq, ty_bare_fn}; -use middle::ty::{ty_closure}; -use middle::ty::type_is_ty_var; -use middle::subst::Subst; +use middle::ty::{type_is_ty_var}; use middle::ty; use CrateCtxt; use middle::infer::combine::Combine; @@ -190,6 +188,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // do this here, but it's actually the most convenient place, since // the coherence tables contain the trait -> type mappings. self.populate_destructor_table(); + + // Check to make sure implementations of `Copy` are legal. + self.check_implementations_of_copy(); } fn check_implementation(&self, @@ -474,6 +475,71 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } } } + + /// Ensures that implementations of the built-in trait `Copy` are legal. + fn check_implementations_of_copy(&self) { + let tcx = self.crate_context.tcx; + let copy_trait = match tcx.lang_items.copy_trait() { + Some(id) => id, + None => return, + }; + + let trait_impls = match tcx.trait_impls + .borrow() + .get(©_trait) + .cloned() { + None => { + debug!("check_implementations_of_copy(): no types with \ + implementations of `Copy` found"); + return + } + Some(found_impls) => found_impls + }; + + // Clone first to avoid a double borrow error. + let trait_impls = trait_impls.borrow().clone(); + + for &impl_did in trait_impls.iter() { + if impl_did.krate != ast::LOCAL_CRATE { + debug!("check_implementations_of_copy(): impl not in this \ + crate"); + continue + } + + let self_type = self.get_self_type_for_implementation(impl_did); + let span = tcx.map.span(impl_did.node); + let param_env = ParameterEnvironment::for_item(tcx, + impl_did.node); + let self_type = self_type.ty.subst(tcx, ¶m_env.free_substs); + + match ty::can_type_implement_copy(tcx, self_type, ¶m_env) { + Ok(()) => {} + Err(ty::FieldDoesNotImplementCopy(name)) => { + tcx.sess + .span_err(span, + format!("the trait `Copy` may not be \ + implemented for this type; field \ + `{}` does not implement `Copy`", + token::get_name(name)).as_slice()) + } + Err(ty::VariantDoesNotImplementCopy(name)) => { + tcx.sess + .span_err(span, + format!("the trait `Copy` may not be \ + implemented for this type; variant \ + `{}` does not implement `Copy`", + token::get_name(name)).as_slice()) + } + Err(ty::TypeIsStructural) => { + tcx.sess + .span_err(span, + "the trait `Copy` may not be implemented \ + for this type; type is not a structure or \ + enumeration") + } + } + } + } } fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 717e886029a..74ac9c480de 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -499,6 +499,8 @@ enum ConvertMethodContext<'a> { TraitConvertMethodContext(ast::DefId, &'a [ast::TraitItem]), } +impl<'a> Copy for ConvertMethodContext<'a> {} + fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, convert_method_context: ConvertMethodContext, container: ImplOrTraitItemContainer, diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs index 3bca24f479f..39c7a87837c 100644 --- a/src/librustc_typeck/rscope.rs +++ b/src/librustc_typeck/rscope.rs @@ -38,6 +38,8 @@ pub trait RegionScope { // for types that appear in structs and so on. pub struct ExplicitRscope; +impl Copy for ExplicitRscope {} + impl RegionScope for ExplicitRscope { fn default_region_bound(&self, _span: Span) -> Option { None @@ -77,6 +79,7 @@ impl RegionScope for UnelidableRscope { // A scope in which any omitted region defaults to `default`. This is // used after the `->` in function signatures, but also for backwards // compatibility with object types. The latter use may go away. +#[allow(missing_copy_implementations)] pub struct SpecificRscope { default: ty::Region } diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index ade3144ce41..56f974ad665 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -232,12 +232,16 @@ type VarianceTermPtr<'a> = &'a VarianceTerm<'a>; #[deriving(Show)] struct InferredIndex(uint); +impl Copy for InferredIndex {} + enum VarianceTerm<'a> { ConstantTerm(ty::Variance), TransformTerm(VarianceTermPtr<'a>, VarianceTermPtr<'a>), InferredTerm(InferredIndex), } +impl<'a> Copy for VarianceTerm<'a> {} + impl<'a> fmt::Show for VarianceTerm<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -270,6 +274,8 @@ enum ParamKind { RegionParam } +impl Copy for ParamKind {} + struct InferredInfo<'a> { item_id: ast::NodeId, kind: ParamKind, @@ -426,6 +432,8 @@ struct Constraint<'a> { variance: &'a VarianceTerm<'a>, } +impl<'a> Copy for Constraint<'a> {} + fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>, krate: &ast::Crate) -> ConstraintContext<'a, 'tcx> { @@ -1015,7 +1023,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { while index < num_inferred && inferred_infos[index].item_id == item_id { - let info = inferred_infos[index]; + let info = &inferred_infos[index]; let variance = solutions[index]; debug!("Index {} Info {} / {} / {} Variance {}", index, info.index, info.kind, info.space, variance); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bc870d39c5d..df7b922bd1a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1178,6 +1178,8 @@ pub enum PrimitiveType { PrimitiveTuple, } +impl Copy for PrimitiveType {} + #[deriving(Clone, Encodable, Decodable)] pub enum TypeKind { TypeEnum, @@ -1190,6 +1192,8 @@ pub enum TypeKind { TypeTypedef, } +impl Copy for TypeKind {} + impl PrimitiveType { fn from_str(s: &str) -> Option { match s.as_slice() { @@ -1843,6 +1847,8 @@ pub enum Mutability { Immutable, } +impl Copy for Mutability {} + impl Clean for ast::Mutability { fn clean(&self, _: &DocContext) -> Mutability { match self { diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index adfd9aa8213..1aac91c4a5c 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -82,6 +82,8 @@ pub enum StructType { Unit } +impl Copy for StructType {} + pub enum TypeBound { RegionBound, TraitBound(ast::TraitRef) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0fca59962d4..68ff2ddbcb0 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -48,6 +48,11 @@ pub struct WhereClause<'a>(pub &'a clean::Generics); /// Wrapper struct for emitting type parameter bounds. pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]); +impl Copy for VisSpace {} +impl Copy for FnStyleSpace {} +impl Copy for MutableSpace {} +impl Copy for RawMutableSpace {} + impl VisSpace { pub fn get(&self) -> Option { let VisSpace(v) = *self; v diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 0ad12b957ba..86787e5c805 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -41,6 +41,8 @@ pub enum ItemType { Constant = 18, } +impl Copy for ItemType {} + impl ItemType { pub fn from_item(item: &clean::Item) -> ItemType { match item.inner { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index dab25c3b2ee..296493f3ba3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -225,7 +225,13 @@ struct Source<'a>(&'a str); // Helper structs for rendering items/sidebars and carrying along contextual // information -struct Item<'a> { cx: &'a Context, item: &'a clean::Item, } +struct Item<'a> { + cx: &'a Context, + item: &'a clean::Item, +} + +impl<'a> Copy for Item<'a> {} + struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, } /// Struct representing one entry in the JS search index. These are all emitted diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs index 42f4c2a0ca6..881270afe14 100644 --- a/src/librustdoc/stability_summary.rs +++ b/src/librustdoc/stability_summary.rs @@ -39,6 +39,8 @@ pub struct Counts { pub unmarked: uint, } +impl Copy for Counts {} + impl Add for Counts { fn add(&self, other: &Counts) -> Counts { Counts { diff --git a/src/librustrt/bookkeeping.rs b/src/librustrt/bookkeeping.rs index 714bbd569bd..e918a496d55 100644 --- a/src/librustrt/bookkeeping.rs +++ b/src/librustrt/bookkeeping.rs @@ -26,6 +26,7 @@ use mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; static TASK_COUNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; static TASK_LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT; +#[allow(missing_copy_implementations)] pub struct Token { _private: () } impl Drop for Token { diff --git a/src/librustrt/c_str.rs b/src/librustrt/c_str.rs index 261bd1b9f8c..07094f08c5d 100644 --- a/src/librustrt/c_str.rs +++ b/src/librustrt/c_str.rs @@ -85,6 +85,7 @@ use libc; /// /// This structure wraps a `*libc::c_char`, and will automatically free the /// memory it is pointing to when it goes out of scope. +#[allow(missing_copy_implementations)] pub struct CString { buf: *const libc::c_char, owns_buffer_: bool, diff --git a/src/librustrt/mutex.rs b/src/librustrt/mutex.rs index 2f0daf8f6e2..5b58ec8fd3a 100644 --- a/src/librustrt/mutex.rs +++ b/src/librustrt/mutex.rs @@ -361,6 +361,7 @@ mod imp { #[cfg(any(target_os = "macos", target_os = "ios"))] mod os { + use core::kinds::Copy; use libc; #[cfg(target_arch = "x86_64")] @@ -384,12 +385,17 @@ mod imp { __sig: libc::c_long, __opaque: [u8, ..__PTHREAD_MUTEX_SIZE__], } + + impl Copy for pthread_mutex_t {} + #[repr(C)] pub struct pthread_cond_t { __sig: libc::c_long, __opaque: [u8, ..__PTHREAD_COND_SIZE__], } + impl Copy for pthread_cond_t {} + pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __sig: _PTHREAD_MUTEX_SIG_INIT, __opaque: [0, ..__PTHREAD_MUTEX_SIZE__], @@ -402,6 +408,7 @@ mod imp { #[cfg(target_os = "linux")] mod os { + use core::kinds::Copy; use libc; // minus 8 because we have an 'align' field @@ -431,12 +438,17 @@ mod imp { __align: libc::c_longlong, size: [u8, ..__SIZEOF_PTHREAD_MUTEX_T], } + + impl Copy for pthread_mutex_t {} + #[repr(C)] pub struct pthread_cond_t { __align: libc::c_longlong, size: [u8, ..__SIZEOF_PTHREAD_COND_T], } + impl Copy for pthread_cond_t {} + pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __align: 0, size: [0, ..__SIZEOF_PTHREAD_MUTEX_T], diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs index 697ee95df4c..714d30ae4b1 100644 --- a/src/librustrt/unwind.rs +++ b/src/librustrt/unwind.rs @@ -77,6 +77,7 @@ use task::Task; use libunwind as uw; +#[allow(missing_copy_implementations)] pub struct Unwinder { unwinding: bool, } diff --git a/src/librustrt/util.rs b/src/librustrt/util.rs index c77fbd4aee0..fd30c3a48d2 100644 --- a/src/librustrt/util.rs +++ b/src/librustrt/util.rs @@ -29,6 +29,9 @@ pub const ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) || pub struct Stdio(libc::c_int); #[allow(non_upper_case_globals)] +impl Copy for Stdio {} + +#[allow(non_uppercase_statics)] pub const Stdout: Stdio = Stdio(libc::STDOUT_FILENO); #[allow(non_upper_case_globals)] pub const Stderr: Stdio = Stdio(libc::STDERR_FILENO); diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index c8ec1700a1d..dd5039c9b82 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -26,6 +26,8 @@ pub enum CharacterSet { UrlSafe } +impl Copy for CharacterSet {} + /// Contains configuration parameters for `to_base64`. pub struct Config { /// Character set to use @@ -36,6 +38,8 @@ pub struct Config { pub line_length: Option } +impl Copy for Config {} + /// Configuration for RFC 4648 standard base64 encoding pub static STANDARD: Config = Config {char_set: Standard, pad: true, line_length: None}; @@ -168,6 +172,8 @@ pub enum FromBase64Error { InvalidBase64Length, } +impl Copy for FromBase64Error {} + impl fmt::Show for FromBase64Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index 4c20f72cac5..22392056ddf 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -68,6 +68,8 @@ pub enum FromHexError { InvalidHexLength, } +impl Copy for FromHexError {} + impl fmt::Show for FromHexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 248d78236ad..318c21234f5 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -247,6 +247,8 @@ pub enum ErrorCode { NotUtf8, } +impl Copy for ErrorCode {} + #[deriving(Clone, PartialEq, Show)] pub enum ParserError { /// msg, line, col @@ -254,6 +256,8 @@ pub enum ParserError { IoError(io::IoErrorKind, &'static str), } +impl Copy for ParserError {} + // Builder and Parser have the same errors. pub type BuilderError = ParserError; diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 2872f74cf88..23eb367dbd1 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -18,6 +18,7 @@ use core::kinds::Sized; use fmt; use iter::IteratorExt; +use kinds::Copy; use mem; use option::Option; use option::Option::{Some, None}; @@ -30,6 +31,8 @@ use vec::Vec; #[deriving(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)] pub struct Ascii { chr: u8 } +impl Copy for Ascii {} + impl Ascii { /// Converts an ascii character into a `u8`. #[inline] diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index 8a90c06f038..ffcd6505dad 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -33,6 +33,8 @@ /// } /// } /// +/// impl Copy for Flags {} +/// /// fn main() { /// let e1 = FLAG_A | FLAG_C; /// let e2 = FLAG_B | FLAG_C; @@ -55,6 +57,8 @@ /// } /// } /// +/// impl Copy for Flags {} +/// /// impl Flags { /// pub fn clear(&mut self) { /// self.bits = 0; // The `bits` field can be accessed from within the @@ -260,6 +264,7 @@ macro_rules! bitflags { #[cfg(test)] #[allow(non_upper_case_globals)] mod tests { + use kinds::Copy; use hash; use option::Option::{Some, None}; use ops::{BitOr, BitAnd, BitXor, Sub, Not}; @@ -283,12 +288,16 @@ mod tests { } } + impl Copy for Flags {} + bitflags! { flags AnotherSetOfFlags: i8 { const AnotherFlag = -1_i8, } } + impl Copy for AnotherSetOfFlags {} + #[test] fn test_bits(){ assert_eq!(Flags::empty().bits(), 0x00000000); diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index de06a1e0bbd..ef4cabedc47 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -16,7 +16,7 @@ use clone::Clone; use cmp; use hash::{Hash, Hasher}; use iter::{Iterator, count}; -use kinds::{Sized, marker}; +use kinds::{Copy, Sized, marker}; use mem::{min_align_of, size_of}; use mem; use num::{Int, UnsignedInt}; @@ -81,12 +81,16 @@ struct RawBucket { val: *mut V } +impl Copy for RawBucket {} + pub struct Bucket { raw: RawBucket, idx: uint, table: M } +impl Copy for Bucket {} + pub struct EmptyBucket { raw: RawBucket, idx: uint, diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index d291ed72567..6cff5a3dd23 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -405,6 +405,8 @@ pub enum TryRecvError { Disconnected, } +impl Copy for TryRecvError {} + /// This enumeration is the list of the possible error outcomes for the /// `SyncSender::try_send` method. #[deriving(PartialEq, Clone, Show)] diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index aa0c8b53c2e..5609fbf16cd 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -29,7 +29,10 @@ use str; use string::String; use vec::Vec; -pub struct DynamicLibrary { handle: *mut u8 } +#[allow(missing_copy_implementations)] +pub struct DynamicLibrary { + handle: *mut u8 +} impl Drop for DynamicLibrary { fn drop(&mut self) { @@ -210,6 +213,7 @@ pub mod dl { use c_str::{CString, ToCStr}; use libc; + use kinds::Copy; use ptr; use result::*; use string::String; @@ -262,6 +266,8 @@ pub mod dl { Local = 0, } + impl Copy for Rtld {} + #[link_name = "dl"] extern { fn dlopen(filename: *const libc::c_char, diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index d43a7a66c5b..dc212e7cab3 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -231,6 +231,7 @@ use error::{FromError, Error}; use fmt; use int; use iter::{Iterator, IteratorExt}; +use kinds::Copy; use mem::transmute; use ops::{BitOr, BitXor, BitAnd, Sub, Not}; use option::Option; @@ -420,6 +421,8 @@ pub enum IoErrorKind { NoProgress, } +impl Copy for IoErrorKind {} + /// A trait that lets you add a `detail` to an IoError easily trait UpdateIoError { /// Returns an IoError with updated description and detail @@ -1560,6 +1563,8 @@ pub enum SeekStyle { SeekCur, } +impl Copy for SeekStyle {} + /// An object implementing `Seek` internally has some form of cursor which can /// be moved within a stream of bytes. The stream typically has a fixed size, /// allowing seeking relative to either end. @@ -1682,6 +1687,8 @@ pub enum FileMode { Truncate, } +impl Copy for FileMode {} + /// Access permissions with which the file should be opened. `File`s /// opened with `Read` will return an error if written to. pub enum FileAccess { @@ -1693,6 +1700,8 @@ pub enum FileAccess { ReadWrite, } +impl Copy for FileAccess {} + /// Different kinds of files which can be identified by a call to stat #[deriving(PartialEq, Show, Hash, Clone)] pub enum FileType { @@ -1715,6 +1724,8 @@ pub enum FileType { Unknown, } +impl Copy for FileType {} + /// A structure used to describe metadata information about a file. This /// structure is created through the `stat` method on a `Path`. /// @@ -1766,6 +1777,8 @@ pub struct FileStat { pub unstable: UnstableFileStat, } +impl Copy for FileStat {} + /// This structure represents all of the possible information which can be /// returned from a `stat` syscall which is not contained in the `FileStat` /// structure. This information is not necessarily platform independent, and may @@ -1795,6 +1808,8 @@ pub struct UnstableFileStat { pub gen: u64, } +impl Copy for UnstableFileStat {} + bitflags! { #[doc = "A set of permissions for a file or directory is represented"] #[doc = "by a set of flags which are or'd together."] @@ -1889,6 +1904,8 @@ bitflags! { } } +impl Copy for FilePermission {} + impl Default for FilePermission { #[inline] fn default() -> FilePermission { FilePermission::empty() } diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index fea8372733c..fc81ab7b57a 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -22,6 +22,7 @@ pub use self::Protocol::*; use iter::IteratorExt; use io::{IoResult}; use io::net::ip::{SocketAddr, IpAddr}; +use kinds::Copy; use option::Option; use option::Option::{Some, None}; use sys; @@ -32,6 +33,8 @@ pub enum SocketType { Stream, Datagram, Raw } +impl Copy for SocketType {} + /// Flags which can be or'd into the `flags` field of a `Hint`. These are used /// to manipulate how a query is performed. /// @@ -46,12 +49,16 @@ pub enum Flag { V4Mapped, } +impl Copy for Flag {} + /// A transport protocol associated with either a hint or a return value of /// `lookup` pub enum Protocol { TCP, UDP } +impl Copy for Protocol {} + /// This structure is used to provide hints when fetching addresses for a /// remote host to control how the lookup is performed. /// @@ -64,6 +71,8 @@ pub struct Hint { pub flags: uint, } +impl Copy for Hint {} + pub struct Info { pub address: SocketAddr, pub family: uint, @@ -72,6 +81,8 @@ pub struct Info { pub flags: uint, } +impl Copy for Info {} + /// Easy name resolution. Given a hostname, returns the list of IP addresses for /// that hostname. pub fn get_host_addresses(host: &str) -> IoResult> { diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index 3fa6f4a6091..f59dd37c0da 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -18,6 +18,7 @@ pub use self::IpAddr::*; use fmt; +use kinds::Copy; use io::{mod, IoResult, IoError}; use io::net; use iter::{Iterator, IteratorExt}; @@ -36,6 +37,8 @@ pub enum IpAddr { Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16) } +impl Copy for IpAddr {} + impl fmt::Show for IpAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -67,6 +70,8 @@ pub struct SocketAddr { pub port: Port, } +impl Copy for SocketAddr {} + impl fmt::Show for SocketAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.ip { diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 61ebfb06c71..c46a6e82e44 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -480,6 +480,8 @@ pub enum StdioContainer { CreatePipe(bool /* readable */, bool /* writable */), } +impl Copy for StdioContainer {} + /// Describes the result of a process after it has terminated. /// Note that Windows have no signals, so the result is usually ExitStatus. #[deriving(PartialEq, Eq, Clone)] @@ -491,6 +493,8 @@ pub enum ProcessExit { ExitSignal(int), } +impl Copy for ProcessExit {} + impl fmt::Show for ProcessExit { /// Format a ProcessExit enum, to nicely present the information. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index e78bd1dd33f..faa52226a03 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -83,6 +83,8 @@ impl Buffer for LimitReader { /// A `Writer` which ignores bytes written to it, like /dev/null. pub struct NullWriter; +impl Copy for NullWriter {} + impl Writer for NullWriter { #[inline] fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> { Ok(()) } @@ -91,6 +93,8 @@ impl Writer for NullWriter { /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero. pub struct ZeroReader; +impl Copy for ZeroReader {} + impl Reader for ZeroReader { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::IoResult { @@ -111,6 +115,8 @@ impl Buffer for ZeroReader { /// A `Reader` which is always at EOF, like /dev/null. pub struct NullReader; +impl Copy for NullReader {} + impl Reader for NullReader { #[inline] fn read(&mut self, _buf: &mut [u8]) -> io::IoResult { diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index c87f40f351b..1c9826ff5ac 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -18,6 +18,7 @@ pub use self::SignFormat::*; use char; use char::Char; +use kinds::Copy; use num; use num::{Int, Float, FPNaN, FPInfinite, ToPrimitive}; use slice::{SlicePrelude, CloneSliceAllocPrelude}; @@ -38,6 +39,8 @@ pub enum ExponentFormat { ExpBin, } +impl Copy for ExponentFormat {} + /// The number of digits used for emitting the fractional part of a number, if /// any. pub enum SignificantDigits { @@ -55,6 +58,8 @@ pub enum SignificantDigits { DigExact(uint) } +impl Copy for SignificantDigits {} + /// How to emit the sign of a number. pub enum SignFormat { /// No sign will be printed. The exponent sign will also be emitted. @@ -67,25 +72,33 @@ pub enum SignFormat { SignAll, } -/// Converts an integral number to its string representation as a byte vector. -/// This is meant to be a common base implementation for all integral string -/// conversion functions like `to_string()` or `to_str_radix()`. -/// -/// # Arguments -/// -/// - `num` - The number to convert. Accepts any number that -/// implements the numeric traits. -/// - `radix` - Base to use. Accepts only the values 2-36. -/// - `sign` - How to emit the sign. Options are: -/// - `SignNone`: No sign at all. Basically emits `abs(num)`. -/// - `SignNeg`: Only `-` on negative values. -/// - `SignAll`: Both `+` on positive, and `-` on negative numbers. -/// - `f` - a callback which will be invoked for each ascii character -/// which composes the string representation of this integer -/// -/// # Panics -/// -/// - Panics if `radix` < 2 or `radix` > 36. +impl Copy for SignFormat {} + +/** + * Converts an integral number to its string representation as a byte vector. + * This is meant to be a common base implementation for all integral string + * conversion functions like `to_string()` or `to_str_radix()`. + * + * # Arguments + * - `num` - The number to convert. Accepts any number that + * implements the numeric traits. + * - `radix` - Base to use. Accepts only the values 2-36. + * - `sign` - How to emit the sign. Options are: + * - `SignNone`: No sign at all. Basically emits `abs(num)`. + * - `SignNeg`: Only `-` on negative values. + * - `SignAll`: Both `+` on positive, and `-` on negative numbers. + * - `f` - a callback which will be invoked for each ascii character + * which composes the string representation of this integer + * + * # Return value + * A tuple containing the byte vector, and a boolean flag indicating + * whether it represents a special value like `inf`, `-inf`, `NaN` or not. + * It returns a tuple because there can be ambiguity between a special value + * and a number representation at higher bases. + * + * # Failure + * - Fails if `radix` < 2 or `radix` > 36. + */ fn int_to_str_bytes_common(num: T, radix: uint, sign: SignFormat, f: |u8|) { assert!(2 <= radix && radix <= 36); diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 2b904acb565..f298ec74f6a 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -36,6 +36,7 @@ use error::{FromError, Error}; use fmt; use io::{IoResult, IoError}; use iter::{Iterator, IteratorExt}; +use kinds::Copy; use libc::{c_void, c_int}; use libc; use boxed::Box; @@ -619,6 +620,8 @@ pub struct Pipe { pub writer: c_int, } +impl Copy for Pipe {} + /// Creates a new low-level OS in-memory pipe. /// /// This function can fail to succeed if there are no more resources available @@ -1185,6 +1188,9 @@ pub struct MemoryMap { kind: MemoryMapKind, } +#[cfg(not(stage0))] +impl Copy for MemoryMap {} + /// Type of memory map pub enum MemoryMapKind { /// Virtual memory map. Usually used to change the permissions of a given @@ -1196,6 +1202,8 @@ pub enum MemoryMapKind { MapVirtual } +impl Copy for MemoryMapKind {} + /// Options the memory map is created with pub enum MapOption { /// The memory should be readable @@ -1219,6 +1227,8 @@ pub enum MapOption { MapNonStandardFlags(c_int), } +impl Copy for MapOption {} + /// Possible errors when creating a map. pub enum MapError { /// ## The following are POSIX-specific @@ -1264,6 +1274,8 @@ pub enum MapError { ErrMapViewOfFile(uint) } +impl Copy for MapError {} + impl fmt::Show for MapError { fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result { let str = match *self { diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index b53e6b2a5e0..ea522536d22 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -22,6 +22,7 @@ use hash; use io::Writer; use iter::{AdditiveIterator, DoubleEndedIteratorExt, Extend}; use iter::{Iterator, IteratorExt, Map}; +use kinds::Copy; use mem; use option::Option; use option::Option::{Some, None}; @@ -985,6 +986,8 @@ pub enum PathPrefix { DiskPrefix } +impl Copy for PathPrefix {} + fn parse_prefix<'a>(mut path: &'a str) -> Option { if path.starts_with("\\\\") { // \\ diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index cc3c46f3610..a359fcf7a9f 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -225,6 +225,7 @@ use cell::RefCell; use clone::Clone; use io::IoResult; use iter::{Iterator, IteratorExt}; +use kinds::Copy; use mem; use rc::Rc; use result::Result::{Ok, Err}; @@ -245,7 +246,11 @@ pub mod reader; /// The standard RNG. This is designed to be efficient on the current /// platform. -pub struct StdRng { rng: IsaacWordRng } +pub struct StdRng { + rng: IsaacWordRng, +} + +impl Copy for StdRng {} impl StdRng { /// Create a randomly seeded instance of `StdRng`. diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 86c3a1fdd32..7e6065129a3 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -13,6 +13,7 @@ #![experimental] use {fmt, i64}; +use kinds::Copy; use ops::{Add, Sub, Mul, Div, Neg}; use option::Option; use option::Option::{Some, None}; @@ -64,6 +65,8 @@ pub const MAX: Duration = Duration { nanos: (i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI }; +impl Copy for Duration {} + impl Duration { /// Makes a new `Duration` with given number of weeks. /// Equivalent to `Duration::seconds(weeks * 7 * 24 * 60 * 60), with overflow checks. diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 87693f39bbd..71d29bca401 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -16,8 +16,17 @@ pub use self::AbiArchitecture::*; use std::fmt; #[deriving(PartialEq)] -pub enum Os { OsWindows, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS, - OsDragonfly } +pub enum Os { + OsWindows, + OsMacos, + OsLinux, + OsAndroid, + OsFreebsd, + OsiOS, + OsDragonfly, +} + +impl Copy for Os {} #[deriving(PartialEq, Eq, Hash, Encodable, Decodable, Clone)] pub enum Abi { @@ -39,6 +48,8 @@ pub enum Abi { RustCall, } +impl Copy for Abi {} + #[allow(non_camel_case_types)] #[deriving(PartialEq)] pub enum Architecture { @@ -49,6 +60,8 @@ pub enum Architecture { Mipsel } +impl Copy for Architecture {} + pub struct AbiData { abi: Abi, @@ -56,6 +69,8 @@ pub struct AbiData { name: &'static str, } +impl Copy for AbiData {} + pub enum AbiArchitecture { /// Not a real ABI (e.g., intrinsic) RustArch, @@ -65,6 +80,9 @@ pub enum AbiArchitecture { Archs(u32) } +#[allow(non_upper_case_globals)] +impl Copy for AbiArchitecture {} + #[allow(non_upper_case_globals)] static AbiDatas: &'static [AbiData] = &[ // Platform-specific ABIs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7e421df505d..0a04a953b31 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -86,6 +86,8 @@ pub struct Ident { pub ctxt: SyntaxContext } +impl Copy for Ident {} + impl Ident { /// Construct an identifier with the given name and an empty context: pub fn new(name: Name) -> Ident { Ident {name: name, ctxt: EMPTY_CTXT}} @@ -161,6 +163,8 @@ pub const ILLEGAL_CTXT : SyntaxContext = 1; #[deriving(Eq, Ord, PartialEq, PartialOrd, Hash, Encodable, Decodable, Clone)] pub struct Name(pub u32); +impl Copy for Name {} + impl Name { pub fn as_str<'a>(&'a self) -> &'a str { unsafe { @@ -204,6 +208,8 @@ pub struct Lifetime { pub name: Name } +impl Copy for Lifetime {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct LifetimeDef { pub lifetime: Lifetime, @@ -338,6 +344,8 @@ pub struct DefId { pub node: NodeId, } +impl Copy for DefId {} + /// Item definitions in the currently-compiled crate would have the CrateNum /// LOCAL_CRATE in their DefId. pub const LOCAL_CRATE: CrateNum = 0; @@ -482,6 +490,8 @@ pub enum BindingMode { BindByValue(Mutability), } +impl Copy for BindingMode {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum PatWildKind { /// Represents the wildcard pattern `_` @@ -491,6 +501,8 @@ pub enum PatWildKind { PatWildMulti, } +impl Copy for PatWildKind {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Pat_ { /// Represents a wildcard pattern (either `_` or `..`) @@ -526,6 +538,8 @@ pub enum Mutability { MutImmutable, } +impl Copy for Mutability {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum BinOp { BiAdd, @@ -548,6 +562,9 @@ pub enum BinOp { BiGt, } +#[cfg(not(stage0))] +impl Copy for BinOp {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum UnOp { UnUniq, @@ -556,6 +573,8 @@ pub enum UnOp { UnNeg } +impl Copy for UnOp {} + pub type Stmt = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] @@ -581,6 +600,8 @@ pub enum LocalSource { LocalFor, } +impl Copy for LocalSource {} + // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. /// Local represents a `let` statement, e.g., `let : = ;` @@ -628,12 +649,16 @@ pub enum BlockCheckMode { UnsafeBlock(UnsafeSource), } +impl Copy for BlockCheckMode {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum UnsafeSource { CompilerGenerated, UserProvided, } +impl Copy for UnsafeSource {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Expr { pub id: NodeId, @@ -718,12 +743,16 @@ pub enum MatchSource { MatchWhileLetDesugar, } +impl Copy for MatchSource {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum CaptureClause { CaptureByValue, CaptureByRef, } +impl Copy for CaptureClause {} + /// A delimited sequence of token trees #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Delimited { @@ -780,6 +809,8 @@ pub enum KleeneOp { OneOrMore, } +impl Copy for KleeneOp {} + /// When the main rust parser encounters a syntax-extension invocation, it /// parses the arguments to the invocation as a token-tree. This is a very /// loose structure, such that all sorts of different AST-fragments can @@ -895,6 +926,8 @@ pub enum StrStyle { RawStr(uint) } +impl Copy for StrStyle {} + pub type Lit = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] @@ -903,7 +936,9 @@ pub enum Sign { Plus } -impl Sign { +impl Copy for Sign {} + +impl Sign where T: Int { pub fn new(n: T) -> Sign { if n < Int::zero() { Minus @@ -920,6 +955,8 @@ pub enum LitIntType { UnsuffixedIntLit(Sign) } +impl Copy for LitIntType {} + impl LitIntType { pub fn suffix_len(&self) -> uint { match *self { @@ -1015,6 +1052,8 @@ pub enum IntTy { TyI64, } +impl Copy for IntTy {} + impl fmt::Show for IntTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::int_ty_to_string(*self, None)) @@ -1040,6 +1079,8 @@ pub enum UintTy { TyU64, } +impl Copy for UintTy {} + impl UintTy { pub fn suffix_len(&self) -> uint { match *self { @@ -1062,6 +1103,8 @@ pub enum FloatTy { TyF64, } +impl Copy for FloatTy {} + impl fmt::Show for FloatTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::float_ty_to_string(*self)) @@ -1095,12 +1138,16 @@ pub enum PrimTy { TyChar } +impl Copy for PrimTy {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Onceness { Once, Many } +impl Copy for Onceness {} + impl fmt::Show for Onceness { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -1171,6 +1218,8 @@ pub enum AsmDialect { AsmIntel } +impl Copy for AsmDialect {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct InlineAsm { pub asm: InternedString, @@ -1228,6 +1277,8 @@ pub enum FnStyle { NormalFn, } +impl Copy for FnStyle {} + impl fmt::Show for FnStyle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -1345,6 +1396,8 @@ pub enum PathListItem_ { PathListMod { id: NodeId } } +impl Copy for PathListItem_ {} + impl PathListItem_ { pub fn id(&self) -> NodeId { match *self { @@ -1404,9 +1457,13 @@ pub enum AttrStyle { AttrInner, } +impl Copy for AttrStyle {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct AttrId(pub uint); +impl Copy for AttrId {} + /// Doc-comments are promoted to attributes that have is_sugared_doc = true #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Attribute_ { @@ -1442,6 +1499,8 @@ pub enum Visibility { Inherited, } +impl Copy for Visibility {} + impl Visibility { pub fn inherit_from(&self, parent_visibility: Visibility) -> Visibility { match self { @@ -1477,6 +1536,8 @@ pub enum StructFieldKind { UnnamedField(Visibility), } +impl Copy for StructFieldKind {} + impl StructFieldKind { pub fn is_unnamed(&self) -> bool { match *self { @@ -1583,6 +1644,8 @@ pub enum UnboxedClosureKind { FnOnceUnboxedClosureKind, } +impl Copy for UnboxedClosureKind {} + /// The data we save and restore about an inlined item or method. This is not /// part of the AST that we parse from a file, but it becomes part of the tree /// that we trans. diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 8db12fbd835..639a33a8063 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -43,6 +43,8 @@ use visit; /// To construct one, use the `Code::from_node` function. pub struct FnLikeNode<'a> { node: ast_map::Node<'a> } +impl<'a> Copy for FnLikeNode<'a> {} + /// MaybeFnLike wraps a method that indicates if an object /// corresponds to some FnLikeNode. pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } @@ -85,6 +87,8 @@ pub enum Code<'a> { BlockCode(&'a Block), } +impl<'a> Copy for Code<'a> {} + impl<'a> Code<'a> { pub fn id(&self) -> ast::NodeId { match *self { diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index ce2fe6e7220..2c985f403f8 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -38,6 +38,8 @@ pub enum PathElem { PathName(Name) } +impl Copy for PathElem {} + impl PathElem { pub fn name(&self) -> Name { match *self { @@ -120,6 +122,8 @@ pub enum Node<'ast> { NodeLifetime(&'ast Lifetime), } +impl<'ast> Copy for Node<'ast> {} + /// Represents an entry and its parent Node ID /// The odd layout is to bring down the total size. #[deriving(Show)] @@ -147,6 +151,8 @@ enum MapEntry<'ast> { RootInlinedParent(&'ast InlinedParent) } +impl<'ast> Copy for MapEntry<'ast> {} + impl<'ast> Clone for MapEntry<'ast> { fn clone(&self) -> MapEntry<'ast> { *self diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 68bb7ecfb85..7dba6a57fc4 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -315,6 +315,8 @@ pub struct IdRange { pub max: NodeId, } +impl Copy for IdRange {} + impl IdRange { pub fn max() -> IdRange { IdRange { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index a2811681efd..5894a88ece6 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -282,6 +282,8 @@ pub enum InlineAttr { InlineNever, } +impl Copy for InlineAttr {} + /// Determine what `#[inline]` attribute is present in `attrs`, if any. pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { // FIXME (#2809)---validate the usage of #[inline] and #[inline] @@ -354,6 +356,8 @@ pub enum StabilityLevel { Locked } +impl Copy for StabilityLevel {} + pub fn find_stability_generic<'a, AM: AttrMetaMethods, I: Iterator<&'a AM>> @@ -469,6 +473,8 @@ pub enum ReprAttr { ReprPacked, } +impl Copy for ReprAttr {} + impl ReprAttr { pub fn is_ffi_safe(&self) -> bool { match *self { @@ -486,6 +492,8 @@ pub enum IntType { UnsignedInt(ast::UintTy) } +impl Copy for IntType {} + impl IntType { #[inline] pub fn is_signed(self) -> bool { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 6bcf562204b..50b4f342368 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -34,12 +34,16 @@ pub trait Pos { #[deriving(Clone, PartialEq, Eq, Hash, PartialOrd, Show)] pub struct BytePos(pub u32); +impl Copy for BytePos {} + /// A character offset. Because of multibyte utf8 characters, a byte offset /// is not equivalent to a character offset. The CodeMap will convert BytePos /// values to CharPos values as necessary. #[deriving(PartialEq, Hash, PartialOrd, Show)] pub struct CharPos(pub uint); +impl Copy for CharPos {} + // FIXME: Lots of boilerplate in these impls, but so far my attempts to fix // have been unsuccessful @@ -90,6 +94,8 @@ pub struct Span { pub expn_id: ExpnId } +impl Copy for Span {} + pub const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: NO_EXPANSION }; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] @@ -98,6 +104,8 @@ pub struct Spanned { pub span: Span, } +impl Copy for Spanned {} + impl PartialEq for Span { fn eq(&self, other: &Span) -> bool { return (*self).lo == (*other).lo && (*self).hi == (*other).hi; @@ -183,6 +191,8 @@ pub enum MacroFormat { MacroBang } +impl Copy for MacroFormat {} + #[deriving(Clone, Hash, Show)] pub struct NameAndSpan { /// The name of the macro that was invoked to create the thing @@ -221,6 +231,8 @@ pub struct ExpnInfo { #[deriving(PartialEq, Eq, Clone, Show, Hash, Encodable, Decodable)] pub struct ExpnId(u32); +impl Copy for ExpnId {} + pub const NO_EXPANSION: ExpnId = ExpnId(-1); impl ExpnId { @@ -249,6 +261,8 @@ pub struct MultiByteChar { pub bytes: uint, } +impl Copy for MultiByteChar {} + /// A single source in the CodeMap pub struct FileMap { /// The name of the file that the source came from, source that doesn't diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 293c1b3a953..bbda80bd96c 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -40,6 +40,8 @@ pub enum RenderSpan { FileLine(Span), } +impl Copy for RenderSpan {} + impl RenderSpan { fn span(self) -> Span { match self { @@ -61,6 +63,8 @@ pub enum ColorConfig { Never } +impl Copy for ColorConfig {} + pub trait Emitter { fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, Span)>, msg: &str, code: Option<&str>, lvl: Level); @@ -73,10 +77,14 @@ pub trait Emitter { /// how a rustc task died (if so desired). pub struct FatalError; +impl Copy for FatalError {} + /// Signifies that the compiler died with an explicit call to `.bug` /// or `.span_bug` rather than a failed assertion, etc. pub struct ExplicitBug; +impl Copy for ExplicitBug {} + /// A span-handler is like a handler but also /// accepts span information for source-location /// reporting. @@ -230,6 +238,8 @@ pub enum Level { Help, } +impl Copy for Level {} + impl fmt::Show for Level { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::fmt::Show; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 0787518f04f..3c7a4a81d20 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -57,7 +57,7 @@ impl ItemDecorator for fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P|) { - (*self)(ecx, sp, meta_item, item, push) + self.clone()(ecx, sp, meta_item, item, push) } } @@ -77,7 +77,7 @@ impl ItemModifier for fn(&mut ExtCtxt, Span, &ast::MetaItem, P) -> P< meta_item: &ast::MetaItem, item: P) -> P { - (*self)(ecx, span, meta_item, item) + self.clone()(ecx, span, meta_item, item) } } @@ -99,7 +99,7 @@ impl TTMacroExpander for MacroExpanderFn { span: Span, token_tree: &[ast::TokenTree]) -> Box { - (*self)(ecx, span, token_tree) + self.clone()(ecx, span, token_tree) } } @@ -122,7 +122,7 @@ impl IdentMacroExpander for IdentMacroExpanderFn { ident: ast::Ident, token_tree: Vec ) -> Box { - (*self)(cx, sp, ident, token_tree) + self.clone()(cx, sp, ident, token_tree) } } @@ -228,6 +228,8 @@ pub struct DummyResult { span: Span } +impl Copy for DummyResult {} + impl DummyResult { /// Create a default MacResult that can be anything. /// diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 787c6e844d5..1bd55b5d504 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -85,6 +85,8 @@ pub enum OrderingOp { PartialCmpOp, LtOp, LeOp, GtOp, GeOp, } +impl Copy for OrderingOp {} + pub fn some_ordering_collapsed(cx: &mut ExtCtxt, span: Span, op: OrderingOp, diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index 6ba90bbebed..48120b575ac 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -56,6 +56,8 @@ pub enum SyntaxContext_ { IllegalCtxt } +impl Copy for SyntaxContext_ {} + /// A list of ident->name renamings pub type RenameList = Vec<(Ident, Name)>; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4af7b35079a..ac36e508f3b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -103,6 +103,8 @@ pub struct Features { pub quote: bool, } +impl Copy for Features {} + impl Features { pub fn new() -> Features { Features { diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index aeec6ee13fd..a17d66476c0 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -36,6 +36,8 @@ pub enum CommentStyle { BlankLine, } +impl Copy for CommentStyle {} + #[deriving(Clone)] pub struct Comment { pub style: CommentStyle, diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 650f8295d01..2a2bb42cef0 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -34,6 +34,8 @@ pub enum ObsoleteSyntax { ObsoleteExternCrateRenaming, } +impl Copy for ObsoleteSyntax {} + pub trait ParserObsoleteMethods { /// Reports an obsolete syntax non-fatal error. fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bb3d28ce2bb..4929ee885ac 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -98,6 +98,8 @@ bitflags! { } } +impl Copy for Restrictions {} + type ItemInfo = (Ident, Item_, Option >); /// How to parse a path. There are four different kinds of paths, all of which @@ -114,6 +116,8 @@ pub enum PathParsingMode { LifetimeAndTypesWithColons, } +impl Copy for PathParsingMode {} + enum ItemOrViewItem { /// Indicates a failure to parse any kind of item. The attributes are /// returned. diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 52b54bc7f2d..4b1e9482a7d 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -42,6 +42,8 @@ pub enum BinOpToken { Shr, } +impl Copy for BinOpToken {} + /// A delimeter token #[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] pub enum DelimToken { @@ -53,6 +55,8 @@ pub enum DelimToken { Brace, } +impl Copy for DelimToken {} + #[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] pub enum IdentStyle { /// `::` follows the identifier with no whitespace in-between. @@ -85,6 +89,12 @@ impl Lit { } } +#[cfg(not(stage0))] +impl Copy for Lit {} + +#[cfg(not(stage0))] +impl Copy for IdentStyle {} + #[allow(non_camel_case_types)] #[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] pub enum Token { @@ -435,6 +445,8 @@ macro_rules! declare_special_idents_and_keywords {( $( $rk_variant, )* } + impl Copy for Keyword {} + impl Keyword { pub fn to_name(&self) -> ast::Name { match *self { diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 7ab3d5dbcd1..c4e040a0f7c 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -72,18 +72,24 @@ pub enum Breaks { Inconsistent, } +impl Copy for Breaks {} + #[deriving(Clone)] pub struct BreakToken { offset: int, blank_space: int } +impl Copy for BreakToken {} + #[deriving(Clone)] pub struct BeginToken { offset: int, breaks: Breaks } +impl Copy for BeginToken {} + #[deriving(Clone)] pub enum Token { String(string::String, int), @@ -152,11 +158,15 @@ pub enum PrintStackBreak { Broken(Breaks), } +impl Copy for PrintStackBreak {} + pub struct PrintStackElem { offset: int, pbreak: PrintStackBreak } +impl Copy for PrintStackElem {} + static SIZE_INFINITY: int = 0xffff; pub fn mk_printer(out: Box, linewidth: uint) -> Printer { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6ce0ee79c62..eab03f73091 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -47,6 +47,8 @@ pub trait PpAnn { pub struct NoAnn; +impl Copy for NoAnn {} + impl PpAnn for NoAnn {} pub struct CurrentCommentAndLiteral { @@ -54,6 +56,8 @@ pub struct CurrentCommentAndLiteral { cur_lit: uint, } +impl Copy for CurrentCommentAndLiteral {} + pub struct State<'a> { pub s: pp::Printer, cm: Option<&'a CodeMap>, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 18623ca2a81..f5e89dd61ff 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -44,6 +44,8 @@ pub enum FnKind<'a> { FkFnBlock, } +impl<'a> Copy for FnKind<'a> {} + /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 0e4ecb8f73e..575ec860f97 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -165,6 +165,7 @@ pub mod color { /// Terminal attributes pub mod attr { pub use self::Attr::*; + use std::kinds::Copy; /// Terminal attributes for use with term.attr(). /// @@ -193,6 +194,8 @@ pub mod attr { /// Convenience attribute to set the background color BackgroundColor(super::color::Color) } + + impl Copy for Attr {} } /// A terminal with similar capabilities to an ANSI Terminal diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index ee8178fed91..c81bff6a1ae 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -33,6 +33,8 @@ enum States { SeekIfEndPercent(int) } +impl Copy for States {} + #[deriving(PartialEq)] enum FormatState { FormatStateFlags, @@ -40,6 +42,8 @@ enum FormatState { FormatStatePrecision } +impl Copy for FormatState {} + /// Types of parameters a capability can use #[allow(missing_docs)] #[deriving(Clone)] @@ -452,6 +456,8 @@ struct Flags { space: bool } +impl Copy for Flags {} + impl Flags { fn new() -> Flags { Flags{ width: 0, precision: 0, alternate: false, @@ -467,6 +473,8 @@ enum FormatOp { FormatString } +impl Copy for FormatOp {} + impl FormatOp { fn from_char(c: char) -> FormatOp { match c { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 06105ca61ca..ffc26738dd7 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -109,7 +109,13 @@ impl Show for TestName { } #[deriving(Clone)] -enum NamePadding { PadNone, PadOnLeft, PadOnRight } +enum NamePadding { + PadNone, + PadOnLeft, + PadOnRight, +} + +impl Copy for NamePadding {} impl TestDesc { fn padded_name(&self, column_count: uint, align: NamePadding) -> String { @@ -179,13 +185,14 @@ impl fmt::Show for TestFn { /// This is feed into functions marked with `#[bench]` to allow for /// set-up & tear-down before running a piece of code repeatedly via a /// call to `iter`. +#[deriving(Copy)] pub struct Bencher { iterations: u64, dur: Duration, pub bytes: u64, } -#[deriving(Clone, Show, PartialEq, Eq, Hash)] +#[deriving(Copy, Clone, Show, PartialEq, Eq, Hash)] pub enum ShouldFail { No, Yes(Option<&'static str>) @@ -212,6 +219,8 @@ pub struct Metric { noise: f64 } +impl Copy for Metric {} + impl Metric { pub fn new(value: f64, noise: f64) -> Metric { Metric {value: value, noise: noise} @@ -238,6 +247,8 @@ pub enum MetricChange { Regression(f64) } +impl Copy for MetricChange {} + pub type MetricDiff = TreeMap; // The default console test runner. It accepts the command line @@ -280,6 +291,8 @@ pub enum ColorConfig { NeverColor, } +impl Copy for ColorConfig {} + pub struct TestOpts { pub filter: Option, pub run_ignored: bool, @@ -1135,7 +1148,7 @@ pub fn run_test(opts: &TestOpts, return; } StaticBenchFn(benchfn) => { - let bs = ::bench::benchmark(|harness| benchfn(harness)); + let bs = ::bench::benchmark(|harness| (benchfn.clone())(harness)); monitor_ch.send((desc, TrBench(bs), Vec::new())); return; } diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index 4453034fe06..e293c547944 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -77,7 +77,13 @@ mod imp { /// A record specifying a time value in seconds and nanoseconds. #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Show)] -pub struct Timespec { pub sec: i64, pub nsec: i32 } +pub struct Timespec { + pub sec: i64, + pub nsec: i32, +} + +impl Copy for Timespec {} + /* * Timespec assumes that pre-epoch Timespecs have negative sec and positive * nsec fields. Darwin's and Linux's struct timespec functions handle pre- @@ -269,6 +275,8 @@ pub struct Tm { pub tm_nsec: i32, } +impl Copy for Tm {} + pub fn empty_tm() -> Tm { Tm { tm_sec: 0_i32, @@ -428,6 +436,8 @@ pub enum ParseError { UnexpectedCharacter(char, char), } +impl Copy for ParseError {} + impl Show for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/src/libunicode/tables.rs b/src/libunicode/tables.rs index c91ce5c6464..54f7b3501b8 100644 --- a/src/libunicode/tables.rs +++ b/src/libunicode/tables.rs @@ -7138,6 +7138,7 @@ pub mod charwidth { pub mod grapheme { pub use self::GraphemeCat::*; use core::slice::SlicePrelude; + use core::kinds::Copy; use core::slice; #[allow(non_camel_case_types)] @@ -7155,6 +7156,8 @@ pub mod grapheme { GC_Any, } + impl Copy for GraphemeCat {} + fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> GraphemeCat { use core::cmp::Ordering::{Equal, Less, Greater}; match r.binary_search(|&(lo, hi, _)| { diff --git a/src/test/auxiliary/issue-14422.rs b/src/test/auxiliary/issue-14422.rs index 04e1d993011..9ecb1195de0 100644 --- a/src/test/auxiliary/issue-14422.rs +++ b/src/test/auxiliary/issue-14422.rs @@ -25,6 +25,8 @@ mod src { pub struct A; + impl Copy for A {} + pub fn make() -> B { A } impl A { diff --git a/src/test/auxiliary/issue13213aux.rs b/src/test/auxiliary/issue13213aux.rs index 5bd52ef5010..cf8d0c167a1 100644 --- a/src/test/auxiliary/issue13213aux.rs +++ b/src/test/auxiliary/issue13213aux.rs @@ -22,6 +22,10 @@ mod private { p: i32, } pub const THREE: P = P { p: 3 }; + impl Copy for P {} } pub static A: S = S { p: private::THREE }; + +impl Copy for S {} + diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index ea2461ccfa8..e6bae462887 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -22,3 +22,8 @@ extern fn stack_exhausted() {} #[lang = "eh_personality"] extern fn eh_personality() {} + +#[lang="copy"] +pub trait Copy {} + + diff --git a/src/test/auxiliary/method_self_arg1.rs b/src/test/auxiliary/method_self_arg1.rs index d02222931e5..37022131c3d 100644 --- a/src/test/auxiliary/method_self_arg1.rs +++ b/src/test/auxiliary/method_self_arg1.rs @@ -16,6 +16,8 @@ pub fn get_count() -> u64 { unsafe { COUNT } } pub struct Foo; +impl Copy for Foo {} + impl Foo { pub fn foo(self, x: &Foo) { unsafe { COUNT *= 2; } diff --git a/src/test/auxiliary/method_self_arg2.rs b/src/test/auxiliary/method_self_arg2.rs index 99eb665388b..e1e79b59e3e 100644 --- a/src/test/auxiliary/method_self_arg2.rs +++ b/src/test/auxiliary/method_self_arg2.rs @@ -16,6 +16,8 @@ pub fn get_count() -> u64 { unsafe { COUNT } } pub struct Foo; +impl Copy for Foo {} + impl Foo { pub fn run_trait(self) { unsafe { COUNT *= 17; } diff --git a/src/test/auxiliary/xcrate_unit_struct.rs b/src/test/auxiliary/xcrate_unit_struct.rs index d56d7a70edf..5a918db1cfa 100644 --- a/src/test/auxiliary/xcrate_unit_struct.rs +++ b/src/test/auxiliary/xcrate_unit_struct.rs @@ -14,20 +14,31 @@ pub struct Struct; +impl Copy for Struct {} + pub enum Unit { UnitVariant, Argument(Struct) } +impl Copy for Unit {} + pub struct TupleStruct(pub uint, pub &'static str); +impl Copy for TupleStruct {} + // used by the cfail test pub struct StructWithFields { foo: int, } +impl Copy for StructWithFields {} + pub enum EnumWithVariants { EnumVariant, EnumVariantArg(int) } + +impl Copy for EnumWithVariants {} + diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index 419e39b53cf..025f8467d20 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -21,6 +21,8 @@ struct Vec2 { y: f32, } +impl Copy for Vec2 {} + fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v } fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) } diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs index 3059a014528..e954d0fed5e 100644 --- a/src/test/bench/shootout-chameneos-redux.rs +++ b/src/test/bench/shootout-chameneos-redux.rs @@ -53,7 +53,14 @@ fn print_complements() { } } -enum Color { Red, Yellow, Blue } +enum Color { + Red, + Yellow, + Blue, +} + +impl Copy for Color {} + impl fmt::Show for Color { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let str = match *self { @@ -70,6 +77,8 @@ struct CreatureInfo { color: Color } +impl Copy for CreatureInfo {} + fn show_color_list(set: Vec) -> String { let mut out = String::new(); for col in set.iter() { diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index b38b8e66d7d..4b890bbd8d3 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -67,6 +67,8 @@ struct P { p: [i32, .. 16], } +impl Copy for P {} + struct Perm { cnt: [i32, .. 16], fact: [u32, .. 16], @@ -75,6 +77,8 @@ struct Perm { perm: P, } +impl Copy for Perm {} + impl Perm { fn new(n: u32) -> Perm { let mut fact = [1, .. 16]; diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index 0b4a1d91968..afffbe5bed4 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -109,6 +109,8 @@ struct AminoAcid { p: f32, } +impl Copy for AminoAcid {} + struct RepeatFasta<'a, W:'a> { alu: &'static str, out: &'a mut W diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 8ed041513c4..847ae2c1c88 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -62,6 +62,8 @@ static OCCURRENCES: [&'static str, ..5] = [ #[deriving(PartialEq, PartialOrd, Ord, Eq)] struct Code(u64); +impl Copy for Code {} + impl Code { fn hash(&self) -> u64 { let Code(ret) = *self; diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index b62504d7ba8..3f36c16aff6 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -100,6 +100,8 @@ struct Planet { mass: f64, } +impl Copy for Planet {} + fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: int) { for _ in range(0, steps) { let mut b_slice = bodies.as_mut_slice(); diff --git a/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs b/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs index c071691c947..d5998c8ca99 100644 --- a/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs +++ b/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs @@ -14,11 +14,15 @@ struct Foo { bar2: Bar } +impl Copy for Foo {} + struct Bar { int1: int, int2: int, } +impl Copy for Bar {} + fn make_foo() -> Box { panic!() } fn borrow_same_field_twice_mut_mut() { diff --git a/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs b/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs index 3a85b45ad12..d252d442297 100644 --- a/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs +++ b/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs @@ -13,11 +13,15 @@ struct Foo { bar2: Bar } +impl Copy for Foo {} + struct Bar { int1: int, int2: int, } +impl Copy for Bar {} + fn make_foo() -> Foo { panic!() } fn borrow_same_field_twice_mut_mut() { diff --git a/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs b/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs deleted file mode 100644 index 2063d7388a9..00000000000 --- a/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 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. - -enum Either { Left(T), Right(U) } - - fn f(x: &mut Either, y: &Either) -> int { - match *y { - Either::Left(ref z) => { - *x = Either::Right(1.0); - *z - } - _ => panic!() - } - } - - fn g() { - let mut x: Either = Either::Left(3); - println!("{}", f(&mut x, &x)); //~ ERROR cannot borrow - } - - fn h() { - let mut x: Either = Either::Left(3); - let y: &Either = &x; - let z: &mut Either = &mut x; //~ ERROR cannot borrow - *z = *y; - } - - fn main() {} diff --git a/src/test/compile-fail/borrowck-use-mut-borrow.rs b/src/test/compile-fail/borrowck-use-mut-borrow.rs index 7414bb930d4..0d27473cb2d 100644 --- a/src/test/compile-fail/borrowck-use-mut-borrow.rs +++ b/src/test/compile-fail/borrowck-use-mut-borrow.rs @@ -9,6 +9,9 @@ // except according to those terms. struct A { a: int, b: int } + +impl Copy for A {} + struct B { a: int, b: Box } fn var_copy_after_var_borrow() { diff --git a/src/test/compile-fail/dst-index.rs b/src/test/compile-fail/dst-index.rs index f6511d68662..af97c864dc8 100644 --- a/src/test/compile-fail/dst-index.rs +++ b/src/test/compile-fail/dst-index.rs @@ -16,6 +16,8 @@ use std::fmt::Show; struct S; +impl Copy for S {} + impl Index for S { fn index<'a>(&'a self, _: &uint) -> &'a str { "hello" @@ -24,6 +26,8 @@ impl Index for S { struct T; +impl Copy for T {} + impl Index for T { fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) { static x: uint = 42; @@ -33,7 +37,8 @@ impl Index for T { fn main() { S[0]; - //~^ ERROR E0161 + //~^ ERROR cannot move out of dereference + //~^^ ERROR E0161 T[0]; //~^ ERROR cannot move out of dereference //~^^ ERROR E0161 diff --git a/src/test/compile-fail/dst-rvalue.rs b/src/test/compile-fail/dst-rvalue.rs index 52b7ea9efa5..4c1dafd8c1a 100644 --- a/src/test/compile-fail/dst-rvalue.rs +++ b/src/test/compile-fail/dst-rvalue.rs @@ -13,8 +13,10 @@ pub fn main() { let _x: Box = box *"hello world"; //~^ ERROR E0161 + //~^^ ERROR cannot move out of dereference let array: &[int] = &[1, 2, 3]; let _x: Box<[int]> = box *array; //~^ ERROR E0161 + //~^^ ERROR cannot move out of dereference } diff --git a/src/test/compile-fail/issue-17651.rs b/src/test/compile-fail/issue-17651.rs index ef8174a26aa..ab396edddf4 100644 --- a/src/test/compile-fail/issue-17651.rs +++ b/src/test/compile-fail/issue-17651.rs @@ -13,5 +13,6 @@ fn main() { (|| box *[0u].as_slice())(); - //~^ ERROR cannot move a value of type [uint] + //~^ ERROR cannot move out of dereference + //~^^ ERROR cannot move a value of type [uint] } diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs index f0c4a4243ac..8868c7f8256 100644 --- a/src/test/compile-fail/kindck-copy.rs +++ b/src/test/compile-fail/kindck-copy.rs @@ -14,6 +14,7 @@ use std::rc::Rc; fn assert_copy() { } + trait Dummy { } struct MyStruct { @@ -21,6 +22,8 @@ struct MyStruct { y: int, } +impl Copy for MyStruct {} + struct MyNoncopyStruct { x: Box, } diff --git a/src/test/compile-fail/lint-dead-code-1.rs b/src/test/compile-fail/lint-dead-code-1.rs index 1a4a87e608b..9e5f15c2721 100644 --- a/src/test/compile-fail/lint-dead-code-1.rs +++ b/src/test/compile-fail/lint-dead-code-1.rs @@ -12,6 +12,7 @@ #![allow(unused_variables)] #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] +#![allow(missing_copy_implementations)] #![deny(dead_code)] #![crate_type="lib"] diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs index 8d4ecde692d..b73c3fa2610 100644 --- a/src/test/compile-fail/lint-missing-doc.rs +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -13,6 +13,7 @@ #![feature(globs)] #![deny(missing_docs)] #![allow(dead_code)] +#![allow(missing_copy_implementations)] //! Some garbage docs for the crate here #![doc="More garbage"] diff --git a/src/test/compile-fail/opt-in-copy.rs b/src/test/compile-fail/opt-in-copy.rs new file mode 100644 index 00000000000..56f71c844ac --- /dev/null +++ b/src/test/compile-fail/opt-in-copy.rs @@ -0,0 +1,33 @@ +// Copyright 2014 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. + +struct CantCopyThis; + +struct IWantToCopyThis { + but_i_cant: CantCopyThis, +} + +impl Copy for IWantToCopyThis {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +enum CantCopyThisEither { + A, + B, +} + +enum IWantToCopyThisToo { + ButICant(CantCopyThisEither), +} + +impl Copy for IWantToCopyThisToo {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} + diff --git a/src/test/compile-fail/stage0-clone-contravariant-lifetime.rs b/src/test/compile-fail/stage0-clone-contravariant-lifetime.rs deleted file mode 100644 index 1d1b244ab5a..00000000000 --- a/src/test/compile-fail/stage0-clone-contravariant-lifetime.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 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. - -// A zero-dependency test that covers some basic traits, default -// methods, etc. When mucking about with basic type system stuff I -// often encounter problems in the iterator trait, so it's useful to -// have hanging around. -nmatsakis - -// error-pattern: requires `start` lang_item - -#![no_std] -#![feature(lang_items)] - -#[lang = "sized"] -pub trait Sized for Sized? { - // Empty. -} - -pub mod std { - pub mod clone { - pub trait Clone { - fn clone(&self) -> Self; - } - } -} - -pub struct ContravariantLifetime<'a>; - -impl <'a> ::std::clone::Clone for ContravariantLifetime<'a> { - #[inline] - fn clone(&self) -> ContravariantLifetime<'a> { - match *self { ContravariantLifetime => ContravariantLifetime, } - } -} - -fn main() { } diff --git a/src/test/compile-fail/stage0-cmp.rs b/src/test/compile-fail/stage0-cmp.rs deleted file mode 100644 index f68eb6400fa..00000000000 --- a/src/test/compile-fail/stage0-cmp.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 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. - - -// A zero-dependency test that covers some basic traits, default -// methods, etc. When mucking about with basic type system stuff I -// often encounter problems in the iterator trait, so it's useful to -// have hanging around. -nmatsakis - -// error-pattern: requires `start` lang_item - -#![no_std] -#![feature(lang_items)] - -#[lang = "sized"] -pub trait Sized for Sized? { - // Empty. -} - -#[unstable = "Definition may change slightly after trait reform"] -pub trait PartialEq for Sized? { - /// This method tests for `self` and `other` values to be equal, and is used by `==`. - fn eq(&self, other: &Self) -> bool; -} - -#[unstable = "Trait is unstable."] -impl<'a, Sized? T: PartialEq> PartialEq for &'a T { - #[inline] - fn eq(&self, other: & &'a T) -> bool { PartialEq::eq(*self, *other) } -} - -fn main() { } diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index fec1d1b2789..b0a0142f6dd 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -104,18 +104,21 @@ use self::AutoDiscriminant::{One, Two, Three}; use self::ManualDiscriminant::{OneHundred, OneThousand, OneMillion}; use self::SingleVariant::TheOnlyVariant; +#[deriving(Copy)] enum AutoDiscriminant { One, Two, Three } +#[deriving(Copy)] enum ManualDiscriminant { OneHundred = 100, OneThousand = 1000, OneMillion = 1000000 } +#[deriving(Copy)] enum SingleVariant { TheOnlyVariant } diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 7ceac0e7cea..4c0c82efea3 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -147,3 +147,6 @@ fn main() { } fn zzz() {()} + +impl Copy for Struct {} + diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index d86aa54f451..8cb8fae75cf 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -148,3 +148,6 @@ fn main() { } fn zzz() {()} + +impl Copy for Enum {} + diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index 2455c7aa519..d4244ee27d4 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -147,3 +147,6 @@ fn main() { } fn zzz() {()} + +impl Copy for Struct {} + diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs index 5e47d32e376..ca00587ba44 100644 --- a/src/test/debuginfo/method-on-struct.rs +++ b/src/test/debuginfo/method-on-struct.rs @@ -146,3 +146,6 @@ fn main() { } fn zzz() {()} + +impl Copy for Struct {} + diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs index 4d5f53fc120..e70f86a5367 100644 --- a/src/test/debuginfo/method-on-trait.rs +++ b/src/test/debuginfo/method-on-trait.rs @@ -152,3 +152,6 @@ fn main() { } fn zzz() {()} + +impl Copy for Struct {} + diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs index fb3bede37fd..31bdd20e409 100644 --- a/src/test/debuginfo/method-on-tuple-struct.rs +++ b/src/test/debuginfo/method-on-tuple-struct.rs @@ -144,3 +144,6 @@ fn main() { } fn zzz() {()} + +impl Copy for TupleStruct {} + diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index 287813a959f..87fdb2c42c8 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -148,3 +148,6 @@ fn main() { } fn zzz() {()} + +impl Copy for Struct {} + diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index bfb8abc9f66..6f488230521 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -149,3 +149,6 @@ fn main() { } fn zzz() {()} + +impl Copy for Struct {} + diff --git a/src/test/pretty/block-disambig.rs b/src/test/pretty/block-disambig.rs index 1b1765475f3..db01bc94e32 100644 --- a/src/test/pretty/block-disambig.rs +++ b/src/test/pretty/block-disambig.rs @@ -21,6 +21,8 @@ fn test2() -> int { let val = &0i; { } *val } struct S { eax: int } +impl Copy for S {} + fn test3() { let regs = &Cell::new(S {eax: 0}); match true { true => { } _ => { } } diff --git a/src/test/run-make/extern-fn-with-packed-struct/test.rs b/src/test/run-make/extern-fn-with-packed-struct/test.rs index 8d8daed1393..12d961bd59e 100644 --- a/src/test/run-make/extern-fn-with-packed-struct/test.rs +++ b/src/test/run-make/extern-fn-with-packed-struct/test.rs @@ -16,6 +16,8 @@ struct Foo { c: i8 } +impl Copy for Foo {} + #[link(name = "test", kind = "static")] extern { fn foo(f: Foo) -> Foo; diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs index eeddd5e19a8..cab98204b17 100644 --- a/src/test/run-make/target-specs/foo.rs +++ b/src/test/run-make/target-specs/foo.rs @@ -11,6 +11,9 @@ #![feature(lang_items)] #![no_std] +#[lang="copy"] +trait Copy { } + #[lang="sized"] trait Sized { } diff --git a/src/test/run-pass/borrowck-univariant-enum.rs b/src/test/run-pass/borrowck-univariant-enum.rs index 3d191f6c4b4..df4106c9844 100644 --- a/src/test/run-pass/borrowck-univariant-enum.rs +++ b/src/test/run-pass/borrowck-univariant-enum.rs @@ -15,6 +15,8 @@ enum newtype { newvar(int) } +impl Copy for newtype {} + pub fn main() { // Test that borrowck treats enums with a single variant diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs index 683e7ece871..382caa83c61 100644 --- a/src/test/run-pass/builtin-superkinds-in-metadata.rs +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -19,10 +19,12 @@ use trait_superkinds_in_metadata::{RequiresCopy}; struct X(T); -impl RequiresShare for X { } +impl Copy for X {} -impl RequiresRequiresShareAndSend for X { } +impl RequiresShare for X { } -impl RequiresCopy for X { } +impl RequiresRequiresShareAndSend for X { } + +impl RequiresCopy for X { } pub fn main() { } diff --git a/src/test/run-pass/cell-does-not-clone.rs b/src/test/run-pass/cell-does-not-clone.rs index c7c655b3db4..6455f1e4bb2 100644 --- a/src/test/run-pass/cell-does-not-clone.rs +++ b/src/test/run-pass/cell-does-not-clone.rs @@ -24,6 +24,8 @@ impl Clone for Foo { } } +impl Copy for Foo {} + pub fn main() { let x = Cell::new(Foo { x: 22 }); let _y = x.get(); diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index a0d35fd596b..2a9756d7714 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -14,6 +14,8 @@ use std::cmp; #[deriving(Show)] enum cat_type { tuxedo, tabby, tortoiseshell } +impl Copy for cat_type {} + impl cmp::PartialEq for cat_type { fn eq(&self, other: &cat_type) -> bool { ((*self) as uint) == ((*other) as uint) diff --git a/src/test/run-pass/coherence-impl-in-fn.rs b/src/test/run-pass/coherence-impl-in-fn.rs index 51cd62677ca..df0012e07ec 100644 --- a/src/test/run-pass/coherence-impl-in-fn.rs +++ b/src/test/run-pass/coherence-impl-in-fn.rs @@ -10,6 +10,7 @@ pub fn main() { enum x { foo } + impl Copy for x {} impl ::std::cmp::PartialEq for x { fn eq(&self, other: &x) -> bool { (*self) as int == (*other) as int diff --git a/src/test/run-pass/coherence-where-clause.rs b/src/test/run-pass/coherence-where-clause.rs index faec0c50280..e0d9d569d17 100644 --- a/src/test/run-pass/coherence-where-clause.rs +++ b/src/test/run-pass/coherence-where-clause.rs @@ -28,6 +28,8 @@ struct MyType { dummy: uint } +impl Copy for MyType {} + impl MyTrait for MyType { fn get(&self) -> MyType { (*self).clone() } } diff --git a/src/test/run-pass/const-nullary-univariant-enum.rs b/src/test/run-pass/const-nullary-univariant-enum.rs index fe171a9f73d..9a1a5de9360 100644 --- a/src/test/run-pass/const-nullary-univariant-enum.rs +++ b/src/test/run-pass/const-nullary-univariant-enum.rs @@ -12,6 +12,8 @@ enum Foo { Bar = 0xDEADBEE } +impl Copy for Foo {} + static X: Foo = Foo::Bar; pub fn main() { diff --git a/src/test/run-pass/dst-struct-sole.rs b/src/test/run-pass/dst-struct-sole.rs index 04fe6d5cefd..26cb27cc653 100644 --- a/src/test/run-pass/dst-struct-sole.rs +++ b/src/test/run-pass/dst-struct-sole.rs @@ -33,6 +33,8 @@ fn foo2(x: &Fat<[T]>) { #[deriving(PartialEq,Eq)] struct Bar; +impl Copy for Bar {} + trait ToBar { fn to_bar(&self) -> Bar; } diff --git a/src/test/run-pass/dst-struct.rs b/src/test/run-pass/dst-struct.rs index 6b8e25e8559..bf5b300f7cf 100644 --- a/src/test/run-pass/dst-struct.rs +++ b/src/test/run-pass/dst-struct.rs @@ -49,6 +49,8 @@ fn foo3(x: &Fat>) { #[deriving(PartialEq,Eq)] struct Bar; +impl Copy for Bar {} + trait ToBar { fn to_bar(&self) -> Bar; } diff --git a/src/test/run-pass/dst-trait.rs b/src/test/run-pass/dst-trait.rs index 97627309551..907c7810736 100644 --- a/src/test/run-pass/dst-trait.rs +++ b/src/test/run-pass/dst-trait.rs @@ -17,11 +17,15 @@ struct Fat { #[deriving(PartialEq,Eq)] struct Bar; +impl Copy for Bar {} + #[deriving(PartialEq,Eq)] struct Bar1 { f: int } +impl Copy for Bar1 {} + trait ToBar { fn to_bar(&self) -> Bar; fn to_val(&self) -> int; diff --git a/src/test/run-pass/empty-tag.rs b/src/test/run-pass/empty-tag.rs index 6b780d85459..e5d11ac1adb 100644 --- a/src/test/run-pass/empty-tag.rs +++ b/src/test/run-pass/empty-tag.rs @@ -11,6 +11,8 @@ #[deriving(Show)] enum chan { chan_t, } +impl Copy for chan {} + impl PartialEq for chan { fn eq(&self, other: &chan) -> bool { ((*self) as uint) == ((*other) as uint) diff --git a/src/test/run-pass/enum-discrim-width-stuff.rs b/src/test/run-pass/enum-discrim-width-stuff.rs index deb3f6b6c7c..cf8e742947d 100644 --- a/src/test/run-pass/enum-discrim-width-stuff.rs +++ b/src/test/run-pass/enum-discrim-width-stuff.rs @@ -20,6 +20,7 @@ macro_rules! check { A = 0 } static C: E = E::V; + impl Copy for E {} pub fn check() { assert_eq!(size_of::(), size_of::<$t>()); assert_eq!(E::V as $t, $v as $t); diff --git a/src/test/run-pass/explicit-self-generic.rs b/src/test/run-pass/explicit-self-generic.rs index 829870930a4..eeda299c71f 100644 --- a/src/test/run-pass/explicit-self-generic.rs +++ b/src/test/run-pass/explicit-self-generic.rs @@ -18,10 +18,14 @@ type EqFn = proc(K, K):'static -> bool; struct LM { resize_at: uint, size: uint } +impl Copy for LM {} + enum HashMap { HashMap_(LM) } +impl Copy for HashMap {} + fn linear_map() -> HashMap { HashMap::HashMap_(LM{ resize_at: 32, diff --git a/src/test/run-pass/export-unexported-dep.rs b/src/test/run-pass/export-unexported-dep.rs index 3fc5310a29b..48e9d9dea22 100644 --- a/src/test/run-pass/export-unexported-dep.rs +++ b/src/test/run-pass/export-unexported-dep.rs @@ -15,6 +15,8 @@ mod foo { // not exported enum t { t1, t2, } + impl Copy for t {} + impl PartialEq for t { fn eq(&self, other: &t) -> bool { ((*self) as uint) == ((*other) as uint) diff --git a/src/test/run-pass/expr-copy.rs b/src/test/run-pass/expr-copy.rs index 4a45ce66058..6e9ba4f8f41 100644 --- a/src/test/run-pass/expr-copy.rs +++ b/src/test/run-pass/expr-copy.rs @@ -15,6 +15,8 @@ fn f(arg: &mut A) { struct A { a: int } +impl Copy for A {} + pub fn main() { let mut x = A {a: 10}; f(&mut x); diff --git a/src/test/run-pass/expr-if-struct.rs b/src/test/run-pass/expr-if-struct.rs index 758d726851d..c95ca3fff8c 100644 --- a/src/test/run-pass/expr-if-struct.rs +++ b/src/test/run-pass/expr-if-struct.rs @@ -16,6 +16,8 @@ struct I { i: int } +impl Copy for I {} + fn test_rec() { let rs = if true { I {i: 100} } else { I {i: 101} }; assert_eq!(rs.i, 100); @@ -24,6 +26,8 @@ fn test_rec() { #[deriving(Show)] enum mood { happy, sad, } +impl Copy for mood {} + impl PartialEq for mood { fn eq(&self, other: &mood) -> bool { ((*self) as uint) == ((*other) as uint) diff --git a/src/test/run-pass/expr-match-struct.rs b/src/test/run-pass/expr-match-struct.rs index ea96005dc60..83101a3d2cc 100644 --- a/src/test/run-pass/expr-match-struct.rs +++ b/src/test/run-pass/expr-match-struct.rs @@ -15,6 +15,8 @@ // Tests for match as expressions resulting in struct types struct R { i: int } +impl Copy for R {} + fn test_rec() { let rs = match true { true => R {i: 100}, _ => panic!() }; assert_eq!(rs.i, 100); @@ -23,6 +25,8 @@ fn test_rec() { #[deriving(Show)] enum mood { happy, sad, } +impl Copy for mood {} + impl PartialEq for mood { fn eq(&self, other: &mood) -> bool { ((*self) as uint) == ((*other) as uint) diff --git a/src/test/run-pass/exterior.rs b/src/test/run-pass/exterior.rs index e95c2034131..2ca5f430a2a 100644 --- a/src/test/run-pass/exterior.rs +++ b/src/test/run-pass/exterior.rs @@ -13,6 +13,8 @@ use std::cell::Cell; struct Point {x: int, y: int, z: int} +impl Copy for Point {} + fn f(p: &Cell) { assert!((p.get().z == 12)); p.set(Point {x: 10, y: 11, z: 13}); diff --git a/src/test/run-pass/extern-pass-TwoU16s.rs b/src/test/run-pass/extern-pass-TwoU16s.rs index 6161d31c4a9..2b80a404036 100644 --- a/src/test/run-pass/extern-pass-TwoU16s.rs +++ b/src/test/run-pass/extern-pass-TwoU16s.rs @@ -16,6 +16,8 @@ pub struct TwoU16s { one: u16, two: u16 } +impl Copy for TwoU16s {} + #[link(name = "rust_test_helpers")] extern { pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s; diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs index 3e6b6502074..be4998c86fd 100644 --- a/src/test/run-pass/extern-pass-TwoU32s.rs +++ b/src/test/run-pass/extern-pass-TwoU32s.rs @@ -16,6 +16,8 @@ pub struct TwoU32s { one: u32, two: u32 } +impl Copy for TwoU32s {} + #[link(name = "rust_test_helpers")] extern { pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s; diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs index 5ad1e89425b..e8d91815bf9 100644 --- a/src/test/run-pass/extern-pass-TwoU64s.rs +++ b/src/test/run-pass/extern-pass-TwoU64s.rs @@ -16,6 +16,8 @@ pub struct TwoU64s { one: u64, two: u64 } +impl Copy for TwoU64s {} + #[link(name = "rust_test_helpers")] extern { pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s; diff --git a/src/test/run-pass/extern-pass-TwoU8s.rs b/src/test/run-pass/extern-pass-TwoU8s.rs index 14ba7c80059..7aa710df800 100644 --- a/src/test/run-pass/extern-pass-TwoU8s.rs +++ b/src/test/run-pass/extern-pass-TwoU8s.rs @@ -16,6 +16,8 @@ pub struct TwoU8s { one: u8, two: u8 } +impl Copy for TwoU8s {} + #[link(name = "rust_test_helpers")] extern { pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s; diff --git a/src/test/run-pass/foreign-fn-with-byval.rs b/src/test/run-pass/foreign-fn-with-byval.rs index 6a26ec44312..5d6815fc3c7 100644 --- a/src/test/run-pass/foreign-fn-with-byval.rs +++ b/src/test/run-pass/foreign-fn-with-byval.rs @@ -14,6 +14,8 @@ pub struct S { z: u64, } +impl Copy for S {} + #[link(name = "rust_test_helpers")] extern { pub fn get_x(x: S) -> u64; diff --git a/src/test/run-pass/generic-fn.rs b/src/test/run-pass/generic-fn.rs index 89f342b4ee5..a341bfe22eb 100644 --- a/src/test/run-pass/generic-fn.rs +++ b/src/test/run-pass/generic-fn.rs @@ -14,6 +14,8 @@ fn id(x: T) -> T { return x; } struct Triple {x: int, y: int, z: int} +impl Copy for Triple {} + pub fn main() { let mut x = 62; let mut y = 63; diff --git a/src/test/run-pass/guards-not-exhaustive.rs b/src/test/run-pass/guards-not-exhaustive.rs index c7f3c9d7182..b1bc40b662d 100644 --- a/src/test/run-pass/guards-not-exhaustive.rs +++ b/src/test/run-pass/guards-not-exhaustive.rs @@ -10,6 +10,8 @@ enum Q { R(Option) } +impl Copy for Q {} + fn xyzzy(q: Q) -> uint { match q { Q::R(S) if S.is_some() => { 0 } diff --git a/src/test/run-pass/guards.rs b/src/test/run-pass/guards.rs index 5bfbe4bf5a0..0157423863c 100644 --- a/src/test/run-pass/guards.rs +++ b/src/test/run-pass/guards.rs @@ -10,6 +10,8 @@ struct Pair { x: int, y: int } +impl Copy for Pair {} + pub fn main() { let a: int = match 10i { x if x < 7 => { 1i } x if x < 11 => { 2i } 10 => { 3i } _ => { 4i } }; diff --git a/src/test/run-pass/issue-12860.rs b/src/test/run-pass/issue-12860.rs index 4496a921e24..1caa04ae0b1 100644 --- a/src/test/run-pass/issue-12860.rs +++ b/src/test/run-pass/issue-12860.rs @@ -20,6 +20,8 @@ struct XYZ { z: int } +impl Copy for XYZ {} + fn main() { let mut connected = HashSet::new(); let mut border = HashSet::new(); diff --git a/src/test/run-pass/issue-19100.rs b/src/test/run-pass/issue-19100.rs index cee5c808f99..0ebd3ae8d97 100644 --- a/src/test/run-pass/issue-19100.rs +++ b/src/test/run-pass/issue-19100.rs @@ -13,6 +13,8 @@ enum Foo { Baz } +impl Copy for Foo {} + impl Foo { fn foo(&self) { match self { diff --git a/src/test/run-pass/issue-2288.rs b/src/test/run-pass/issue-2288.rs index 85dd879c830..1f371f0a1c2 100644 --- a/src/test/run-pass/issue-2288.rs +++ b/src/test/run-pass/issue-2288.rs @@ -12,10 +12,13 @@ trait clam { fn chowder(&self, y: A); } + struct foo { x: A, } +impl Copy for foo {} + impl clam for foo { fn chowder(&self, _y: A) { } diff --git a/src/test/run-pass/issue-2633.rs b/src/test/run-pass/issue-2633.rs index a9ebfbcbf33..bc014f699c7 100644 --- a/src/test/run-pass/issue-2633.rs +++ b/src/test/run-pass/issue-2633.rs @@ -12,6 +12,8 @@ struct cat { meow: extern "Rust" fn(), } +impl Copy for cat {} + fn meow() { println!("meow") } @@ -24,6 +26,8 @@ fn cat() -> cat { struct KittyInfo {kitty: cat} +impl Copy for KittyInfo {} + // Code compiles and runs successfully if we add a + before the first arg fn nyan(kitty: cat, _kitty_info: KittyInfo) { (kitty.meow)(); diff --git a/src/test/run-pass/issue-3121.rs b/src/test/run-pass/issue-3121.rs index d0e995da5f1..9e9d611f1a3 100644 --- a/src/test/run-pass/issue-3121.rs +++ b/src/test/run-pass/issue-3121.rs @@ -13,6 +13,10 @@ enum side { mayo, catsup, vinegar } enum order { hamburger, fries(side), shake } enum meal { to_go(order), for_here(order) } +impl Copy for side {} +impl Copy for order {} +impl Copy for meal {} + fn foo(m: Box, cond: bool) { match *m { meal::to_go(_) => { } diff --git a/src/test/run-pass/issue-3563-3.rs b/src/test/run-pass/issue-3563-3.rs index 4e330b9a0e7..d04d8f92ac4 100644 --- a/src/test/run-pass/issue-3563-3.rs +++ b/src/test/run-pass/issue-3563-3.rs @@ -29,6 +29,8 @@ struct Point { y: int, } +impl Copy for Point {} + // Represents an offset on a canvas. (This has the same structure as a Point. // but different semantics). struct Size { @@ -36,11 +38,15 @@ struct Size { height: int, } +impl Copy for Size {} + struct Rect { top_left: Point, size: Size, } +impl Copy for Rect {} + // Contains the information needed to do shape rendering via ASCII art. struct AsciiArt { width: uint, diff --git a/src/test/run-pass/issue-3743.rs b/src/test/run-pass/issue-3743.rs index bebaad2d297..ada3e37c092 100644 --- a/src/test/run-pass/issue-3743.rs +++ b/src/test/run-pass/issue-3743.rs @@ -13,6 +13,8 @@ struct Vec2 { y: f64 } +impl Copy for Vec2 {} + // methods we want to export as methods as well as operators impl Vec2 { #[inline(always)] diff --git a/src/test/run-pass/issue-3753.rs b/src/test/run-pass/issue-3753.rs index 9fbabed3a94..de6926e5512 100644 --- a/src/test/run-pass/issue-3753.rs +++ b/src/test/run-pass/issue-3753.rs @@ -19,11 +19,15 @@ pub struct Point { y: f64 } +impl Copy for Point {} + pub enum Shape { Circle(Point, f64), Rectangle(Point, Point) } +impl Copy for Shape {} + impl Shape { pub fn area(&self, sh: Shape) -> f64 { match sh { diff --git a/src/test/run-pass/issue-5688.rs b/src/test/run-pass/issue-5688.rs index 73bf375923a..0a13e001fab 100644 --- a/src/test/run-pass/issue-5688.rs +++ b/src/test/run-pass/issue-5688.rs @@ -18,7 +18,11 @@ failed to typecheck correctly. */ struct X { vec: &'static [int] } + +impl Copy for X {} + static V: &'static [X] = &[X { vec: &[1, 2, 3] }]; + pub fn main() { for &v in V.iter() { println!("{}", v.vec); diff --git a/src/test/run-pass/lang-item-public.rs b/src/test/run-pass/lang-item-public.rs index 982d4f6a0b5..81774c73c39 100644 --- a/src/test/run-pass/lang-item-public.rs +++ b/src/test/run-pass/lang-item-public.rs @@ -13,6 +13,7 @@ // ignore-windows #13361 #![no_std] +#![feature(lang_items)] extern crate "lang-item-public" as lang_lib; diff --git a/src/test/run-pass/match-arm-statics.rs b/src/test/run-pass/match-arm-statics.rs index 85fa61266a3..400aab64b4c 100644 --- a/src/test/run-pass/match-arm-statics.rs +++ b/src/test/run-pass/match-arm-statics.rs @@ -38,6 +38,8 @@ const VARIANT2_NORTH: EnumWithStructVariants = EnumWithStructVariants::Variant2 pub mod glfw { pub struct InputState(uint); + impl Copy for InputState {} + pub const RELEASE : InputState = InputState(0); pub const PRESS : InputState = InputState(1); pub const REPEAT : InputState = InputState(2); diff --git a/src/test/run-pass/method-self-arg-trait.rs b/src/test/run-pass/method-self-arg-trait.rs index b821c064cac..36dfe83a9eb 100644 --- a/src/test/run-pass/method-self-arg-trait.rs +++ b/src/test/run-pass/method-self-arg-trait.rs @@ -14,6 +14,8 @@ static mut COUNT: u64 = 1; struct Foo; +impl Copy for Foo {} + trait Bar { fn foo1(&self); fn foo2(self); diff --git a/src/test/run-pass/method-self-arg.rs b/src/test/run-pass/method-self-arg.rs index 3d73f34f8cf..788a25efcf9 100644 --- a/src/test/run-pass/method-self-arg.rs +++ b/src/test/run-pass/method-self-arg.rs @@ -14,6 +14,8 @@ static mut COUNT: uint = 1; struct Foo; +impl Copy for Foo {} + impl Foo { fn foo(self, x: &Foo) { unsafe { COUNT *= 2; } diff --git a/src/test/run-pass/monomorphize-abi-alignment.rs b/src/test/run-pass/monomorphize-abi-alignment.rs index 2233a5c3ea7..f5b51cd4233 100644 --- a/src/test/run-pass/monomorphize-abi-alignment.rs +++ b/src/test/run-pass/monomorphize-abi-alignment.rs @@ -19,12 +19,25 @@ */ struct S { i:u8, t:T } -impl S { fn unwrap(self) -> T { self.t } } + +impl Copy for S {} + +impl S { + fn unwrap(self) -> T { + self.t + } +} + #[deriving(PartialEq, Show)] struct A((u32, u32)); + +impl Copy for A {} + #[deriving(PartialEq, Show)] struct B(u64); +impl Copy for B {} + pub fn main() { static Ca: S = S { i: 0, t: A((13, 104)) }; static Cb: S = S { i: 0, t: B(31337) }; diff --git a/src/test/run-pass/multidispatch1.rs b/src/test/run-pass/multidispatch1.rs index 76c87f5d4c5..87d188418bd 100644 --- a/src/test/run-pass/multidispatch1.rs +++ b/src/test/run-pass/multidispatch1.rs @@ -18,6 +18,8 @@ struct MyType { dummy: uint } +impl Copy for MyType {} + impl MyTrait for MyType { fn get(&self) -> uint { self.dummy } } diff --git a/src/test/run-pass/multidispatch2.rs b/src/test/run-pass/multidispatch2.rs index 13131be93c8..1aa15cc5983 100644 --- a/src/test/run-pass/multidispatch2.rs +++ b/src/test/run-pass/multidispatch2.rs @@ -27,6 +27,8 @@ struct MyType { dummy: uint } +impl Copy for MyType {} + impl MyTrait for MyType { fn get(&self) -> uint { self.dummy } } diff --git a/src/test/run-pass/newtype.rs b/src/test/run-pass/newtype.rs index 0d1103086ae..093fd6c81cc 100644 --- a/src/test/run-pass/newtype.rs +++ b/src/test/run-pass/newtype.rs @@ -10,7 +10,14 @@ struct mytype(Mytype); -struct Mytype {compute: fn(mytype) -> int, val: int} +impl Copy for mytype {} + +struct Mytype { + compute: fn(mytype) -> int, + val: int, +} + +impl Copy for Mytype {} fn compute(i: mytype) -> int { let mytype(m) = i; diff --git a/src/test/run-pass/out-pointer-aliasing.rs b/src/test/run-pass/out-pointer-aliasing.rs index 2a44df7a1b5..5f399deb885 100644 --- a/src/test/run-pass/out-pointer-aliasing.rs +++ b/src/test/run-pass/out-pointer-aliasing.rs @@ -13,6 +13,8 @@ pub struct Foo { _f2: int, } +impl Copy for Foo {} + #[inline(never)] pub fn foo(f: &mut Foo) -> Foo { let ret = *f; diff --git a/src/test/run-pass/overloaded-autoderef-order.rs b/src/test/run-pass/overloaded-autoderef-order.rs index 0a9ac734c26..f0daf371ca7 100644 --- a/src/test/run-pass/overloaded-autoderef-order.rs +++ b/src/test/run-pass/overloaded-autoderef-order.rs @@ -15,6 +15,8 @@ struct DerefWrapper { y: Y } +impl Copy for DerefWrapper {} + impl DerefWrapper { fn get_x(self) -> X { self.x @@ -33,6 +35,8 @@ mod priv_test { pub y: Y } + impl Copy for DerefWrapperHideX {} + impl DerefWrapperHideX { pub fn new(x: X, y: Y) -> DerefWrapperHideX { DerefWrapperHideX { diff --git a/src/test/run-pass/packed-struct-vec.rs b/src/test/run-pass/packed-struct-vec.rs index c20e62351a6..59bb5678b69 100644 --- a/src/test/run-pass/packed-struct-vec.rs +++ b/src/test/run-pass/packed-struct-vec.rs @@ -19,6 +19,8 @@ struct Foo { baz: u64 } +impl Copy for Foo {} + pub fn main() { let foos = [Foo { bar: 1, baz: 2 }, .. 10]; diff --git a/src/test/run-pass/rec-tup.rs b/src/test/run-pass/rec-tup.rs index 0dc547f1a02..8adad012ec6 100644 --- a/src/test/run-pass/rec-tup.rs +++ b/src/test/run-pass/rec-tup.rs @@ -10,6 +10,8 @@ struct Point {x: int, y: int} +impl Copy for Point {} + type rect = (Point, Point); fn fst(r: rect) -> Point { let (fst, _) = r; return fst; } diff --git a/src/test/run-pass/rec.rs b/src/test/run-pass/rec.rs index b9b5cfebb0b..02fcf1ad068 100644 --- a/src/test/run-pass/rec.rs +++ b/src/test/run-pass/rec.rs @@ -13,6 +13,8 @@ struct Rect {x: int, y: int, w: int, h: int} +impl Copy for Rect {} + fn f(r: Rect, x: int, y: int, w: int, h: int) { assert_eq!(r.x, x); assert_eq!(r.y, y); diff --git a/src/test/run-pass/regions-dependent-addr-of.rs b/src/test/run-pass/regions-dependent-addr-of.rs index f074ca9a889..79f8ca48882 100644 --- a/src/test/run-pass/regions-dependent-addr-of.rs +++ b/src/test/run-pass/regions-dependent-addr-of.rs @@ -29,6 +29,8 @@ struct C { f: int } +impl Copy for C {} + fn get_v1(a: &A) -> &int { // Region inferencer must deduce that &v < L2 < L1 let foo = &a.value; // L1 diff --git a/src/test/run-pass/regions-early-bound-used-in-bound-method.rs b/src/test/run-pass/regions-early-bound-used-in-bound-method.rs index c011d11749b..5b4169a4e84 100644 --- a/src/test/run-pass/regions-early-bound-used-in-bound-method.rs +++ b/src/test/run-pass/regions-early-bound-used-in-bound-method.rs @@ -19,6 +19,8 @@ struct Box<'a> { t: &'a int } +impl<'a> Copy for Box<'a> {} + impl<'a> GetRef<'a> for Box<'a> { fn get(&self) -> &'a int { self.t diff --git a/src/test/run-pass/regions-early-bound-used-in-bound.rs b/src/test/run-pass/regions-early-bound-used-in-bound.rs index 58de2e0e20e..73eb7ca7188 100644 --- a/src/test/run-pass/regions-early-bound-used-in-bound.rs +++ b/src/test/run-pass/regions-early-bound-used-in-bound.rs @@ -19,6 +19,8 @@ struct Box<'a, T:'a> { t: &'a T } +impl<'a,T:'a> Copy for Box<'a,T> {} + impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> { fn get(&self) -> &'a T { self.t diff --git a/src/test/run-pass/regions-early-bound-used-in-type-param.rs b/src/test/run-pass/regions-early-bound-used-in-type-param.rs index 708664f33e9..622f820971f 100644 --- a/src/test/run-pass/regions-early-bound-used-in-type-param.rs +++ b/src/test/run-pass/regions-early-bound-used-in-type-param.rs @@ -19,6 +19,8 @@ struct Box { t: T } +impl Copy for Box {} + impl Get for Box { fn get(&self) -> T { self.t.clone() diff --git a/src/test/run-pass/regions-mock-tcx.rs b/src/test/run-pass/regions-mock-tcx.rs index e13edae330a..e10c12a6037 100644 --- a/src/test/run-pass/regions-mock-tcx.rs +++ b/src/test/run-pass/regions-mock-tcx.rs @@ -32,6 +32,9 @@ enum TypeStructure<'tcx> { TypeInt, TypeFunction(Type<'tcx>, Type<'tcx>), } + +impl<'tcx> Copy for TypeStructure<'tcx> {} + impl<'tcx> PartialEq for TypeStructure<'tcx> { fn eq(&self, other: &TypeStructure<'tcx>) -> bool { match (*self, *other) { @@ -93,6 +96,8 @@ struct NodeId { id: uint } +impl Copy for NodeId {} + type Ast<'ast> = &'ast AstStructure<'ast>; struct AstStructure<'ast> { @@ -100,12 +105,16 @@ struct AstStructure<'ast> { kind: AstKind<'ast> } +impl<'ast> Copy for AstStructure<'ast> {} + enum AstKind<'ast> { ExprInt, ExprVar(uint), ExprLambda(Ast<'ast>), } +impl<'ast> Copy for AstKind<'ast> {} + fn compute_types<'tcx,'ast>(tcx: &mut TypeContext<'tcx,'ast>, ast: Ast<'ast>) -> Type<'tcx> { diff --git a/src/test/run-pass/self-in-mut-slot-immediate-value.rs b/src/test/run-pass/self-in-mut-slot-immediate-value.rs index f2482474073..1603f7f9763 100644 --- a/src/test/run-pass/self-in-mut-slot-immediate-value.rs +++ b/src/test/run-pass/self-in-mut-slot-immediate-value.rs @@ -15,6 +15,8 @@ struct Value { n: int } +impl Copy for Value {} + impl Value { fn squared(mut self) -> Value { self.n *= self.n; diff --git a/src/test/run-pass/shape_intrinsic_tag_then_rec.rs b/src/test/run-pass/shape_intrinsic_tag_then_rec.rs deleted file mode 100644 index 930364c0e22..00000000000 --- a/src/test/run-pass/shape_intrinsic_tag_then_rec.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2012 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. - - -// Exercises a bug in the shape code that was exposed -// on x86_64: when there is an enum embedded in an -// interior record which is then itself interior to -// something else, shape calculations were off. - -#[deriving(Clone, Show)] -enum opt_span { - //hack (as opposed to option), to make `span` compile - os_none, - os_some(Box), -} - -#[deriving(Clone, Show)] -struct Span { - lo: uint, - hi: uint, - expanded_from: opt_span, -} - -#[deriving(Clone, Show)] -struct Spanned { - data: T, - span: Span, -} - -type ty_ = uint; - -#[deriving(Clone, Show)] -struct Path_ { - global: bool, - idents: Vec , - types: Vec>, -} - -type path = Spanned; -type ty = Spanned; - -#[deriving(Clone, Show)] -struct X { - sp: Span, - path: path, -} - -pub fn main() { - let sp: Span = Span {lo: 57451u, hi: 57542u, expanded_from: opt_span::os_none}; - let t: Box = box Spanned { data: 3u, span: sp.clone() }; - let p_: Path_ = Path_ { - global: true, - idents: vec!("hi".to_string()), - types: vec!(t), - }; - let p: path = Spanned { data: p_, span: sp.clone() }; - let x = X { sp: sp, path: p }; - println!("{}", x.path.clone()); - println!("{}", x.clone()); -} diff --git a/src/test/run-pass/simd-generics.rs b/src/test/run-pass/simd-generics.rs index 68c210b018a..31c29b615fc 100644 --- a/src/test/run-pass/simd-generics.rs +++ b/src/test/run-pass/simd-generics.rs @@ -15,6 +15,8 @@ use std::ops; #[simd] struct f32x4(f32, f32, f32, f32); +impl Copy for f32x4 {} + fn add>(lhs: T, rhs: T) -> T { lhs + rhs } diff --git a/src/test/run-pass/small-enum-range-edge.rs b/src/test/run-pass/small-enum-range-edge.rs index 17d647e58b5..de38a553e12 100644 --- a/src/test/run-pass/small-enum-range-edge.rs +++ b/src/test/run-pass/small-enum-range-edge.rs @@ -14,11 +14,17 @@ #[repr(u8)] enum Eu { Lu = 0, Hu = 255 } + +impl Copy for Eu {} + static CLu: Eu = Eu::Lu; static CHu: Eu = Eu::Hu; #[repr(i8)] enum Es { Ls = -128, Hs = 127 } + +impl Copy for Es {} + static CLs: Es = Es::Ls; static CHs: Es = Es::Hs; diff --git a/src/test/run-pass/struct-return.rs b/src/test/run-pass/struct-return.rs index 63574316fe5..bb06aec23f6 100644 --- a/src/test/run-pass/struct-return.rs +++ b/src/test/run-pass/struct-return.rs @@ -11,8 +11,13 @@ // ignore-lexer-test FIXME #15883 pub struct Quad { a: u64, b: u64, c: u64, d: u64 } + +impl Copy for Quad {} + pub struct Floats { a: f64, b: u8, c: f64 } +impl Copy for Floats {} + mod rustrt { use super::{Floats, Quad}; diff --git a/src/test/run-pass/structured-compare.rs b/src/test/run-pass/structured-compare.rs index 88f72932ca0..d0446d83d2e 100644 --- a/src/test/run-pass/structured-compare.rs +++ b/src/test/run-pass/structured-compare.rs @@ -13,6 +13,8 @@ #[deriving(Show)] enum foo { large, small, } +impl Copy for foo {} + impl PartialEq for foo { fn eq(&self, other: &foo) -> bool { ((*self) as uint) == ((*other) as uint) diff --git a/src/test/run-pass/tag-variant-disr-val.rs b/src/test/run-pass/tag-variant-disr-val.rs index 7aa2ba280ac..cf53c1a912a 100644 --- a/src/test/run-pass/tag-variant-disr-val.rs +++ b/src/test/run-pass/tag-variant-disr-val.rs @@ -20,6 +20,8 @@ enum color { orange = 8 >> 1 } +impl Copy for color {} + impl PartialEq for color { fn eq(&self, other: &color) -> bool { ((*self) as uint) == ((*other) as uint) diff --git a/src/test/run-pass/trait-coercion-generic.rs b/src/test/run-pass/trait-coercion-generic.rs index 1e241ad2278..7d924f977cb 100644 --- a/src/test/run-pass/trait-coercion-generic.rs +++ b/src/test/run-pass/trait-coercion-generic.rs @@ -18,6 +18,8 @@ struct Struct { y: int, } +impl Copy for Struct {} + impl Trait<&'static str> for Struct { fn f(&self, x: &'static str) { println!("Hi, {}!", x); diff --git a/src/test/run-pass/trait-coercion.rs b/src/test/run-pass/trait-coercion.rs index 55beebbf2bc..37d69ddfe07 100644 --- a/src/test/run-pass/trait-coercion.rs +++ b/src/test/run-pass/trait-coercion.rs @@ -19,6 +19,8 @@ struct Struct { y: int, } +impl Copy for Struct {} + impl Trait for Struct { fn f(&self) { println!("Hi!"); diff --git a/src/test/run-pass/typeclasses-eq-example-static.rs b/src/test/run-pass/typeclasses-eq-example-static.rs index a5547c0eea9..6b00a8b5c2d 100644 --- a/src/test/run-pass/typeclasses-eq-example-static.rs +++ b/src/test/run-pass/typeclasses-eq-example-static.rs @@ -18,8 +18,11 @@ trait Equal { fn isEq(a: &Self, b: &Self) -> bool; } +#[deriving(Clone)] enum Color { cyan, magenta, yellow, black } +impl Copy for Color {} + impl Equal for Color { fn isEq(a: &Color, b: &Color) -> bool { match (*a, *b) { @@ -32,6 +35,7 @@ impl Equal for Color { } } +#[deriving(Clone)] enum ColorTree { leaf(Color), branch(Box, Box) @@ -40,9 +44,12 @@ enum ColorTree { impl Equal for ColorTree { fn isEq(a: &ColorTree, b: &ColorTree) -> bool { match (a, b) { - (&leaf(x), &leaf(y)) => { Equal::isEq(&x, &y) } + (&leaf(ref x), &leaf(ref y)) => { + Equal::isEq(&(*x).clone(), &(*y).clone()) + } (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => { - Equal::isEq(&**l1, &**l2) && Equal::isEq(&**r1, &**r2) + Equal::isEq(&(**l1).clone(), &(**l2).clone()) && + Equal::isEq(&(**r1).clone(), &(**r2).clone()) } _ => { false } } diff --git a/src/test/run-pass/typeclasses-eq-example.rs b/src/test/run-pass/typeclasses-eq-example.rs index 21b9c774e8c..e4b7d2eb60b 100644 --- a/src/test/run-pass/typeclasses-eq-example.rs +++ b/src/test/run-pass/typeclasses-eq-example.rs @@ -17,8 +17,11 @@ trait Equal { fn isEq(&self, a: &Self) -> bool; } +#[deriving(Clone)] enum Color { cyan, magenta, yellow, black } +impl Copy for Color {} + impl Equal for Color { fn isEq(&self, a: &Color) -> bool { match (*self, *a) { @@ -31,6 +34,7 @@ impl Equal for Color { } } +#[deriving(Clone)] enum ColorTree { leaf(Color), branch(Box, Box) @@ -39,9 +43,9 @@ enum ColorTree { impl Equal for ColorTree { fn isEq(&self, a: &ColorTree) -> bool { match (self, a) { - (&leaf(x), &leaf(y)) => { x.isEq(&y) } + (&leaf(ref x), &leaf(ref y)) => { x.isEq(&(*y).clone()) } (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => { - (&**l1).isEq(&**l2) && (&**r1).isEq(&**r2) + (*l1).isEq(&(**l2).clone()) && (*r1).isEq(&(**r2).clone()) } _ => { false } } diff --git a/src/test/run-pass/ufcs-explicit-self.rs b/src/test/run-pass/ufcs-explicit-self.rs index b96820eee14..b6b9fb67f90 100644 --- a/src/test/run-pass/ufcs-explicit-self.rs +++ b/src/test/run-pass/ufcs-explicit-self.rs @@ -12,6 +12,8 @@ struct Foo { f: int, } +impl Copy for Foo {} + impl Foo { fn foo(self: Foo, x: int) -> int { self.f + x @@ -28,6 +30,8 @@ struct Bar { f: T, } +impl Copy for Bar {} + impl Bar { fn foo(self: Bar, x: int) -> int { x diff --git a/src/test/run-pass/unboxed-closures-monomorphization.rs b/src/test/run-pass/unboxed-closures-monomorphization.rs index 43fb4b296cc..cd97fd96fa3 100644 --- a/src/test/run-pass/unboxed-closures-monomorphization.rs +++ b/src/test/run-pass/unboxed-closures-monomorphization.rs @@ -30,6 +30,9 @@ fn main(){ #[deriving(Show, PartialEq)] struct Foo(uint, &'static str); + + impl Copy for Foo {} + let x = Foo(42, "forty-two"); let f = bar(x); assert_eq!(f.call_once(()), x); -- cgit 1.4.1-3-g733a5 From 397dda8aa08ee540cffd36f542ebd1140227d0bd Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 29 Nov 2014 17:08:30 +1300 Subject: Add support for equality constraints on associated types --- src/librustc/diagnostics.rs | 9 +- src/librustc/middle/infer/error_reporting.rs | 16 ++- src/librustc/middle/privacy.rs | 11 +- src/librustc/middle/resolve.rs | 62 ++++++--- src/librustc/middle/resolve_lifetime.rs | 19 ++- src/librustc/middle/subst.rs | 7 + src/librustc/middle/traits/util.rs | 15 +- src/librustc_typeck/astconv.rs | 139 +++++++++++++++---- src/librustc_typeck/check/method/probe.rs | 18 ++- src/librustc_typeck/check/mod.rs | 64 ++++++++- src/librustc_typeck/collect.rs | 74 ++++++---- src/libsyntax/ast.rs | 43 +++++- src/libsyntax/ast_util.rs | 16 +++ src/libsyntax/ext/build.rs | 14 +- src/libsyntax/ext/deriving/generic/mod.rs | 2 +- src/libsyntax/ext/deriving/generic/ty.rs | 4 +- src/libsyntax/ext/deriving/rand.rs | 1 + src/libsyntax/ext/env.rs | 3 +- src/libsyntax/ext/format.rs | 1 + src/libsyntax/fold.rs | 48 +++++-- src/libsyntax/parse/parser.rs | 177 ++++++++++++++++++------ src/libsyntax/print/pprust.rs | 28 +++- src/libsyntax/visit.rs | 18 ++- src/test/compile-fail/assoc-eq-1.rs | 27 ++++ src/test/compile-fail/assoc-eq-2.rs | 30 ++++ src/test/compile-fail/assoc-eq-3.rs | 48 +++++++ src/test/compile-fail/issue-3973.rs | 2 +- src/test/compile-fail/macro-inner-attributes.rs | 2 +- src/test/run-pass/assoc-eq.rs | 55 ++++++++ 29 files changed, 790 insertions(+), 163 deletions(-) create mode 100644 src/test/compile-fail/assoc-eq-1.rs create mode 100644 src/test/compile-fail/assoc-eq-2.rs create mode 100644 src/test/compile-fail/assoc-eq-3.rs create mode 100644 src/test/run-pass/assoc-eq.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 81209763a0c..641d1e1f299 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -148,5 +148,12 @@ register_diagnostics!( E0169, E0170, E0171, - E0172 + E0172, + E0173, + E0174, + E0175, + E0176, + E0177, + E0178, + E0179 ) diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 657ee088758..d24eddf9ab0 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1405,10 +1405,22 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { let new_types = data.types.map(|t| { self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names) }); + let new_bindings = data.bindings.map(|b| { + P(ast::TypeBinding { + id: b.id, + ident: b.ident, + ty: self.rebuild_arg_ty_or_output(&*b.ty, + lifetime, + anon_nums, + region_names), + span: b.span + }) + }); ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: new_lts, - types: new_types - }) + types: new_types, + bindings: new_bindings, + }) } }; let new_seg = ast::PathSegment { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 5770b601a69..37b70535306 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -1453,8 +1453,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { } } for predicate in generics.where_clause.predicates.iter() { - for bound in predicate.bounds.iter() { - self.check_ty_param_bound(predicate.span, bound) + match predicate { + &ast::BoundPredicate(ref bound_pred) => { + for bound in bound_pred.bounds.iter() { + self.check_ty_param_bound(bound_pred.span, bound) + } + } + &ast::EqPredicate(ref eq_pred) => { + self.visit_ty(&*eq_pred.ty); + } } } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 36b87bbd423..e36fefe578d 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -3407,9 +3407,8 @@ impl<'a> Resolver<'a> { // This is not a crate-relative path. We resolve the // first component of the path in the current lexical // scope and then proceed to resolve below that. - match self.resolve_module_in_lexical_scope( - module_, - module_path[0]) { + match self.resolve_module_in_lexical_scope(module_, + module_path[0]) { Failed(err) => return Failed(err), Indeterminate => { debug!("(resolving module path for import) \ @@ -4590,25 +4589,42 @@ impl<'a> Resolver<'a> { fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) { for predicate in where_clause.predicates.iter() { - match self.resolve_identifier(predicate.ident, - TypeNS, - true, - predicate.span) { - Some((def @ DefTyParam(_, _, _), last_private)) => { - self.record_def(predicate.id, (def, last_private)); - } - _ => { - self.resolve_error( - predicate.span, - format!("undeclared type parameter `{}`", - token::get_ident( - predicate.ident)).as_slice()); + match predicate { + &ast::BoundPredicate(ref bound_pred) => { + match self.resolve_identifier(bound_pred.ident, + TypeNS, + true, + bound_pred.span) { + Some((def @ DefTyParam(..), last_private)) => { + self.record_def(bound_pred.id, (def, last_private)); + } + _ => { + self.resolve_error( + bound_pred.span, + format!("undeclared type parameter `{}`", + token::get_ident( + bound_pred.ident)).as_slice()); + } + } + + for bound in bound_pred.bounds.iter() { + self.resolve_type_parameter_bound(bound_pred.id, bound, + TraitBoundingTypeParameter); + } } - } + &ast::EqPredicate(ref eq_pred) => { + match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) { + Some((def @ DefTyParam(..), last_private)) => { + self.record_def(eq_pred.id, (def, last_private)); + } + _ => { + self.resolve_error(eq_pred.path.span, + "undeclared associated type"); + } + } - for bound in predicate.bounds.iter() { - self.resolve_type_parameter_bound(predicate.id, bound, - TraitBoundingTypeParameter); + self.resolve_type(&*eq_pred.ty); + } } } } @@ -5269,15 +5285,19 @@ impl<'a> Resolver<'a> { path: &Path, namespace: Namespace, check_ribs: bool) -> Option<(Def, LastPrivate)> { - // First, resolve the types. + // First, resolve the types and associated type bindings. for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) { self.resolve_type(&**ty); } + for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) { + self.resolve_type(&*binding.ty); + } if path.global { return self.resolve_crate_relative_path(path, namespace); } + // Try to find a path to an item in a module. let unqualified_def = self.resolve_identifier(path.segments .last().unwrap() diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 2ba9ba5631d..b822e658c0d 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -210,8 +210,16 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } } for predicate in generics.where_clause.predicates.iter() { - self.visit_ident(predicate.span, predicate.ident); - visit::walk_ty_param_bounds_helper(self, &predicate.bounds); + match predicate { + &ast::BoundPredicate(ast::WhereBoundPredicate{ident, ref bounds, span, ..}) => { + self.visit_ident(span, ident); + visit::walk_ty_param_bounds_helper(self, bounds); + } + &ast::EqPredicate(ast::WhereEqPredicate{id, ref path, ref ty, ..}) => { + self.visit_path(path, id); + self.visit_ty(&**ty); + } + } } } @@ -486,7 +494,12 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec { visit::walk_ty_param_bounds_helper(&mut collector, &ty_param.bounds); } for predicate in generics.where_clause.predicates.iter() { - visit::walk_ty_param_bounds_helper(&mut collector, &predicate.bounds); + match predicate { + &ast::BoundPredicate(ast::WhereBoundPredicate{ref bounds, ..}) => { + visit::walk_ty_param_bounds_helper(&mut collector, bounds); + } + _ => {} + } } } diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index bcc762a9640..fccb45f8724 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -123,6 +123,13 @@ pub fn self_ty(&self) -> Option> { s } + pub fn with_assoc_tys(&self, assoc_tys: Vec>) -> Substs<'tcx> { + assert!(self.types.is_empty_in(AssocSpace)); + let mut s = (*self).clone(); + s.types.replace(AssocSpace, assoc_tys); + s + } + pub fn erase_regions(self) -> Substs<'tcx> { let Substs { types, regions: _ } = self; Substs { types: types, regions: ErasedRegions } diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 1b7998a9263..66716267135 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -10,7 +10,7 @@ // except according to those terms. use middle::subst; -use middle::subst::{ParamSpace, Substs, VecPerParamSpace}; +use middle::subst::{ParamSpace, Substs, VecPerParamSpace, Subst}; use middle::infer::InferCtxt; use middle::ty::{mod, Ty}; use std::collections::HashSet; @@ -149,7 +149,18 @@ pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, { let tcx = infcx.tcx; let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics; - infcx.fresh_substs_for_generics(span, &impl_generics) + let input_substs = infcx.fresh_substs_for_generics(span, &impl_generics); + + // Add substs for the associated types bound in the impl. + let ref items = tcx.impl_items.borrow()[impl_def_id]; + let mut assoc_tys = Vec::new(); + for item in items.iter() { + if let &ty::ImplOrTraitItemId::TypeTraitItemId(id) = item { + assoc_tys.push(tcx.tcache.borrow()[id].ty.subst(tcx, &input_substs)); + } + } + + input_substs.with_assoc_tys(assoc_tys) } impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 7f1aad8ca77..89e10270f01 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -83,13 +83,18 @@ pub trait AstConv<'tcx> { trait_id: ast::DefId) -> bool; - /// Returns the binding of the given associated type for some type. + /// Returns the concrete type bound to the given associated type (indicated + /// by associated_type_id) in the current context. For example, + /// in `trait Foo { type A; }` looking up `A` will give a type variable; + /// in `impl Foo for ... { type A = int; ... }` looking up `A` will give `int`. fn associated_type_binding(&self, span: Span, - ty: Option>, + self_ty: Option>, + // DefId for the declaration of the trait + // in which the associated type is declared. trait_id: ast::DefId, associated_type_id: ast::DefId) - -> Ty<'tcx>; + -> Option>; } pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime) @@ -207,7 +212,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>( rscope: &RS, decl_def_id: ast::DefId, decl_generics: &ty::Generics<'tcx>, - self_ty: Option>, path: &ast::Path) -> Substs<'tcx> where AC: AstConv<'tcx>, RS: RegionScope @@ -225,19 +229,26 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>( assert!(decl_generics.regions.all(|d| d.space == TypeSpace)); assert!(decl_generics.types.all(|d| d.space != FnSpace)); - let (regions, types) = match path.segments.last().unwrap().parameters { + let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters { ast::AngleBracketedParameters(ref data) => { convert_angle_bracketed_parameters(this, rscope, data) } ast::ParenthesizedParameters(ref data) => { span_err!(tcx.sess, path.span, E0169, "parenthesized parameters may only be used with a trait"); - (Vec::new(), convert_parenthesized_parameters(this, data)) + (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new()) } }; - create_substs_for_ast_path(this, rscope, path.span, decl_def_id, - decl_generics, self_ty, types, regions) + create_substs_for_ast_path(this, + rscope, + path.span, + decl_def_id, + decl_generics, + None, + types, + regions, + assoc_bindings) } fn create_substs_for_ast_path<'tcx,AC,RS>( @@ -248,7 +259,8 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( decl_generics: &ty::Generics<'tcx>, self_ty: Option>, types: Vec>, - regions: Vec) + regions: Vec, + assoc_bindings: Vec<(ast::Ident, Ty<'tcx>)>) -> Substs<'tcx> where AC: AstConv<'tcx>, RS: RegionScope { @@ -355,13 +367,49 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( } } - for param in decl_generics.types.get_slice(AssocSpace).iter() { - substs.types.push( - AssocSpace, - this.associated_type_binding(span, - self_ty, - decl_def_id, - param.def_id)); + let mut matched_assoc = 0u; + for formal_assoc in decl_generics.types.get_slice(AssocSpace).iter() { + let mut found = false; + for &(ident, ty) in assoc_bindings.iter() { + if formal_assoc.name.ident() == ident { + substs.types.push(AssocSpace, ty); + matched_assoc += 1; + found = true; + break; + } + } + if !found { + match this.associated_type_binding(span, + self_ty, + decl_def_id, + formal_assoc.def_id) { + Some(ty) => { + substs.types.push(AssocSpace, ty); + matched_assoc += 1; + } + None => { + span_err!(this.tcx().sess, span, E0179, + "missing type for associated type `{}`", + token::get_ident(formal_assoc.name.ident())); + } + } + } + } + + if decl_generics.types.get_slice(AssocSpace).len() != matched_assoc { + span_err!(tcx.sess, span, E0171, + "wrong number of associated type parameters: expected {}, found {}", + decl_generics.types.get_slice(AssocSpace).len(), matched_assoc); + } + + for &(ident, _) in assoc_bindings.iter() { + let mut formal_idents = decl_generics.types.get_slice(AssocSpace) + .iter().map(|t| t.name.ident()); + if !formal_idents.any(|i| i == ident) { + span_err!(this.tcx().sess, span, E0177, + "associated type `{}` does not exist", + token::get_ident(ident)); + } } return substs; @@ -370,7 +418,9 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC, rscope: &RS, data: &ast::AngleBracketedParameterData) - -> (Vec, Vec>) + -> (Vec, + Vec>, + Vec<(ast::Ident, Ty<'tcx>)>) where AC: AstConv<'tcx>, RS: RegionScope { let regions: Vec<_> = @@ -383,7 +433,12 @@ fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC, .map(|t| ast_ty_to_ty(this, rscope, &**t)) .collect(); - (regions, types) + let assoc_bindings: Vec<_> = + data.bindings.iter() + .map(|b| (b.ident, ast_ty_to_ty(this, rscope, &*b.ty))) + .collect(); + + (regions, types, assoc_bindings) } /// Returns the appropriate lifetime to use for any output lifetimes @@ -484,7 +539,8 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>( pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC, rscope: &RS, ast_trait_ref: &ast::TraitRef, - self_ty: Option>) + self_ty: Option>, + allow_eq: AllowEqConstraints) -> Rc> where AC: AstConv<'tcx>, RS: RegionScope @@ -493,8 +549,12 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC, ast_trait_ref.path.span, ast_trait_ref.ref_id) { def::DefTrait(trait_def_id) => { - let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id, - self_ty, &ast_trait_ref.path)); + let trait_ref = Rc::new(ast_path_to_trait_ref(this, + rscope, + trait_def_id, + self_ty, + &ast_trait_ref.path, + allow_eq)); this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone()); trait_ref @@ -507,15 +567,23 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC, } } +#[deriving(PartialEq,Show)] +pub enum AllowEqConstraints { + Allow, + DontAllow +} + fn ast_path_to_trait_ref<'tcx,AC,RS>( this: &AC, rscope: &RS, trait_def_id: ast::DefId, self_ty: Option>, - path: &ast::Path) + path: &ast::Path, + allow_eq: AllowEqConstraints) -> ty::TraitRef<'tcx> where AC: AstConv<'tcx>, RS: RegionScope { + debug!("ast_path_to_trait_ref {}", path); let trait_def = this.get_trait_def(trait_def_id); // the trait reference introduces a binding level here, so @@ -525,15 +593,20 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>( // lifetimes. Oh well, not there yet. let shifted_rscope = ShiftedRscope::new(rscope); - let (regions, types) = match path.segments.last().unwrap().parameters { + let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters { ast::AngleBracketedParameters(ref data) => { convert_angle_bracketed_parameters(this, &shifted_rscope, data) } ast::ParenthesizedParameters(ref data) => { - (Vec::new(), convert_parenthesized_parameters(this, data)) + (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new()) } }; + if allow_eq == AllowEqConstraints::DontAllow && assoc_bindings.len() > 0 { + span_err!(this.tcx().sess, path.span, E0173, + "equality constraints are not allowed in this position"); + } + let substs = create_substs_for_ast_path(this, &shifted_rscope, path.span, @@ -541,7 +614,8 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>( &trait_def.generics, self_ty, types, - regions); + regions, + assoc_bindings); ty::TraitRef::new(trait_def_id, substs) } @@ -693,7 +767,8 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, rscope, trait_def_id, None, - path)); + path, + AllowEqConstraints::Allow)); } _ => { span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait"); @@ -772,7 +847,8 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC, let trait_ref = instantiate_trait_ref(this, rscope, &*qpath.trait_ref, - Some(self_type)); + Some(self_type), + AllowEqConstraints::DontAllow); debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx())); @@ -916,7 +992,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( rscope, trait_def_id, None, - path); + path, + AllowEqConstraints::Allow); trait_ref_to_object_type(this, rscope, path.span, result, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { @@ -1336,7 +1413,11 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) { Some(trait_bound) => { - Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None)) + Some(instantiate_trait_ref(this, + rscope, + &trait_bound.trait_ref, + None, + AllowEqConstraints::Allow)) } None => { this.tcx().sess.span_err( diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 6ff276edbce..3fa1234ee6e 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -318,7 +318,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { substs: rcvr_substs.clone() }); - self.elaborate_bounds(&[trait_ref.clone()], |this, new_trait_ref, m, method_num| { + self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| { let vtable_index = get_method_index(tcx, &*new_trait_ref, trait_ref.clone(), method_num); @@ -365,7 +365,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { let bounds = self.fcx.inh.param_env.bounds.get(space, index).trait_bounds .as_slice(); - self.elaborate_bounds(bounds, |this, trait_ref, m, method_num| { + self.elaborate_bounds(bounds, true, |this, trait_ref, m, method_num| { let xform_self_ty = this.xform_self_ty(&m, &trait_ref.substs); @@ -402,6 +402,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn elaborate_bounds( &mut self, bounds: &[Rc>], + num_includes_types: bool, mk_cand: for<'a> |this: &mut ProbeContext<'a, 'tcx>, tr: Rc>, m: Rc>, @@ -415,7 +416,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { continue; } - let (pos, method) = match trait_method(tcx, bound_trait_ref.def_id, self.method_name) { + let (pos, method) = match trait_method(tcx, + bound_trait_ref.def_id, + self.method_name, + num_includes_types) { Some(v) => v, None => { continue; } }; @@ -988,12 +992,18 @@ fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, /// index (or `None`, if no such method). fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, trait_def_id: ast::DefId, - method_name: ast::Name) + method_name: ast::Name, + num_includes_types: bool) -> Option<(uint, Rc>)> { let trait_items = ty::trait_items(tcx, trait_def_id); trait_items .iter() + .filter(|item| + num_includes_types || match *item { + &ty::MethodTraitItem(_) => true, + &ty::TypeTraitItem(_) => false + }) .enumerate() .find(|&(_, ref item)| item.name() == method_name) .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m))) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1a8b06ec12d..6a7f6bd0ea1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -112,7 +112,7 @@ use std::collections::hash_map::{Occupied, Vacant}; use std::mem::replace; use std::rc::Rc; use syntax::{mod, abi, attr}; -use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem}; +use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId}; use syntax::ast_util::{mod, local_def, PostExpansionMethod}; use syntax::codemap::{mod, Span}; use syntax::owned_slice::OwnedSlice; @@ -1585,9 +1585,9 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { _: Option>, _: ast::DefId, _: ast::DefId) - -> Ty<'tcx> { + -> Option> { self.tcx().sess.span_err(span, "unsupported associated type binding"); - ty::mk_err() + Some(ty::mk_err()) } } @@ -5152,12 +5152,18 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } Some(space) => { + let trait_def_id = match def { + def::DefTrait(did) => Some(did), + _ => None + }; push_explicit_parameters_from_segment_to_substs(fcx, space, path.span, type_defs, region_defs, segment, + trait_def_id, + path.span, &mut substs); } } @@ -5244,12 +5250,14 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, type_defs: &VecPerParamSpace>, region_defs: &VecPerParamSpace, segment: &ast::PathSegment, + trait_def_id: Option, + path_span: Span, substs: &mut Substs<'tcx>) { match segment.parameters { ast::AngleBracketedParameters(ref data) => { push_explicit_angle_bracketed_parameters_from_segment_to_substs( - fcx, space, type_defs, region_defs, data, substs); + fcx, space, type_defs, region_defs, data, trait_def_id, path_span, substs); } ast::ParenthesizedParameters(ref data) => { @@ -5265,6 +5273,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, type_defs: &VecPerParamSpace>, region_defs: &VecPerParamSpace, data: &ast::AngleBracketedParameterData, + trait_def_id: Option, + path_span: Span, substs: &mut Substs<'tcx>) { { @@ -5281,8 +5291,54 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, found {} parameter(s)", type_count, data.types.len()); substs.types.truncate(space, 0); + break; + } + } + } + + if let Some(trait_def_id) = trait_def_id { + let ref items = fcx.tcx().trait_item_def_ids.borrow()[trait_def_id]; + let mut assoc_tys = Vec::new(); + for item in items.iter() { + if let &ty::ImplOrTraitItemId::TypeTraitItemId(id) = item { + if let ty::ImplOrTraitItem::TypeTraitItem(ref ty) = + fcx.tcx().impl_or_trait_items.borrow()[id] { + assoc_tys.push(ty.clone()); + } + } + } + + if data.bindings.len() > assoc_tys.len() { + span_err!(fcx.tcx().sess, data.bindings[assoc_tys.len()].span, E0174, + "too many type equality constraints provided: \ + expected at most {} constraint(s), \ + found {} constraint(s)", + assoc_tys.len(), data.types.len()); + substs.types.truncate(space, 0); + } else if data.bindings.len() > 0 { + for assoc_ty in assoc_tys.iter() { + let mut matched = false; + for binding in data.bindings.iter() { + if assoc_ty.name.ident() == binding.ident { + let t = fcx.to_ty(&*binding.ty); + substs.types.push(space, t); + matched = true; + break; + } + } + if !matched { + span_err!(fcx.tcx().sess, path_span, E0176, + "missing type equality constraint for associated type: {}", + assoc_ty.name); + substs.types.truncate(space, 0); + break; + } } } + } else if data.bindings.len() > 0 { + span_err!(fcx.tcx().sess, path_span, E0175, + "type equality constraints provided on a non-trait type"); + substs.types.truncate(space, 0); } { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 74ac9c480de..32892aa94ee 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -32,7 +32,7 @@ as `ty_param()` instances. use self::ConvertMethodContext::*; use self::CreateTypeParametersForAssociatedTypesFlag::*; -use astconv::{AstConv, ty_of_arg}; +use astconv::{AstConv, ty_of_arg, AllowEqConstraints}; use astconv::{ast_ty_to_ty, ast_region_to_region}; use astconv; use metadata::csearch; @@ -197,10 +197,10 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> { _: Option>, _: ast::DefId, _: ast::DefId) - -> Ty<'tcx> { + -> Option> { self.tcx().sess.span_err(span, "associated types may not be \ referenced here"); - ty::mk_err() + Some(ty::mk_err()) } } @@ -782,7 +782,7 @@ impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> { ast::MethodImplItem(_) => {} ast::TypeImplItem(ref typedef) => { if associated_type.name() == typedef.ident.name { - return self.ccx.to_ty(&ExplicitRscope, &*typedef.typ) + return Some(self.ccx.to_ty(&ExplicitRscope, &*typedef.typ)) } } } @@ -943,10 +943,10 @@ impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> { fn associated_type_binding(&self, span: Span, - ty: Option>, + self_ty: Option>, trait_id: ast::DefId, associated_type_id: ast::DefId) - -> Ty<'tcx> { + -> Option> { debug!("collect::TraitMethodCtxt::associated_type_binding()"); // If this is one of our own associated types, return it. @@ -957,10 +957,10 @@ impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> { ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} ast::TypeTraitItem(ref item) => { if local_def(item.ty_param.id) == associated_type_id { - return ty::mk_param(self.tcx(), - subst::AssocSpace, - index, - associated_type_id) + return Some(ty::mk_param(self.tcx(), + subst::AssocSpace, + index, + associated_type_id)) } index += 1; } @@ -1142,8 +1142,11 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { parent_visibility); for trait_ref in opt_trait_ref.iter() { - astconv::instantiate_trait_ref(&icx, &ExplicitRscope, trait_ref, - Some(selfty)); + astconv::instantiate_trait_ref(&icx, + &ExplicitRscope, + trait_ref, + Some(selfty), + AllowEqConstraints::DontAllow); } }, ast::ItemTrait(_, _, _, ref trait_methods) => { @@ -1838,8 +1841,17 @@ fn ty_generics<'tcx,AC>(this: &AC, let trait_def = ty::lookup_trait_def(this.tcx(), trait_def_id); let associated_type_defs = trait_def.generics.types.get_slice(subst::AssocSpace); + // Find any assocaited type bindings in the bound. + let ref segments = ast_trait_ref.trait_ref.path.segments; + let bindings = segments[segments.len() -1].parameters.bindings(); + // Iterate over each associated type `Elem` for associated_type_def in associated_type_defs.iter() { + if bindings.iter().any(|b| associated_type_def.name.ident() == b.ident) { + // Don't add a variable for a bound associated type. + continue; + } + // Create the fresh type parameter `A` let def = ty::TypeParameterDef { name: associated_type_def.name, @@ -1998,10 +2010,11 @@ fn conv_param_bounds<'tcx,AC>(this: &AC, let trait_bounds: Vec> = trait_bounds.into_iter() .map(|bound| { - astconv::instantiate_poly_trait_ref(this, - &ExplicitRscope, - bound, - Some(param_ty.to_ty(this.tcx()))) + astconv::instantiate_trait_ref(this, + &ExplicitRscope, + &bound.trait_ref, + Some(param_ty.to_ty(this.tcx())), + AllowEqConstraints::Allow) }) .collect(); let region_bounds: Vec = @@ -2029,18 +2042,23 @@ fn merge_param_bounds<'a>(tcx: &ty::ctxt, } for predicate in where_clause.predicates.iter() { - let predicate_param_id = - tcx.def_map - .borrow() - .get(&predicate.id) - .expect("compute_bounds(): resolve didn't resolve the type \ - parameter identifier in a `where` clause") - .def_id(); - if param_ty.def_id != predicate_param_id { - continue - } - for bound in predicate.bounds.iter() { - result.push(bound); + match predicate { + &ast::BoundPredicate(ref bound_pred) => { + let predicate_param_id = + tcx.def_map + .borrow() + .get(&bound_pred.id) + .expect("merge_param_bounds(): resolve didn't resolve the \ + type parameter identifier in a `where` clause") + .def_id(); + if param_ty.def_id != predicate_param_id { + continue + } + for bound in bound_pred.bounds.iter() { + result.push(bound); + } + } + &ast::EqPredicate(_) => panic!("not implemented") } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 11af1a43277..ea8de458ce2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -255,6 +255,7 @@ impl PathParameters { AngleBracketedParameters(AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) } @@ -307,6 +308,17 @@ impl PathParameters { } } } + + pub fn bindings(&self) -> Vec<&P> { + match *self { + AngleBracketedParameters(ref data) => { + data.bindings.iter().collect() + } + ParenthesizedParameters(_) => { + Vec::new() + } + } + } } /// A path like `Foo<'a, T>` @@ -316,11 +328,14 @@ pub struct AngleBracketedParameterData { pub lifetimes: Vec, /// The type parameters for this path segment, if present. pub types: OwnedSlice>, + /// Bindings (equality constraints) on associated types, if present. + /// E.g., `Foo`. + pub bindings: OwnedSlice>, } impl AngleBracketedParameterData { fn is_empty(&self) -> bool { - self.lifetimes.is_empty() && self.types.is_empty() + self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty() } } @@ -406,13 +421,27 @@ pub struct WhereClause { } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] -pub struct WherePredicate { +pub enum WherePredicate { + BoundPredicate(WhereBoundPredicate), + EqPredicate(WhereEqPredicate) +} + +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct WhereBoundPredicate { pub id: NodeId, pub span: Span, pub ident: Ident, pub bounds: OwnedSlice, } +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct WhereEqPredicate { + pub id: NodeId, + pub span: Span, + pub path: Path, + pub ty: P, +} + /// The set of MetaItems that define the compilation environment of the crate, /// used to drive conditional compilation pub type CrateConfig = Vec> ; @@ -1118,6 +1147,16 @@ impl FloatTy { } } +// Bind a type to an associated type: `A=Foo`. +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct TypeBinding { + pub id: NodeId, + pub ident: Ident, + pub ty: P, + pub span: Span, +} + + // NB PartialEq method appears below. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Ty { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 7dba6a57fc4..eec3f69ee64 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -174,12 +174,28 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) } ), } } +// If path is a single segment ident path, return that ident. Otherwise, return +// None. +pub fn path_to_ident(path: &Path) -> Option { + if path.segments.len() != 1 { + return None; + } + + let segment = &path.segments[0]; + if !segment.parameters.is_empty() { + return None; + } + + Some(segment.identifier) +} + pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> P { P(Pat { id: id, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index b4bb1a1a529..84040bcfa9f 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -37,7 +37,8 @@ pub trait AstBuilder { global: bool, idents: Vec , lifetimes: Vec, - types: Vec> ) + types: Vec>, + bindings: Vec> ) -> ast::Path; // types @@ -293,20 +294,21 @@ pub trait AstBuilder { impl<'a> AstBuilder for ExtCtxt<'a> { fn path(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, false, strs, Vec::new(), Vec::new()) + self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new()) } fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path { self.path(span, vec!(id)) } fn path_global(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, true, strs, Vec::new(), Vec::new()) + self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) } fn path_all(&self, sp: Span, global: bool, mut idents: Vec , lifetimes: Vec, - types: Vec> ) + types: Vec>, + bindings: Vec> ) -> ast::Path { let last_identifier = idents.pop().unwrap(); let mut segments: Vec = idents.into_iter() @@ -321,6 +323,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }) }); ast::Path { @@ -391,7 +394,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.ident_of("Option") ), Vec::new(), - vec!( ty ))) + vec!( ty ), + Vec::new())) } fn ty_field_imm(&self, span: Span, name: Ident, ty: P) -> ast::TypeField { diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index d5f472bd827..cf3b3ad9051 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -444,7 +444,7 @@ impl<'a> TraitDef<'a> { // Create the type of `self`. let self_type = cx.ty_path( cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes, - self_ty_params.into_vec())); + self_ty_params.into_vec(), Vec::new())); let attr = cx.attribute( self.span, diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index 01398273161..56d11c2377f 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -80,7 +80,7 @@ impl<'a> Path<'a> { let lt = mk_lifetimes(cx, span, &self.lifetime); let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); - cx.path_all(span, self.global, idents, lt, tys) + cx.path_all(span, self.global, idents, lt, tys, Vec::new()) } } @@ -177,7 +177,7 @@ impl<'a> Ty<'a> { .collect(); cx.path_all(span, false, vec!(self_ty), lifetimes, - self_params.into_vec()) + self_params.into_vec(), Vec::new()) } Literal(ref p) => { p.to_path(cx, span, self_ty, self_generics) diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 8ad8436906b..c4e64d58c29 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -88,6 +88,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) true, rand_ident.clone(), Vec::new(), + Vec::new(), Vec::new()); let rand_name = cx.expr_path(rand_name); diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index e6a44c57f1b..8c17b31f458 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -45,7 +45,8 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT Some(cx.lifetime(sp, cx.ident_of( "'static").name)), - ast::MutImmutable)))) + ast::MutImmutable)), + Vec::new())) } Some(s) => { cx.expr_call_global(sp, diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index c8fed3dcd16..5d595474e9c 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -530,6 +530,7 @@ impl<'a, 'b> Context<'a, 'b> { self.fmtsp, true, Context::rtpath(self.ecx, "Argument"), vec![static_lifetime], + vec![], vec![] )); lets.push(Context::item_static_array(self.ecx, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 122f99cabb3..69e311c57f5 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -146,6 +146,10 @@ pub trait Folder { noop_fold_qpath(t, self) } + fn fold_ty_binding(&mut self, t: P) -> P { + noop_fold_ty_binding(t, self) + } + fn fold_mod(&mut self, m: Mod) -> Mod { noop_fold_mod(m, self) } @@ -391,6 +395,15 @@ pub fn noop_fold_decl(d: P, fld: &mut T) -> SmallVector }) } +pub fn noop_fold_ty_binding(b: P, fld: &mut T) -> P { + b.map(|TypeBinding { id, ident, ty, span }| TypeBinding { + id: fld.new_id(id), + ident: ident, + ty: fld.fold_ty(ty), + span: fld.new_span(span), + }) +} + pub fn noop_fold_ty(t: P, fld: &mut T) -> P { t.map(|Ty {id, node, span}| Ty { id: fld.new_id(id), @@ -533,9 +546,10 @@ pub fn noop_fold_angle_bracketed_parameter_data(data: AngleBracketedP fld: &mut T) -> AngleBracketedParameterData { - let AngleBracketedParameterData { lifetimes, types } = data; + let AngleBracketedParameterData { lifetimes, types, bindings } = data; AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes), - types: types.move_map(|ty| fld.fold_ty(ty)) } + types: types.move_map(|ty| fld.fold_ty(ty)), + bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) } } pub fn noop_fold_parenthesized_parameter_data(data: ParenthesizedParameterData, @@ -807,14 +821,32 @@ pub fn noop_fold_where_clause( } pub fn noop_fold_where_predicate( - WherePredicate {id, ident, bounds, span}: WherePredicate, + pred: WherePredicate, fld: &mut T) -> WherePredicate { - WherePredicate { - id: fld.new_id(id), - ident: fld.fold_ident(ident), - bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), - span: fld.new_span(span) + match pred { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{id, + ident, + bounds, + span}) => { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + id: fld.new_id(id), + ident: fld.fold_ident(ident), + bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), + span: fld.new_span(span) + }) + } + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, + path, + ty, + span}) => { + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ + id: fld.new_id(id), + path: fld.fold_path(path), + ty:fld.fold_ty(ty), + span: fld.new_span(span) + }) + } } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4929ee885ac..92c7380a61d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -53,7 +53,7 @@ use ast::{StructVariantKind, BiSub, StrStyle}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; use ast::{TtDelimited, TtSequence, TtToken}; -use ast::{TupleVariantKind, Ty, Ty_}; +use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; @@ -62,7 +62,7 @@ use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; use ast::{UnnamedField, UnsafeBlock}; use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; -use ast::{Visibility, WhereClause, WherePredicate}; +use ast::{Visibility, WhereClause}; use ast; use ast_util::{mod, as_prec, ident_to_path, operator_prec}; use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp}; @@ -769,13 +769,10 @@ impl<'a> Parser<'a> { } } - /// Parse a sequence bracketed by '<' and '>', stopping - /// before the '>'. - pub fn parse_seq_to_before_gt( - &mut self, - sep: Option, - f: |&mut Parser| -> T) - -> OwnedSlice { + pub fn parse_seq_to_before_gt_or_return(&mut self, + sep: Option, + f: |&mut Parser| -> Option) + -> (OwnedSlice, bool) { let mut v = Vec::new(); // This loop works by alternating back and forth between parsing types // and commas. For example, given a string `A, B,>`, the parser would @@ -792,24 +789,48 @@ impl<'a> Parser<'a> { } if i % 2 == 0 { - v.push(f(self)); + match f(self) { + Some(result) => v.push(result), + None => return (OwnedSlice::from_vec(v), true) + } } else { sep.as_ref().map(|t| self.expect(t)); } } - return OwnedSlice::from_vec(v); + return (OwnedSlice::from_vec(v), false); + } + + /// Parse a sequence bracketed by '<' and '>', stopping + /// before the '>'. + pub fn parse_seq_to_before_gt(&mut self, + sep: Option, + f: |&mut Parser| -> T) + -> OwnedSlice { + let (result, returned) = self.parse_seq_to_before_gt_or_return(sep, |p| Some(f(p))); + assert!(!returned); + return result; } - pub fn parse_seq_to_gt( - &mut self, - sep: Option, - f: |&mut Parser| -> T) - -> OwnedSlice { + pub fn parse_seq_to_gt(&mut self, + sep: Option, + f: |&mut Parser| -> T) + -> OwnedSlice { let v = self.parse_seq_to_before_gt(sep, f); self.expect_gt(); return v; } + pub fn parse_seq_to_gt_or_return(&mut self, + sep: Option, + f: |&mut Parser| -> Option) + -> (OwnedSlice, bool) { + let (v, returned) = self.parse_seq_to_before_gt_or_return(sep, f); + if !returned { + self.expect_gt(); + } + return (v, returned); + } + /// Parse a sequence, including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. @@ -1842,11 +1863,12 @@ impl<'a> Parser<'a> { // Parse types, optionally. let parameters = if self.eat_lt(false) { - let (lifetimes, types) = self.parse_generic_values_after_lt(); + let (lifetimes, types, bindings) = self.parse_generic_values_after_lt(); ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }) } else if self.eat(&token::OpenDelim(token::Paren)) { let inputs = self.parse_seq_to_end( @@ -1894,6 +1916,7 @@ impl<'a> Parser<'a> { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) }); return segments; @@ -1902,12 +1925,13 @@ impl<'a> Parser<'a> { // Check for a type segment. if self.eat_lt(false) { // Consumed `a::b::<`, go look for types - let (lifetimes, types) = self.parse_generic_values_after_lt(); + let (lifetimes, types, bindings) = self.parse_generic_values_after_lt(); segments.push(ast::PathSegment { identifier: identifier, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }), }); @@ -2435,13 +2459,18 @@ impl<'a> Parser<'a> { let dot = self.last_span.hi; hi = self.span.hi; self.bump(); - let (_, tys) = if self.eat(&token::ModSep) { + let (_, tys, bindings) = if self.eat(&token::ModSep) { self.expect_lt(); self.parse_generic_values_after_lt() } else { - (Vec::new(), Vec::new()) + (Vec::new(), Vec::new(), Vec::new()) }; + if bindings.len() > 0 { + let last_span = self.last_span; + self.span_err(last_span, "type bindings are only permitted on trait paths"); + } + // expr.f() method call match self.token { token::OpenDelim(token::Paren) => { @@ -4041,16 +4070,51 @@ impl<'a> Parser<'a> { } } - fn parse_generic_values_after_lt(&mut self) -> (Vec, Vec> ) { + fn parse_generic_values_after_lt(&mut self) + -> (Vec, Vec>, Vec>) { let lifetimes = self.parse_lifetimes(token::Comma); - let result = self.parse_seq_to_gt( + + // First parse types. + let (types, returned) = self.parse_seq_to_gt_or_return( + Some(token::Comma), + |p| { + p.forbid_lifetime(); + if p.look_ahead(1, |t| t == &token::Eq) { + None + } else { + Some(p.parse_ty_sum()) + } + } + ); + + // If we found the `>`, don't continue. + if !returned { + return (lifetimes, types.into_vec(), Vec::new()); + } + + // Then parse type bindings. + let bindings = self.parse_seq_to_gt( Some(token::Comma), |p| { p.forbid_lifetime(); - p.parse_ty_sum() + let lo = p.span.lo; + let ident = p.parse_ident(); + let found_eq = p.eat(&token::Eq); + if !found_eq { + let span = p.span; + p.span_warn(span, "whoops, no =?"); + } + let ty = p.parse_ty(); + let hi = p.span.hi; + let span = mk_sp(lo, hi); + return P(TypeBinding{id: ast::DUMMY_NODE_ID, + ident: ident, + ty: ty, + span: span, + }); } ); - (lifetimes, result.into_vec()) + (lifetimes, types.into_vec(), bindings.into_vec()) } fn forbid_lifetime(&mut self) { @@ -4070,29 +4134,58 @@ impl<'a> Parser<'a> { let mut parsed_something = false; loop { let lo = self.span.lo; - let ident = match self.token { - token::Ident(..) => self.parse_ident(), + let path = match self.token { + token::Ident(..) => self.parse_path(NoTypesAllowed), _ => break, }; - self.expect(&token::Colon); - let bounds = self.parse_ty_param_bounds(); - let hi = self.span.hi; - let span = mk_sp(lo, hi); + if self.eat(&token::Colon) { + let bounds = self.parse_ty_param_bounds(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); - if bounds.len() == 0 { - self.span_err(span, - "each predicate in a `where` clause must have \ - at least one bound in it"); - } + if bounds.len() == 0 { + self.span_err(span, + "each predicate in a `where` clause must have \ + at least one bound in it"); + } - generics.where_clause.predicates.push(ast::WherePredicate { - id: ast::DUMMY_NODE_ID, - span: span, - ident: ident, - bounds: bounds, - }); - parsed_something = true; + let ident = match ast_util::path_to_ident(&path) { + Some(ident) => ident, + None => { + self.span_err(path.span, "expected a single identifier \ + in bound where clause"); + break; + } + }; + + generics.where_clause.predicates.push( + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + id: ast::DUMMY_NODE_ID, + span: span, + ident: ident, + bounds: bounds, + })); + parsed_something = true; + } else if self.eat(&token::Eq) { + let ty = self.parse_ty(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); + generics.where_clause.predicates.push( + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + id: ast::DUMMY_NODE_ID, + span: span, + path: path, + ty: ty, + })); + parsed_something = true; + // FIXME(#18433) + self.span_err(span, "equality constraints are not yet supported in where clauses"); + } else { + let last_span = self.last_span; + self.span_err(last_span, + "unexpected token in `where` clause"); + } if !self.eat(&token::Comma) { break diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index eab03f73091..26373d00aaf 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1976,6 +1976,18 @@ impl<'a> State<'a> { Inconsistent, data.types.as_slice(), |s, ty| s.print_type(&**ty))); + comma = true; + } + + for binding in data.bindings.iter() { + if comma { + try!(self.word_space(",")) + } + try!(self.print_ident(binding.ident)); + try!(space(&mut self.s)); + try!(self.word_space("=")); + try!(self.print_type(&*binding.ty)); + comma = true; } try!(word(&mut self.s, ">")) @@ -2437,8 +2449,20 @@ impl<'a> State<'a> { try!(self.word_space(",")); } - try!(self.print_ident(predicate.ident)); - try!(self.print_bounds(":", predicate.bounds.as_slice())); + match predicate { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ident, + ref bounds, + ..}) => { + try!(self.print_ident(ident)); + try!(self.print_bounds(":", bounds.as_slice())); + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { + try!(self.print_path(path, false)); + try!(space(&mut self.s)); + try!(self.word_space("=")); + try!(self.print_type(&**ty)); + } + } } Ok(()) diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f5e89dd61ff..a36f8b23ca3 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -573,8 +573,22 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics } walk_lifetime_decls_helper(visitor, &generics.lifetimes); for predicate in generics.where_clause.predicates.iter() { - visitor.visit_ident(predicate.span, predicate.ident); - walk_ty_param_bounds_helper(visitor, &predicate.bounds); + match predicate { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{span, + ident, + ref bounds, + ..}) => { + visitor.visit_ident(span, ident); + walk_ty_param_bounds_helper(visitor, bounds); + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, + ref path, + ref ty, + ..}) => { + visitor.visit_path(path, id); + visitor.visit_ty(&**ty); + } + } } } diff --git a/src/test/compile-fail/assoc-eq-1.rs b/src/test/compile-fail/assoc-eq-1.rs new file mode 100644 index 00000000000..4fd53150618 --- /dev/null +++ b/src/test/compile-fail/assoc-eq-1.rs @@ -0,0 +1,27 @@ +// Copyright 2014 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. + +// Test equality constraints on associated types. Check that unsupported syntax +// does not ICE. + +#![feature(associated_types)] + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +fn foo2(x: I) { + let _: A = x.boo(); //~ERROR use of undeclared + let _: I::A = x.boo(); //~ERROR failed to resolve + //~^ERROR use of undeclared type name `I::A` +} + +pub fn main() {} diff --git a/src/test/compile-fail/assoc-eq-2.rs b/src/test/compile-fail/assoc-eq-2.rs new file mode 100644 index 00000000000..652bf4fb577 --- /dev/null +++ b/src/test/compile-fail/assoc-eq-2.rs @@ -0,0 +1,30 @@ +// Copyright 2014 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. + +// Test equality constraints on associated types. Check we get an error when an +// equality constraint is used in a qualified path. + +#![feature(associated_types)] + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for int { + type A = uint; + fn boo(&self) -> uint { 42 } +} + +fn baz(x: &>::A) {} //~ERROR equality constraints are not allowed in this + +pub fn main() {} diff --git a/src/test/compile-fail/assoc-eq-3.rs b/src/test/compile-fail/assoc-eq-3.rs new file mode 100644 index 00000000000..880b2e9cc4a --- /dev/null +++ b/src/test/compile-fail/assoc-eq-3.rs @@ -0,0 +1,48 @@ +// Copyright 2014 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. + +// Test equality constraints on associated types. Check we get type errors +// where we should. + +#![feature(associated_types)] + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for int { + type A = uint; + fn boo(&self) -> uint { + 42 + } +} + +fn foo1>(x: I) { + let _: Bar = x.boo(); +} + +fn foo2(x: I) { + let _: Bar = x.boo(); //~ERROR mismatched types +} + + +pub fn baz(x: &Foo) { + let _: Bar = x.boo(); +} + + +pub fn main() { + let a = 42i; + foo1(a); //~ERROR the trait `Foo` is not implemented for the type `int` + baz(&a); //~ERROR the trait `Foo` is not implemented for the type `int` +} diff --git a/src/test/compile-fail/issue-3973.rs b/src/test/compile-fail/issue-3973.rs index 57bc1137912..e4f7521c333 100644 --- a/src/test/compile-fail/issue-3973.rs +++ b/src/test/compile-fail/issue-3973.rs @@ -31,6 +31,6 @@ impl ToString_ for Point { fn main() { let p = Point::new(0.0, 0.0); //~^ ERROR unresolved name `Point::new` - //~^^ ERROR failed to resolve. Use of undeclared module `Point` + //~^^ ERROR failed to resolve. Use of undeclared type or module `Point` println!("{}", p.to_string()); } diff --git a/src/test/compile-fail/macro-inner-attributes.rs b/src/test/compile-fail/macro-inner-attributes.rs index 3e731a2d2fe..4c4fb5572d6 100644 --- a/src/test/compile-fail/macro-inner-attributes.rs +++ b/src/test/compile-fail/macro-inner-attributes.rs @@ -25,7 +25,7 @@ test!(b, #[qux] fn main() { a::bar(); - //~^ ERROR failed to resolve. Use of undeclared module `a` + //~^ ERROR failed to resolve. Use of undeclared type or module `a` //~^^ ERROR unresolved name `a::bar` b::bar(); } diff --git a/src/test/run-pass/assoc-eq.rs b/src/test/run-pass/assoc-eq.rs new file mode 100644 index 00000000000..f1ba382b42d --- /dev/null +++ b/src/test/run-pass/assoc-eq.rs @@ -0,0 +1,55 @@ +// Copyright 2014 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. + +// Test equality constraints on associated types. + +#![feature(associated_types)] + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for int { + type A = uint; + fn boo(&self) -> uint { 42 } +} +impl Foo for Bar { + type A = int; + fn boo(&self) -> int { 43 } +} +impl Foo for char { + type A = Bar; + fn boo(&self) -> Bar { Bar } +} + +fn foo1>(x: I) -> Bar { + x.boo() +} +fn foo2(x: I) -> ::A { + x.boo() +} +fn baz(x: &Foo) -> Bar { + x.boo() +} + +pub fn main() { + let a = 42i; + assert!(foo2(a) == 42u); + + let a = Bar; + assert!(foo2(a) == 43i); + + let a = 'a'; + foo1(a); + baz(&a); +} -- cgit 1.4.1-3-g733a5 From 319c379bac07c6213ac4de817be0dac202a249f8 Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Thu, 11 Dec 2014 18:31:09 +0200 Subject: Add `Copy` to bitflags-generated structures --- src/librustc/middle/resolve.rs | 2 -- src/librustc/middle/ty.rs | 2 -- src/librustc_llvm/lib.rs | 1 - src/libstd/bitflags.rs | 10 +--------- src/libstd/io/mod.rs | 1 - src/libsyntax/parse/parser.rs | 1 - 6 files changed, 1 insertion(+), 16 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 36b87bbd423..840675d60bb 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -633,8 +633,6 @@ bitflags! { } } -impl Copy for DefModifiers {} - // Records a possibly-private type definition. #[deriving(Clone)] struct TypeNsDef { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 4c4b5d07f50..9435268c2ef 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -800,8 +800,6 @@ bitflags! { } } -impl Copy for TypeFlags {} - #[deriving(Show)] pub struct TyS<'tcx> { pub sty: sty<'tcx>, diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 23dad21e530..f6ac6fb6c70 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -149,7 +149,6 @@ bitflags! { } } -impl Copy for Attribute {} #[repr(u64)] pub enum OtherAttribute { diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index ffcd6505dad..8a6d329ec46 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -33,8 +33,6 @@ /// } /// } /// -/// impl Copy for Flags {} -/// /// fn main() { /// let e1 = FLAG_A | FLAG_C; /// let e2 = FLAG_B | FLAG_C; @@ -57,8 +55,6 @@ /// } /// } /// -/// impl Copy for Flags {} -/// /// impl Flags { /// pub fn clear(&mut self) { /// self.bits = 0; // The `bits` field can be accessed from within the @@ -121,7 +117,7 @@ macro_rules! bitflags { ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty { $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ }) => { - #[deriving(PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] + #[deriving(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] $(#[$attr])* pub struct $BitFlags { bits: $T, @@ -288,16 +284,12 @@ mod tests { } } - impl Copy for Flags {} - bitflags! { flags AnotherSetOfFlags: i8 { const AnotherFlag = -1_i8, } } - impl Copy for AnotherSetOfFlags {} - #[test] fn test_bits(){ assert_eq!(Flags::empty().bits(), 0x00000000); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index dc212e7cab3..8be48114418 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1904,7 +1904,6 @@ bitflags! { } } -impl Copy for FilePermission {} impl Default for FilePermission { #[inline] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4929ee885ac..ab398603b61 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -98,7 +98,6 @@ bitflags! { } } -impl Copy for Restrictions {} type ItemInfo = (Ident, Item_, Option >); -- cgit 1.4.1-3-g733a5 From 0dac05dd627612232403c07ca8bd6d3376eec64a Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 8 Dec 2014 13:28:32 -0500 Subject: libsyntax: use unboxed closures --- src/libsyntax/ast_map/blocks.rs | 15 ++-- src/libsyntax/ast_map/mod.rs | 12 ++- src/libsyntax/ast_util.rs | 11 +-- src/libsyntax/attr.rs | 7 +- src/libsyntax/codemap.rs | 4 +- src/libsyntax/config.rs | 82 +++++++++++++----- src/libsyntax/diagnostic.rs | 4 +- src/libsyntax/diagnostics/plugin.rs | 12 ++- src/libsyntax/ext/deriving/bounds.rs | 13 +-- src/libsyntax/ext/deriving/clone.rs | 12 +-- src/libsyntax/ext/deriving/cmp/eq.rs | 12 +-- src/libsyntax/ext/deriving/cmp/ord.rs | 12 +-- src/libsyntax/ext/deriving/cmp/totaleq.rs | 12 +-- src/libsyntax/ext/deriving/cmp/totalord.rs | 12 +-- src/libsyntax/ext/deriving/decodable.rs | 26 +++--- src/libsyntax/ext/deriving/default.rs | 12 +-- src/libsyntax/ext/deriving/encodable.rs | 12 +-- src/libsyntax/ext/deriving/generic/mod.rs | 62 ++++++++------ src/libsyntax/ext/deriving/hash.rs | 12 +-- src/libsyntax/ext/deriving/primitive.rs | 12 +-- src/libsyntax/ext/deriving/rand.rs | 28 +++--- src/libsyntax/ext/deriving/show.rs | 12 +-- src/libsyntax/ext/deriving/zero.rs | 12 +-- src/libsyntax/ext/expand.rs | 12 +-- src/libsyntax/ext/mtwt.rs | 12 ++- src/libsyntax/fold.rs | 6 +- src/libsyntax/parse/lexer/mod.rs | 8 +- src/libsyntax/parse/parser.rs | 132 ++++++++++++++++------------- src/libsyntax/print/pprust.rs | 30 ++++--- src/libsyntax/ptr.rs | 8 +- src/libsyntax/util/parser_testing.rs | 4 +- src/libsyntax/util/small_vector.rs | 2 +- 32 files changed, 377 insertions(+), 245 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 639a33a8063..75f69f2f6d0 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -181,22 +181,23 @@ impl<'a> FnLikeNode<'a> { } pub fn kind(self) -> visit::FnKind<'a> { - let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> { + let item = |: p: ItemFnParts<'a>| -> visit::FnKind<'a> { visit::FkItemFn(p.ident, p.generics, p.style, p.abi) }; - let closure = |_: ClosureParts| { + let closure = |: _: ClosureParts| { visit::FkFnBlock }; - let method = |m: &'a ast::Method| { + let method = |: m: &'a ast::Method| { visit::FkMethod(m.pe_ident(), m.pe_generics(), m) }; self.handle(item, method, closure) } - fn handle(self, - item_fn: |ItemFnParts<'a>| -> A, - method: |&'a ast::Method| -> A, - closure: |ClosureParts<'a>| -> A) -> A { + fn handle(self, item_fn: I, method: M, closure: C) -> A where + I: FnOnce(ItemFnParts<'a>) -> A, + M: FnOnce(&'a ast::Method) -> A, + C: FnOnce(ClosureParts<'a>) -> A, + { match self.node { ast_map::NodeItem(i) => match i.node { ast::ItemFn(ref decl, style, abi, ref generics, ref block) => diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 2c985f403f8..907ac6b19fc 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -424,7 +424,9 @@ impl<'ast> Map<'ast> { } } - pub fn with_path(&self, id: NodeId, f: |PathElems| -> T) -> T { + pub fn with_path(&self, id: NodeId, f: F) -> T where + F: FnOnce(PathElems) -> T, + { self.with_path_next(id, None, f) } @@ -438,7 +440,9 @@ impl<'ast> Map<'ast> { }) } - fn with_path_next(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -> T { + fn with_path_next(&self, id: NodeId, next: LinkedPath, f: F) -> T where + F: FnOnce(PathElems) -> T, + { let parent = self.get_parent(id); let parent = match self.find_entry(id) { Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => { @@ -470,7 +474,9 @@ impl<'ast> Map<'ast> { /// Given a node ID and a closure, apply the closure to the array /// of attributes associated with the AST corresponding to the Node ID - pub fn with_attrs(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T { + pub fn with_attrs(&self, id: NodeId, f: F) -> T where + F: FnOnce(Option<&[Attribute]>) -> T, + { let attrs = match self.get(id) { NodeItem(i) => Some(i.attrs.as_slice()), NodeForeignItem(fi) => Some(fi.attrs.as_slice()), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index eec3f69ee64..7579972c6d8 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -602,6 +602,7 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind, id_visitor.operation.result } +// FIXME(#19596) unbox `it` pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool { if !it(pat) { return false; @@ -632,21 +633,21 @@ pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool { } pub trait EachViewItem { - fn each_view_item(&self, f: |&ast::ViewItem| -> bool) -> bool; + fn each_view_item(&self, f: F) -> bool where F: FnMut(&ast::ViewItem) -> bool; } -struct EachViewItemData<'a> { - callback: |&ast::ViewItem|: 'a -> bool, +struct EachViewItemData where F: FnMut(&ast::ViewItem) -> bool { + callback: F, } -impl<'a, 'v> Visitor<'v> for EachViewItemData<'a> { +impl<'v, F> Visitor<'v> for EachViewItemData where F: FnMut(&ast::ViewItem) -> bool { fn visit_view_item(&mut self, view_item: &ast::ViewItem) { let _ = (self.callback)(view_item); } } impl EachViewItem for ast::Crate { - fn each_view_item(&self, f: |&ast::ViewItem| -> bool) -> bool { + fn each_view_item(&self, f: F) -> bool where F: FnMut(&ast::ViewItem) -> bool { let mut visit = EachViewItemData { callback: f, }; diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 5894a88ece6..8248eae4b8c 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -115,7 +115,8 @@ impl AttrMetaMethods for P { pub trait AttributeMethods { fn meta<'a>(&'a self) -> &'a MetaItem; - fn with_desugared_doc(&self, f: |&Attribute| -> T) -> T; + fn with_desugared_doc(&self, f: F) -> T where + F: FnOnce(&Attribute) -> T; } impl AttributeMethods for Attribute { @@ -127,7 +128,9 @@ impl AttributeMethods for Attribute { /// Convert self to a normal #[doc="foo"] comment, if it is a /// comment like `///` or `/** */`. (Returns self unchanged for /// non-sugared doc attributes.) - fn with_desugared_doc(&self, f: |&Attribute| -> T) -> T { + fn with_desugared_doc(&self, f: F) -> T where + F: FnOnce(&Attribute) -> T, + { if self.node.is_sugared_doc { let comment = self.value_str().unwrap(); let meta = mk_name_value_item_str( diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 7f2becf8201..d2fe667339c 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -568,7 +568,9 @@ impl CodeMap { ExpnId(expansions.len().to_u32().expect("too many ExpnInfo's!") - 1) } - pub fn with_expn_info(&self, id: ExpnId, f: |Option<&ExpnInfo>| -> T) -> T { + pub fn with_expn_info(&self, id: ExpnId, f: F) -> T where + F: FnOnce(Option<&ExpnInfo>) -> T, + { match id { NO_EXPANSION => f(None), ExpnId(i) => f(Some(&(*self.expansions.borrow())[i as uint])) diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 4f718555d53..87426dce918 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -19,8 +19,8 @@ use util::small_vector::SmallVector; /// A folder that strips out items that do not belong in the current /// configuration. -struct Context<'a> { - in_cfg: |attrs: &[ast::Attribute]|: 'a -> bool, +struct Context where F: FnMut(&[ast::Attribute]) -> bool { + in_cfg: F, } // Support conditional compilation by transforming the AST, stripping out @@ -30,7 +30,7 @@ pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> strip_items(krate, |attrs| in_cfg(diagnostic, config.as_slice(), attrs)) } -impl<'a> fold::Folder for Context<'a> { +impl fold::Folder for Context where F: FnMut(&[ast::Attribute]) -> bool { fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod { fold_mod(self, module) } @@ -54,16 +54,20 @@ impl<'a> fold::Folder for Context<'a> { } } -pub fn strip_items(krate: ast::Crate, - in_cfg: |attrs: &[ast::Attribute]| -> bool) - -> ast::Crate { +pub fn strip_items(krate: ast::Crate, in_cfg: F) -> ast::Crate where + F: FnMut(&[ast::Attribute]) -> bool, +{ let mut ctxt = Context { in_cfg: in_cfg, }; ctxt.fold_crate(krate) } -fn filter_view_item(cx: &mut Context, view_item: ast::ViewItem) -> Option { +fn filter_view_item(cx: &mut Context, + view_item: ast::ViewItem) + -> Option where + F: FnMut(&[ast::Attribute]) -> bool +{ if view_item_in_cfg(cx, &view_item) { Some(view_item) } else { @@ -71,7 +75,11 @@ fn filter_view_item(cx: &mut Context, view_item: ast::ViewItem) -> Option ast::Mod { +fn fold_mod(cx: &mut Context, + ast::Mod {inner, + view_items, items}: ast::Mod) -> ast::Mod where + F: FnMut(&[ast::Attribute]) -> bool +{ ast::Mod { inner: inner, view_items: view_items.into_iter().filter_map(|a| { @@ -83,8 +91,11 @@ fn fold_mod(cx: &mut Context, ast::Mod {inner, view_items, items}: ast::Mod) -> } } -fn filter_foreign_item(cx: &mut Context, item: P) - -> Option> { +fn filter_foreign_item(cx: &mut Context, + item: P) + -> Option> where + F: FnMut(&[ast::Attribute]) -> bool +{ if foreign_item_in_cfg(cx, &*item) { Some(item) } else { @@ -92,8 +103,11 @@ fn filter_foreign_item(cx: &mut Context, item: P) } } -fn fold_foreign_mod(cx: &mut Context, ast::ForeignMod {abi, view_items, items}: ast::ForeignMod) - -> ast::ForeignMod { +fn fold_foreign_mod(cx: &mut Context, + ast::ForeignMod {abi, view_items, items}: ast::ForeignMod) + -> ast::ForeignMod where + F: FnMut(&[ast::Attribute]) -> bool +{ ast::ForeignMod { abi: abi, view_items: view_items.into_iter().filter_map(|a| { @@ -105,7 +119,9 @@ fn fold_foreign_mod(cx: &mut Context, ast::ForeignMod {abi, view_items, items}: } } -fn fold_item(cx: &mut Context, item: P) -> SmallVector> { +fn fold_item(cx: &mut Context, item: P) -> SmallVector> where + F: FnMut(&[ast::Attribute]) -> bool +{ if item_in_cfg(cx, &*item) { SmallVector::one(item.map(|i| cx.fold_item_simple(i))) } else { @@ -113,7 +129,9 @@ fn fold_item(cx: &mut Context, item: P) -> SmallVector> } } -fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ { +fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ where + F: FnMut(&[ast::Attribute]) -> bool +{ let item = match item { ast::ItemImpl(a, b, c, impl_items) => { let impl_items = impl_items.into_iter() @@ -166,7 +184,9 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ { fold::noop_fold_item_underscore(item, cx) } -fn fold_struct(cx: &mut Context, def: P) -> P { +fn fold_struct(cx: &mut Context, def: P) -> P where + F: FnMut(&[ast::Attribute]) -> bool +{ def.map(|ast::StructDef { fields, ctor_id }| { ast::StructDef { fields: fields.into_iter().filter(|m| { @@ -177,7 +197,9 @@ fn fold_struct(cx: &mut Context, def: P) -> P { }) } -fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool { +fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ match stmt.node { ast::StmtDecl(ref decl, _) => { match decl.node { @@ -191,7 +213,9 @@ fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool { } } -fn fold_block(cx: &mut Context, b: P) -> P { +fn fold_block(cx: &mut Context, b: P) -> P where + F: FnMut(&[ast::Attribute]) -> bool +{ b.map(|ast::Block {id, view_items, stmts, expr, rules, span}| { let resulting_stmts: Vec> = stmts.into_iter().filter(|a| retain_stmt(cx, &**a)).collect(); @@ -212,7 +236,9 @@ fn fold_block(cx: &mut Context, b: P) -> P { }) } -fn fold_expr(cx: &mut Context, expr: P) -> P { +fn fold_expr(cx: &mut Context, expr: P) -> P where + F: FnMut(&[ast::Attribute]) -> bool +{ expr.map(|ast::Expr {id, span, node}| { fold::noop_fold_expr(ast::Expr { id: id, @@ -229,19 +255,27 @@ fn fold_expr(cx: &mut Context, expr: P) -> P { }) } -fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool { +fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ return (cx.in_cfg)(item.attrs.as_slice()); } -fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool { +fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ return (cx.in_cfg)(item.attrs.as_slice()); } -fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool { +fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ return (cx.in_cfg)(item.attrs.as_slice()); } -fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool { +fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ match *meth { ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()), ast::ProvidedMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()), @@ -249,7 +283,9 @@ fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool { } } -fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool { +fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ match *impl_item { ast::MethodImplItem(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()), ast::TypeImplItem(ref typ) => (cx.in_cfg)(typ.attrs.as_slice()), diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index bbda80bd96c..3a816987922 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -581,7 +581,9 @@ fn print_macro_backtrace(w: &mut EmitterWriter, cs.map_or(Ok(()), |call_site| print_macro_backtrace(w, cm, call_site)) } -pub fn expect(diag: &SpanHandler, opt: Option, msg: || -> String) -> T { +pub fn expect(diag: &SpanHandler, opt: Option, msg: M) -> T where + M: FnOnce() -> String, +{ match opt { Some(t) => t, None => diag.handler().bug(msg().as_slice()), diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 2be11a236d3..cb2a1f8acd8 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -25,14 +25,18 @@ thread_local!(static USED_DIAGNOSTICS: RefCell> = { RefCell::new(HashMap::new()) }) -fn with_registered_diagnostics(f: |&mut HashMap>| -> T) -> T { - REGISTERED_DIAGNOSTICS.with(|slot| { +fn with_registered_diagnostics(f: F) -> T where + F: FnOnce(&mut HashMap>) -> T, +{ + REGISTERED_DIAGNOSTICS.with(move |slot| { f(&mut *slot.borrow_mut()) }) } -fn with_used_diagnostics(f: |&mut HashMap| -> T) -> T { - USED_DIAGNOSTICS.with(|slot| { +fn with_used_diagnostics(f: F) -> T where + F: FnOnce(&mut HashMap) -> T, +{ + USED_DIAGNOSTICS.with(move |slot| { f(&mut *slot.borrow_mut()) }) } diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index 0595b0bc7f4..3145b3bb1a4 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -15,12 +15,13 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_bound(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { - +pub fn expand_deriving_bound(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let name = match mitem.node { MetaWord(ref tname) => { match tname.get() { diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index f6b8c00e761..a34764221b3 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_clone(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_clone(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 7727bb824db..c8bf5ec326c 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_eq(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_eq(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ // structures are equal if all fields are equal, and non equal, if // any fields are not equal or if the enum variants are different fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 1bd55b5d504..bd1962de56e 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -20,11 +20,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_ord(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_ord(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ macro_rules! md ( ($name:expr, $op:expr, $equal:expr) => { { let inline = cx.meta_word(span, InternedString::new("inline")); diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index ecee2008254..2b986bea122 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { cs_same_method(|cx, span, exprs| { // create `a.(); b.(); c.(); ...` diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 6900773f44d..a2bf46f41fc 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -18,11 +18,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_totalord(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_totalord(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index e3cf2b68752..0a8d59da896 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -21,11 +21,13 @@ use parse::token::InternedString; use parse::token; use ptr::P; -pub fn expand_deriving_decodable(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_decodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let trait_def = TraitDef { span: span, attributes: Vec::new(), @@ -155,12 +157,14 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, /// Create a decoder for a single enum variant/struct: /// - `outer_pat_path` is the path to this enum variant/struct /// - `getarg` should retrieve the `uint`-th field with name `@str`. -fn decode_static_fields(cx: &mut ExtCtxt, - trait_span: Span, - outer_pat_path: ast::Path, - fields: &StaticFields, - getarg: |&mut ExtCtxt, Span, InternedString, uint| -> P) - -> P { +fn decode_static_fields(cx: &mut ExtCtxt, + trait_span: Span, + outer_pat_path: ast::Path, + fields: &StaticFields, + mut getarg: F) + -> P where + F: FnMut(&mut ExtCtxt, Span, InternedString, uint) -> P, +{ match *fields { Unnamed(ref fields) => { let path_expr = cx.expr_path(outer_pat_path); diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index f4a66414d89..b3621490ce3 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_default(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_default(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 62f3b5d01b4..30851ebeaae 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -97,11 +97,13 @@ use ext::deriving::generic::ty::*; use parse::token; use ptr::P; -pub fn expand_deriving_encodable(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_encodable(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let trait_def = TraitDef { span: span, attributes: Vec::new(), diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index cf3b3ad9051..a75be40604e 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -333,11 +333,13 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) impl<'a> TraitDef<'a> { - pub fn expand(&self, - cx: &mut ExtCtxt, - mitem: &ast::MetaItem, - item: &ast::Item, - push: |P|) { + pub fn expand(&self, + cx: &mut ExtCtxt, + mitem: &ast::MetaItem, + item: &ast::Item, + push: F) where + F: FnOnce(P), + { let newitem = match item.node { ast::ItemStruct(ref struct_def, ref generics) => { self.expand_struct_def(cx, @@ -1309,14 +1311,16 @@ impl<'a> TraitDef<'a> { /// Fold the fields. `use_foldl` controls whether this is done /// left-to-right (`true`) or right-to-left (`false`). -pub fn cs_fold(use_foldl: bool, - f: |&mut ExtCtxt, Span, P, P, &[P]| -> P, - base: P, - enum_nonmatch_f: EnumNonMatchCollapsedFunc, - cx: &mut ExtCtxt, - trait_span: Span, - substructure: &Substructure) - -> P { +pub fn cs_fold(use_foldl: bool, + mut f: F, + base: P, + enum_nonmatch_f: EnumNonMatchCollapsedFunc, + cx: &mut ExtCtxt, + trait_span: Span, + substructure: &Substructure) + -> P where + F: FnMut(&mut ExtCtxt, Span, P, P, &[P]) -> P, +{ match *substructure.fields { EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => { if use_foldl { @@ -1355,12 +1359,14 @@ pub fn cs_fold(use_foldl: bool, /// self_2.method(__arg_1_2, __arg_2_2)]) /// ``` #[inline] -pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec>| -> P, - enum_nonmatch_f: EnumNonMatchCollapsedFunc, - cx: &mut ExtCtxt, - trait_span: Span, - substructure: &Substructure) - -> P { +pub fn cs_same_method(f: F, + enum_nonmatch_f: EnumNonMatchCollapsedFunc, + cx: &mut ExtCtxt, + trait_span: Span, + substructure: &Substructure) + -> P where + F: FnOnce(&mut ExtCtxt, Span, Vec>) -> P, +{ match *substructure.fields { EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => { // call self_n.method(other_1_n, other_2_n, ...) @@ -1388,14 +1394,16 @@ pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec>| -> P, /// fields. `use_foldl` controls whether this is done left-to-right /// (`true`) or right-to-left (`false`). #[inline] -pub fn cs_same_method_fold(use_foldl: bool, - f: |&mut ExtCtxt, Span, P, P| -> P, - base: P, - enum_nonmatch_f: EnumNonMatchCollapsedFunc, - cx: &mut ExtCtxt, - trait_span: Span, - substructure: &Substructure) - -> P { +pub fn cs_same_method_fold(use_foldl: bool, + mut f: F, + base: P, + enum_nonmatch_f: EnumNonMatchCollapsedFunc, + cx: &mut ExtCtxt, + trait_span: Span, + substructure: &Substructure) + -> P where + F: FnMut(&mut ExtCtxt, Span, P, P) -> P, +{ cs_same_method( |cx, span, vals| { if use_foldl { diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index b7f11c25825..4e59124a129 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_hash(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_hash(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let (path, generics, args) = if cx.ecfg.deriving_hash_type_parameter { (Path::new_(vec!("std", "hash", "Hash"), None, diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index cd2d98b70f1..8abd846373a 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -18,11 +18,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index c4e64d58c29..4f6e4d1fb3c 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_rand(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_rand(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let trait_def = TraitDef { span: span, attributes: Vec::new(), @@ -64,7 +66,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) cx.ident_of("Rand"), cx.ident_of("rand") ); - let rand_call = |cx: &mut ExtCtxt, span| { + let mut rand_call = |&mut: cx: &mut ExtCtxt, span| { cx.expr_call_global(span, rand_ident.clone(), vec!(rng.clone())) @@ -133,12 +135,14 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) _ => cx.bug("Non-static method in `deriving(Rand)`") }; - fn rand_thing(cx: &mut ExtCtxt, - trait_span: Span, - ctor_path: ast::Path, - summary: &StaticFields, - rand_call: |&mut ExtCtxt, Span| -> P) - -> P { + fn rand_thing(cx: &mut ExtCtxt, + trait_span: Span, + ctor_path: ast::Path, + summary: &StaticFields, + mut rand_call: F) + -> P where + F: FnMut(&mut ExtCtxt, Span) -> P, + { let path = cx.expr_path(ctor_path.clone()); match *summary { Unnamed(ref fields) => { diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 322a84eaa2b..a68b521bbc9 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -21,11 +21,13 @@ use ptr::P; use std::collections::HashMap; -pub fn expand_deriving_show(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_show(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ // &mut ::std::fmt::Formatter let fmtr = Ptr(box Literal(Path::new(vec!("std", "fmt", "Formatter"))), Borrowed(None, ast::MutMutable)); diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index 7f265b529ff..ea32549cad2 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_zero(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P|) { +pub fn expand_deriving_zero(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index a697d332d16..9c4e85f16ff 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -238,11 +238,13 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { /// of expansion and the mark which must be applied to the result. /// Our current interface doesn't allow us to apply the mark to the /// result until after calling make_expr, make_items, etc. -fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, - parse_thunk: |Box|->Option, - mark_thunk: |T,Mrk|->T, - fld: &mut MacroExpander) - -> Option +fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, + parse_thunk: F, + mark_thunk: G, + fld: &mut MacroExpander) + -> Option where + F: FnOnce(Box) -> Option, + G: FnOnce(T, Mrk) -> T, { match mac.node { // it would almost certainly be cleaner to pass the whole diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index 48120b575ac..a4e06aeaf63 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -105,9 +105,11 @@ pub fn apply_renames(renames: &RenameList, ctxt: SyntaxContext) -> SyntaxContext } /// Fetch the SCTable from TLS, create one if it doesn't yet exist. -pub fn with_sctable(op: |&SCTable| -> T) -> T { +pub fn with_sctable(op: F) -> T where + F: FnOnce(&SCTable) -> T, +{ thread_local!(static SCTABLE_KEY: SCTable = new_sctable_internal()) - SCTABLE_KEY.with(|slot| op(slot)) + SCTABLE_KEY.with(move |slot| op(slot)) } // Make a fresh syntax context table with EmptyCtxt in slot zero @@ -167,12 +169,14 @@ type ResolveTable = HashMap<(Name,SyntaxContext),Name>; // okay, I admit, putting this in TLS is not so nice: // fetch the SCTable from TLS, create one if it doesn't yet exist. -fn with_resolve_table_mut(op: |&mut ResolveTable| -> T) -> T { +fn with_resolve_table_mut(op: F) -> T where + F: FnOnce(&mut ResolveTable) -> T, +{ thread_local!(static RESOLVE_TABLE_KEY: RefCell = { RefCell::new(HashMap::new()) }) - RESOLVE_TABLE_KEY.with(|slot| op(&mut *slot.borrow_mut())) + RESOLVE_TABLE_KEY.with(move |slot| op(&mut *slot.borrow_mut())) } /// Resolve a syntax object to a name, per MTWT. diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 69e311c57f5..0318dd5b0cd 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -32,11 +32,11 @@ use std::rc::Rc; // This could have a better place to live. pub trait MoveMap { - fn move_map(self, f: |T| -> T) -> Self; + fn move_map(self, f: F) -> Self where F: FnMut(T) -> T; } impl MoveMap for Vec { - fn move_map(mut self, f: |T| -> T) -> Vec { + fn move_map(mut self, mut f: F) -> Vec where F: FnMut(T) -> T { for p in self.iter_mut() { unsafe { // FIXME(#5016) this shouldn't need to zero to be safe. @@ -48,7 +48,7 @@ impl MoveMap for Vec { } impl MoveMap for OwnedSlice { - fn move_map(self, f: |T| -> T) -> OwnedSlice { + fn move_map(self, f: F) -> OwnedSlice where F: FnMut(T) -> T { OwnedSlice::from_vec(self.into_vec().move_map(f)) } } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 4c15fae9feb..50c7258fe1c 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -244,7 +244,9 @@ impl<'a> StringReader<'a> { /// Calls `f` with a string slice of the source text spanning from `start` /// up to but excluding `self.last_pos`, meaning the slice does not include /// the character `self.curr`. - pub fn with_str_from(&self, start: BytePos, f: |s: &str| -> T) -> T { + pub fn with_str_from(&self, start: BytePos, f: F) -> T where + F: FnOnce(&str) -> T, + { self.with_str_from_to(start, self.last_pos, f) } @@ -264,7 +266,9 @@ impl<'a> StringReader<'a> { /// Calls `f` with a string slice of the source text spanning from `start` /// up to but excluding `end`. - fn with_str_from_to(&self, start: BytePos, end: BytePos, f: |s: &str| -> T) -> T { + fn with_str_from_to(&self, start: BytePos, end: BytePos, f: F) -> T where + F: FnOnce(&str) -> T, + { f(self.filemap.src.slice( self.byte_offset(start).to_uint(), self.byte_offset(end).to_uint())) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 92c7380a61d..8c44f9fdf26 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -718,11 +718,12 @@ impl<'a> Parser<'a> { } /// Parse a sequence bracketed by `|` and `|`, stopping before the `|`. - fn parse_seq_to_before_or( - &mut self, - sep: &token::Token, - f: |&mut Parser| -> T) - -> Vec { + fn parse_seq_to_before_or(&mut self, + sep: &token::Token, + mut f: F) + -> Vec where + F: FnMut(&mut Parser) -> T, + { let mut first = true; let mut vector = Vec::new(); while self.token != token::BinOp(token::Or) && @@ -769,10 +770,12 @@ impl<'a> Parser<'a> { } } - pub fn parse_seq_to_before_gt_or_return(&mut self, - sep: Option, - f: |&mut Parser| -> Option) - -> (OwnedSlice, bool) { + pub fn parse_seq_to_before_gt_or_return(&mut self, + sep: Option, + mut f: F) + -> (OwnedSlice, bool) where + F: FnMut(&mut Parser) -> Option, + { let mut v = Vec::new(); // This loop works by alternating back and forth between parsing types // and commas. For example, given a string `A, B,>`, the parser would @@ -802,28 +805,34 @@ impl<'a> Parser<'a> { /// Parse a sequence bracketed by '<' and '>', stopping /// before the '>'. - pub fn parse_seq_to_before_gt(&mut self, - sep: Option, - f: |&mut Parser| -> T) - -> OwnedSlice { + pub fn parse_seq_to_before_gt(&mut self, + sep: Option, + mut f: F) + -> OwnedSlice where + F: FnMut(&mut Parser) -> T, + { let (result, returned) = self.parse_seq_to_before_gt_or_return(sep, |p| Some(f(p))); assert!(!returned); return result; } - pub fn parse_seq_to_gt(&mut self, - sep: Option, - f: |&mut Parser| -> T) - -> OwnedSlice { + pub fn parse_seq_to_gt(&mut self, + sep: Option, + f: F) + -> OwnedSlice where + F: FnMut(&mut Parser) -> T, + { let v = self.parse_seq_to_before_gt(sep, f); self.expect_gt(); return v; } - pub fn parse_seq_to_gt_or_return(&mut self, - sep: Option, - f: |&mut Parser| -> Option) - -> (OwnedSlice, bool) { + pub fn parse_seq_to_gt_or_return(&mut self, + sep: Option, + f: F) + -> (OwnedSlice, bool) where + F: FnMut(&mut Parser) -> Option, + { let (v, returned) = self.parse_seq_to_before_gt_or_return(sep, f); if !returned { self.expect_gt(); @@ -834,12 +843,13 @@ impl<'a> Parser<'a> { /// Parse a sequence, including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_seq_to_end( - &mut self, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Vec { + pub fn parse_seq_to_end(&mut self, + ket: &token::Token, + sep: SeqSep, + f: F) + -> Vec where + F: FnMut(&mut Parser) -> T, + { let val = self.parse_seq_to_before_end(ket, sep, f); self.bump(); val @@ -848,12 +858,13 @@ impl<'a> Parser<'a> { /// Parse a sequence, not including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_seq_to_before_end( - &mut self, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Vec { + pub fn parse_seq_to_before_end(&mut self, + ket: &token::Token, + sep: SeqSep, + mut f: F) + -> Vec where + F: FnMut(&mut Parser) -> T, + { let mut first: bool = true; let mut v = vec!(); while self.token != *ket { @@ -873,13 +884,14 @@ impl<'a> Parser<'a> { /// Parse a sequence, including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_unspanned_seq( - &mut self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Vec { + pub fn parse_unspanned_seq(&mut self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: F) + -> Vec where + F: FnMut(&mut Parser) -> T, + { self.expect(bra); let result = self.parse_seq_to_before_end(ket, sep, f); self.bump(); @@ -888,13 +900,14 @@ impl<'a> Parser<'a> { /// Parse a sequence parameter of enum variant. For consistency purposes, /// these should not be empty. - pub fn parse_enum_variant_seq( - &mut self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Vec { + pub fn parse_enum_variant_seq(&mut self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: F) + -> Vec where + F: FnMut(&mut Parser) -> T, + { let result = self.parse_unspanned_seq(bra, ket, sep, f); if result.is_empty() { let last_span = self.last_span; @@ -906,13 +919,14 @@ impl<'a> Parser<'a> { // NB: Do not use this function unless you actually plan to place the // spanned list in the AST. - pub fn parse_seq( - &mut self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Spanned > { + pub fn parse_seq(&mut self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: F) + -> Spanned> where + F: FnMut(&mut Parser) -> T, + { let lo = self.span.lo; self.expect(bra); let result = self.parse_seq_to_before_end(ket, sep, f); @@ -972,8 +986,9 @@ impl<'a> Parser<'a> { } return (4 - self.buffer_start) + self.buffer_end; } - pub fn look_ahead(&mut self, distance: uint, f: |&token::Token| -> R) - -> R { + pub fn look_ahead(&mut self, distance: uint, f: F) -> R where + F: FnOnce(&token::Token) -> R, + { let dist = distance as int; while self.buffer_length() < dist { self.buffer[self.buffer_end as uint] = self.reader.real_token(); @@ -4285,8 +4300,9 @@ impl<'a> Parser<'a> { /// Parse the argument list and result type of a function /// that may have a self type. - fn parse_fn_decl_with_self(&mut self, parse_arg_fn: |&mut Parser| -> Arg) - -> (ExplicitSelf, P) { + fn parse_fn_decl_with_self(&mut self, parse_arg_fn: F) -> (ExplicitSelf, P) where + F: FnMut(&mut Parser) -> Arg, + { fn maybe_parse_borrowed_explicit_self(this: &mut Parser) -> ast::ExplicitSelf_ { // The following things are possible to see here: diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 26373d00aaf..6d8b8dcb8ba 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -165,7 +165,9 @@ impl<'a> State<'a> { } } -pub fn to_string(f: |&mut State| -> IoResult<()>) -> String { +pub fn to_string(f: F) -> String where + F: FnOnce(&mut State) -> IoResult<()>, +{ use std::raw::TraitObject; let mut s = rust_printer(box Vec::new()); f(&mut s).unwrap(); @@ -426,8 +428,10 @@ pub mod with_hygiene { // This function is the trick that all the rest of the routines // hang on. - pub fn to_string_hyg(f: |&mut super::State| -> IoResult<()>) -> String { - super::to_string(|s| { + pub fn to_string_hyg(f: F) -> String where + F: FnOnce(&mut super::State) -> IoResult<()>, + { + super::to_string(move |s| { s.encode_idents_with_hygiene = true; f(s) }) @@ -580,9 +584,9 @@ impl<'a> State<'a> { word(&mut self.s, "*/") } - pub fn commasep(&mut self, b: Breaks, elts: &[T], - op: |&mut State, &T| -> IoResult<()>) - -> IoResult<()> { + pub fn commasep(&mut self, b: Breaks, elts: &[T], mut op: F) -> IoResult<()> where + F: FnMut(&mut State, &T) -> IoResult<()>, + { try!(self.rbox(0u, b)); let mut first = true; for elt in elts.iter() { @@ -593,12 +597,14 @@ impl<'a> State<'a> { } - pub fn commasep_cmnt( - &mut self, - b: Breaks, - elts: &[T], - op: |&mut State, &T| -> IoResult<()>, - get_span: |&T| -> codemap::Span) -> IoResult<()> { + pub fn commasep_cmnt(&mut self, + b: Breaks, + elts: &[T], + mut op: F, + mut get_span: G) -> IoResult<()> where + F: FnMut(&mut State, &T) -> IoResult<()>, + G: FnMut(&T) -> codemap::Span, + { try!(self.rbox(0u, b)); let len = elts.len(); let mut i = 0u; diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 1b231ed861b..1b3ebde2461 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -56,12 +56,16 @@ pub fn P(value: T) -> P { impl P { /// Move out of the pointer. /// Intended for chaining transformations not covered by `map`. - pub fn and_then(self, f: |T| -> U) -> U { + pub fn and_then(self, f: F) -> U where + F: FnOnce(T) -> U, + { f(*self.ptr) } /// Transform the inner value, consuming `self` and producing a new `P`. - pub fn map(mut self, f: |T| -> T) -> P { + pub fn map(mut self, f: F) -> P where + F: FnOnce(T) -> T, + { unsafe { let p = &mut *self.ptr; // FIXME(#5016) this shouldn't need to zero to be safe. diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index c1ea8f60b82..83bbff8473d 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -31,7 +31,9 @@ pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> source_str) } -fn with_error_checking_parse(s: String, f: |&mut Parser| -> T) -> T { +fn with_error_checking_parse(s: String, f: F) -> T where + F: FnOnce(&mut Parser) -> T, +{ let ps = new_parse_sess(); let mut p = string_to_parser(&ps, s); let x = f(&mut p); diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index d56e4f70449..8d050e34abf 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -171,7 +171,7 @@ impl Iterator for MoveItems { } impl MoveMap for SmallVector { - fn move_map(self, f: |T| -> T) -> SmallVector { + fn move_map(self, mut f: F) -> SmallVector where F: FnMut(T) -> T { let repr = match self.repr { Zero => Zero, One(v) => One(f(v)), -- cgit 1.4.1-3-g733a5 From c434954b272318d8fdceca01de7d005c8cce2118 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 9 Dec 2014 12:17:24 -0500 Subject: libsyntax: use tuple indexing --- src/libsyntax/parse/mod.rs | 16 ++++++++-------- src/libsyntax/parse/parser.rs | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 951fe11a470..310d5662afa 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -431,7 +431,7 @@ pub fn str_lit(lit: &str) -> String { /// Eat everything up to a non-whitespace fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharOffsets<'a>>) { loop { - match it.peek().map(|x| x.val1()) { + match it.peek().map(|x| x.1) { Some(' ') | Some('\n') | Some('\r') | Some('\t') => { it.next(); }, @@ -448,7 +448,7 @@ pub fn str_lit(lit: &str) -> String { '\\' => { let ch = chars.peek().unwrap_or_else(|| { panic!("{}", error(i).as_slice()) - }).val1(); + }).1; if ch == '\n' { eat(&mut chars); @@ -456,7 +456,7 @@ pub fn str_lit(lit: &str) -> String { chars.next(); let ch = chars.peek().unwrap_or_else(|| { panic!("{}", error(i).as_slice()) - }).val1(); + }).1; if ch != '\n' { panic!("lexer accepted bare CR"); @@ -474,7 +474,7 @@ pub fn str_lit(lit: &str) -> String { '\r' => { let ch = chars.peek().unwrap_or_else(|| { panic!("{}", error(i).as_slice()) - }).val1(); + }).1; if ch != '\n' { panic!("lexer accepted bare CR"); @@ -600,7 +600,7 @@ pub fn binary_lit(lit: &str) -> Rc> { /// Eat everything up to a non-whitespace fn eat<'a, I: Iterator<(uint, u8)>>(it: &mut iter::Peekable<(uint, u8), I>) { loop { - match it.peek().map(|x| x.val1()) { + match it.peek().map(|x| x.1) { Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => { it.next(); }, @@ -615,11 +615,11 @@ pub fn binary_lit(lit: &str) -> Rc> { match chars.next() { Some((i, b'\\')) => { let em = error(i); - match chars.peek().expect(em.as_slice()).val1() { + match chars.peek().expect(em.as_slice()).1 { b'\n' => eat(&mut chars), b'\r' => { chars.next(); - if chars.peek().expect(em.as_slice()).val1() != b'\n' { + if chars.peek().expect(em.as_slice()).1 != b'\n' { panic!("lexer accepted bare CR"); } eat(&mut chars); @@ -637,7 +637,7 @@ pub fn binary_lit(lit: &str) -> Rc> { }, Some((i, b'\r')) => { let em = error(i); - if chars.peek().expect(em.as_slice()).val1() != b'\n' { + if chars.peek().expect(em.as_slice()).1 != b'\n' { panic!("lexer accepted bare CR"); } chars.next(); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8c44f9fdf26..e9cc91d9415 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1740,8 +1740,8 @@ impl<'a> Parser<'a> { } token::Literal(lit, suf) => { let (suffix_illegal, out) = match lit { - token::Byte(i) => (true, LitByte(parse::byte_lit(i.as_str()).val0())), - token::Char(i) => (true, LitChar(parse::char_lit(i.as_str()).val0())), + token::Byte(i) => (true, LitByte(parse::byte_lit(i.as_str()).0)), + token::Char(i) => (true, LitChar(parse::char_lit(i.as_str()).0)), // there are some valid suffixes for integer and // float literals, so all the handling is done -- cgit 1.4.1-3-g733a5 From d258d68db6ae5ad81e4b8b4f5fcc1e4d89624f97 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 26 Nov 2014 10:07:22 -0500 Subject: Remove `proc` types/expressions from the parser, compiler, and language. Recommend `move||` instead. --- src/libcore/raw.rs | 9 ----- src/librustc/middle/cfg/construct.rs | 1 - src/librustc/middle/check_loop.rs | 3 +- src/librustc/middle/expr_use_visitor.rs | 3 +- src/librustc/middle/infer/error_reporting.rs | 53 ---------------------------- src/librustc/middle/infer/mod.rs | 18 ---------- src/librustc/middle/liveness.rs | 10 +++--- src/librustc/middle/mem_categorization.rs | 4 +-- src/librustc/middle/resolve.rs | 13 ++----- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/middle/traits/select.rs | 25 ++++++++++--- src/librustc/middle/ty.rs | 1 - src/librustc/util/ppaux.rs | 9 ++++- src/librustc_back/svh.rs | 2 -- src/librustc_borrowck/borrowck/mod.rs | 1 - src/librustc_trans/trans/base.rs | 3 +- src/librustc_trans/trans/debuginfo.rs | 2 -- src/librustc_trans/trans/expr.rs | 3 +- src/librustc_typeck/astconv.rs | 22 +----------- src/librustc_typeck/check/closure.rs | 28 ++++++--------- src/librustc_typeck/check/mod.rs | 18 +--------- src/librustc_typeck/check/regionck.rs | 4 +-- src/librustc_typeck/check/writeback.rs | 3 +- src/libsyntax/ast.rs | 3 -- src/libsyntax/ast_map/blocks.rs | 6 ++-- src/libsyntax/ast_map/mod.rs | 2 +- src/libsyntax/ext/expand.rs | 18 ---------- src/libsyntax/feature_gate.rs | 6 ---- src/libsyntax/fold.rs | 15 -------- src/libsyntax/parse/obsolete.rs | 10 ++++++ src/libsyntax/parse/parser.rs | 51 ++++++++++---------------- src/libsyntax/print/pprust.rs | 49 ++----------------------- src/libsyntax/visit.rs | 15 -------- 33 files changed, 91 insertions(+), 321 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index db1be94b2b8..be2f4e590a3 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -40,15 +40,6 @@ pub struct Closure { impl Copy for Closure {} -/// The representation of a Rust procedure (`proc()`) -#[repr(C)] -pub struct Procedure { - pub code: *mut (), - pub env: *mut (), -} - -impl Copy for Procedure {} - /// The representation of a Rust trait object. /// /// This struct does not have a `Repr` implementation diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 0dcb78f6bb0..b6347278bff 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -498,7 +498,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { ast::ExprMac(..) | ast::ExprClosure(..) | - ast::ExprProc(..) | ast::ExprLit(..) | ast::ExprPath(..) => { self.straightline(expr, pred, None::.iter()) diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index fee2d810fcb..c4ad089d76e 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -52,8 +52,7 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> { self.visit_expr(&**e); self.with_context(Loop, |v| v.visit_block(&**b)); } - ast::ExprClosure(_, _, _, ref b) | - ast::ExprProc(_, ref b) => { + ast::ExprClosure(_, _, _, ref b) => { self.with_context(Closure, |v| v.visit_block(&**b)); } ast::ExprBreak(_) => self.require_loop("break", e.span), diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 8e00c96535b..6501d8d6eb4 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -613,8 +613,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { self.consume_expr(&**count); } - ast::ExprClosure(..) | - ast::ExprProc(..) => { + ast::ExprClosure(..) => { self.walk_captures(expr) } diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index e2a57629d7e..0c346519672 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -587,19 +587,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { sub, ""); } - infer::ProcCapture(span, id) => { - self.tcx.sess.span_err( - span, - format!("captured variable `{}` must be 'static \ - to be captured in a proc", - ty::local_var_name_str(self.tcx, id).get()) - .as_slice()); - note_and_explain_region( - self.tcx, - "captured variable is only valid for ", - sup, - ""); - } infer::IndexSlice(span) => { self.tcx.sess.span_err(span, "index of slice outside its lifetime"); @@ -625,28 +612,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { sup, ""); } - infer::RelateProcBound(span, var_node_id, ty) => { - self.tcx.sess.span_err( - span, - format!( - "the type `{}` of captured variable `{}` \ - outlives the `proc()` it \ - is captured in", - self.ty_to_string(ty), - ty::local_var_name_str(self.tcx, - var_node_id)).as_slice()); - note_and_explain_region( - self.tcx, - "`proc()` is valid for ", - sub, - ""); - note_and_explain_region( - self.tcx, - format!("the type `{}` is only valid for ", - self.ty_to_string(ty)).as_slice(), - sup, - ""); - } infer::RelateParamBound(span, ty) => { self.tcx.sess.span_err( span, @@ -1587,15 +1552,6 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { self.tcx, id).get().to_string()).as_slice()); } - infer::ProcCapture(span, id) => { - self.tcx.sess.span_note( - span, - format!("...so that captured variable `{}` \ - is 'static", - ty::local_var_name_str( - self.tcx, - id).get()).as_slice()); - } infer::IndexSlice(span) => { self.tcx.sess.span_note( span, @@ -1606,15 +1562,6 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { span, "...so that it can be closed over into an object"); } - infer::RelateProcBound(span, var_node_id, _ty) => { - self.tcx.sess.span_note( - span, - format!( - "...so that the variable `{}` can be captured \ - into a proc", - ty::local_var_name_str(self.tcx, - var_node_id)).as_slice()); - } infer::CallRcvr(span) => { self.tcx.sess.span_note( span, diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 4c3b7589d76..2b1d8776365 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -175,9 +175,6 @@ pub enum SubregionOrigin<'tcx> { // Closure bound must not outlive captured free variables FreeVariable(Span, ast::NodeId), - // Proc upvars must be 'static - ProcCapture(Span, ast::NodeId), - // Index into slice must be within its lifetime IndexSlice(Span), @@ -185,10 +182,6 @@ pub enum SubregionOrigin<'tcx> { // relating `'a` to `'b` RelateObjectBound(Span), - // When closing over a variable in a closure/proc, ensure that the - // type of the variable outlives the lifetime bound. - RelateProcBound(Span, ast::NodeId, Ty<'tcx>), - // Some type parameter was instantiated with the given type, // and that type must outlive some region. RelateParamBound(Span, Ty<'tcx>), @@ -1089,10 +1082,8 @@ impl<'tcx> SubregionOrigin<'tcx> { InvokeClosure(a) => a, DerefPointer(a) => a, FreeVariable(a, _) => a, - ProcCapture(a, _) => a, IndexSlice(a) => a, RelateObjectBound(a) => a, - RelateProcBound(a, _, _) => a, RelateParamBound(a, _) => a, RelateRegionParamBound(a) => a, RelateDefaultParamBound(a, _) => a, @@ -1128,21 +1119,12 @@ impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> { FreeVariable(a, b) => { format!("FreeVariable({}, {})", a.repr(tcx), b) } - ProcCapture(a, b) => { - format!("ProcCapture({}, {})", a.repr(tcx), b) - } IndexSlice(a) => { format!("IndexSlice({})", a.repr(tcx)) } RelateObjectBound(a) => { format!("RelateObjectBound({})", a.repr(tcx)) } - RelateProcBound(a, b, c) => { - format!("RelateProcBound({},{},{})", - a.repr(tcx), - b, - c.repr(tcx)) - } RelateParamBound(a, b) => { format!("RelateParamBound({},{})", a.repr(tcx), diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 271e903bbdf..31bcdff9cd5 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -461,7 +461,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { } visit::walk_expr(ir, expr); } - ast::ExprClosure(..) | ast::ExprProc(..) => { + ast::ExprClosure(..) => { // Interesting control flow (for loops can contain labeled // breaks or continues) ir.add_live_node_for_node(expr.id, ExprNode(expr.span)); @@ -981,9 +981,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_expr(&**e, succ) } - ast::ExprClosure(_, _, _, ref blk) | - ast::ExprProc(_, ref blk) => { - debug!("{} is an ExprClosure or ExprProc", + ast::ExprClosure(_, _, _, ref blk) => { + debug!("{} is an ExprClosure", expr_to_string(expr)); /* @@ -1502,8 +1501,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { ast::ExprBreak(..) | ast::ExprAgain(..) | ast::ExprLit(_) | ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) | - ast::ExprClosure(..) | ast::ExprProc(..) | - ast::ExprPath(..) | ast::ExprBox(..) | ast::ExprSlice(..) => { + ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) | ast::ExprSlice(..) => { visit::walk_expr(this, expr); } ast::ExprIfLet(..) => { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index d96cf4495bd..652847a6343 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -555,8 +555,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ast::ExprAddrOf(..) | ast::ExprCall(..) | ast::ExprAssign(..) | ast::ExprAssignOp(..) | - ast::ExprClosure(..) | ast::ExprProc(..) | - ast::ExprRet(..) | + ast::ExprClosure(..) | ast::ExprRet(..) | ast::ExprUnary(..) | ast::ExprSlice(..) | ast::ExprMethodCall(..) | ast::ExprCast(..) | ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) | @@ -728,7 +727,6 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { }; match fn_expr.node { - ast::ExprProc(_, ref body) | ast::ExprClosure(_, _, _, ref body) => body.id, _ => unreachable!() } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 85e0c9294a6..9912db69a05 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -51,7 +51,7 @@ use util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap}; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField}; use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall}; -use syntax::ast::{ExprPath, ExprProc, ExprStruct, FnDecl}; +use syntax::ast::{ExprPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemEnum, ItemFn, ItemForeignMod}; use syntax::ast::{ItemImpl, ItemMac, ItemMod, ItemStatic, ItemStruct}; @@ -64,7 +64,7 @@ use syntax::ast::{RegionTyParamBound, StmtDecl, StructField}; use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound}; use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32}; use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum}; -use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyProc, TyQPath}; +use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath}; use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint}; use syntax::ast::{TypeImplItem, UnnamedField}; use syntax::ast::{Variant, ViewItem, ViewItemExternCrate}; @@ -5027,7 +5027,7 @@ impl<'a> Resolver<'a> { self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath); } - TyClosure(ref c) | TyProc(ref c) => { + TyClosure(ref c) => { self.resolve_type_parameter_bounds( ty.id, &c.bounds, @@ -5902,13 +5902,6 @@ impl<'a> Resolver<'a> { &**block); } - ExprProc(ref fn_decl, ref block) => { - self.capture_mode_map.insert(expr.id, ast::CaptureByValue); - self.resolve_function(ClosureRibKind(expr.id, block.id), - Some(&**fn_decl), NoTypeParameters, - &**block); - } - ExprStruct(ref path, _, _) => { // Resolve the path to the structure it goes to. We don't // check to ensure that the path is actually a structure; that diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 83332d275ce..ee0fc327020 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -141,7 +141,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { fn visit_ty(&mut self, ty: &ast::Ty) { match ty.node { - ast::TyClosure(ref c) | ast::TyProc(ref c) => { + ast::TyClosure(ref c) => { // Careful, the bounds on a closure/proc are *not* within its binder. visit::walk_ty_param_bounds_helper(self, &c.bounds); visit::walk_lifetime_decls_helper(self, &c.lifetimes); diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 88c70f5557c..c3c4acd8191 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -746,8 +746,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => { return Ok(()); } }; - debug!("assemble_unboxed_candidates: self_ty={} obligation={}", + debug!("assemble_unboxed_candidates: self_ty={} kind={} obligation={}", self_ty.repr(self.tcx()), + kind, obligation.repr(self.tcx())); let closure_kind = match self.typer.unboxed_closures().borrow().get(&closure_def_id) { @@ -760,6 +761,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }; + debug!("closure_kind = {}", closure_kind); + if closure_kind == kind { candidates.vec.push(UnboxedClosureCandidate(closure_def_id, substs.clone())); } @@ -842,14 +845,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: &Candidate<'tcx>) -> EvaluationResult<'tcx> { - debug!("winnow_candidate: candidate={}", candidate.repr(self.tcx())); - self.infcx.probe(|| { + /*! + * Further evaluate `candidate` to decide whether all type parameters match + * and whether nested obligations are met. Returns true if `candidate` remains + * viable after this further scrutiny. + */ + + debug!("winnow_candidate: depth={} candidate={}", + stack.obligation.recursion_depth, candidate.repr(self.tcx())); + let result = self.infcx.probe(|| { let candidate = (*candidate).clone(); match self.confirm_candidate(stack.obligation, candidate) { Ok(selection) => self.winnow_selection(Some(stack), selection), Err(error) => EvaluatedToErr(error), } - }) + }); + debug!("winnow_candidate depth={} result={}", + stack.obligation.recursion_depth, result); + result } fn winnow_selection<'o>(&mut self, @@ -1562,6 +1575,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { substs: substs, }); + debug!("confirm_unboxed_closure_candidate(closure_def_id={}, trait_ref={})", + closure_def_id.repr(self.tcx()), + trait_ref.repr(self.tcx())); + self.confirm(obligation.cause, obligation.trait_ref.clone(), trait_ref) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8e99045cffb..98d4761508a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4236,7 +4236,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { ast::ExprIf(..) | ast::ExprMatch(..) | ast::ExprClosure(..) | - ast::ExprProc(..) | ast::ExprBlock(..) | ast::ExprRepeat(..) | ast::ExprVec(..) => { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 5dbf3208595..f8276fa8f84 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -449,7 +449,14 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { let unboxed_closures = cx.unboxed_closures.borrow(); unboxed_closures.get(did).map(|cl| { closure_to_string(cx, &cl.closure_type.subst(cx, substs)) - }).unwrap_or_else(|| "closure".to_string()) + }).unwrap_or_else(|| { + if did.krate == ast::LOCAL_CRATE { + let span = cx.map.span(did.node); + format!("closure[{}]", span.repr(cx)) + } else { + format!("closure") + } + }) } ty_vec(t, sz) => { let inner_str = ty_to_string(cx, t); diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 549d636e8cb..116cff49153 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -242,7 +242,6 @@ mod svh_visitor { SawExprWhile, SawExprMatch, SawExprClosure, - SawExprProc, SawExprBlock, SawExprAssign, SawExprAssignOp(ast::BinOp), @@ -274,7 +273,6 @@ mod svh_visitor { ExprLoop(_, id) => SawExprLoop(id.map(content)), ExprMatch(..) => SawExprMatch, ExprClosure(..) => SawExprClosure, - ExprProc(..) => SawExprProc, ExprBlock(..) => SawExprBlock, ExprAssign(..) => SawExprAssign, ExprAssignOp(op, _, _) => SawExprAssignOp(op), diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 1722f9a1f75..a3fb91aced0 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -337,7 +337,6 @@ pub fn closure_to_block(closure_id: ast::NodeId, tcx: &ty::ctxt) -> ast::NodeId { match tcx.map.get(closure_id) { ast_map::NodeExpr(expr) => match expr.node { - ast::ExprProc(_, ref block) | ast::ExprClosure(_, _, _, ref block) => { block.id } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 5170746404e..b2578fdbc05 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -1396,8 +1396,7 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool { } Some(ast_map::NodeExpr(e)) => { match e.node { - ast::ExprClosure(_, _, _, ref blk) | - ast::ExprProc(_, ref blk) => { + ast::ExprClosure(_, _, _, ref blk) => { let mut explicit = CheckForNestedReturnsVisitor::explicit(); let mut implicit = CheckForNestedReturnsVisitor::implicit(); visit::walk_expr(&mut explicit, e); diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index de169fc9d62..66258f228cd 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -1239,7 +1239,6 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } ast_map::NodeExpr(ref expr) => { match expr.node { - ast::ExprProc(ref fn_decl, ref top_level_block) | ast::ExprClosure(_, _, ref fn_decl, ref top_level_block) => { let name = format!("fn{}", token::gensym("fn")); let name = token::str_to_ident(name.as_slice()); @@ -3588,7 +3587,6 @@ fn populate_scope_map(cx: &CrateContext, }) } - ast::ExprProc(ref decl, ref block) | ast::ExprClosure(_, _, ref decl, ref block) => { with_new_scope(cx, block.span, diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index e1769001942..5b9a1d49991 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -1052,8 +1052,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprVec(..) | ast::ExprRepeat(..) => { tvec::trans_fixed_vstore(bcx, expr, dest) } - ast::ExprClosure(_, _, ref decl, ref body) | - ast::ExprProc(ref decl, ref body) => { + ast::ExprClosure(_, _, ref decl, ref body) => { // Check the side-table to see whether this is an unboxed // closure or an older, legacy style closure. Store this // into a variable to ensure the the RefCell-lock is diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 7ee627dbe14..4ea2a228701 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -945,26 +945,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( None); ty::mk_closure(tcx, fn_decl) } - ast::TyProc(ref f) => { - // Use corresponding trait store to figure out default bounds - // if none were specified. - let bounds = conv_existential_bounds(this, - rscope, - ast_ty.span, - None, - f.bounds.as_slice()); - - let fn_decl = ty_of_closure(this, - f.fn_style, - f.onceness, - bounds, - ty::UniqTraitStore, - &*f.decl, - abi::Rust, - None); - - ty::mk_closure(tcx, fn_decl) - } ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice()) } @@ -1071,7 +1051,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } ast::TyInfer => { // TyInfer also appears as the type of arguments or return - // values in a ExprClosure or ExprProc, or as + // values in a ExprClosure, or as // the type of local variables. Both of these cases are // handled specially and will not descend into this routine. this.ty_infer(ast_ty.span) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 4e027005931..692bd31638e 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -250,12 +250,12 @@ fn deduce_unboxed_closure_expectations_from_obligations<'a,'tcx>( } -pub fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, - expr: &ast::Expr, - store: ty::TraitStore, - decl: &ast::FnDecl, - body: &ast::Block, - expected: Expectation<'tcx>) { +fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + expr: &ast::Expr, + store: ty::TraitStore, + decl: &ast::FnDecl, + body: &ast::Block, + expected: Expectation<'tcx>) { let tcx = fcx.ccx.tcx; // Find the expected input/output types (if any). Substitute @@ -293,18 +293,10 @@ pub fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, } _ => { // Not an error! Means we're inferring the closure type - let (bounds, onceness) = match expr.node { - ast::ExprProc(..) => { - let mut bounds = ty::region_existential_bound(ty::ReStatic); - bounds.builtin_bounds.insert(ty::BoundSend); // FIXME - (bounds, ast::Once) - } - _ => { - let region = fcx.infcx().next_region_var( - infer::AddrOfRegion(expr.span)); - (ty::region_existential_bound(region), ast::Many) - } - }; + let region = fcx.infcx().next_region_var( + infer::AddrOfRegion(expr.span)); + let bounds = ty::region_existential_bound(region); + let onceness = ast::Many; (None, onceness, bounds) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 77460bb6b26..fccd6605df7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2122,14 +2122,6 @@ fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fcx.inh.method_map.borrow_mut().insert(method_call, method_callee); write_call(fcx, call_expression, output_type); - if !fcx.tcx().sess.features.borrow().unboxed_closures { - span_err!(fcx.tcx().sess, call_expression.span, E0056, - "overloaded calls are experimental"); - span_help!(fcx.tcx().sess, call_expression.span, - "add `#![feature(unboxed_closures)]` to \ - the crate attributes to enable"); - } - return true } @@ -2666,7 +2658,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }; for (i, arg) in args.iter().take(t).enumerate() { let is_block = match arg.node { - ast::ExprClosure(..) | ast::ExprProc(..) => true, + ast::ExprClosure(..) => true, _ => false }; @@ -3997,14 +3989,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ast::ExprClosure(_, opt_kind, ref decl, ref body) => { closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected); } - ast::ExprProc(ref decl, ref body) => { - closure::check_boxed_closure(fcx, - expr, - ty::UniqTraitStore, - &**decl, - &**body, - expected); - } ast::ExprBlock(ref b) => { check_block_with_expected(fcx, &**b, expected); fcx.write_ty(id, fcx.node_ty(b.id)); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index cadcee43b44..9f75b9764eb 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -714,7 +714,6 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { visit::walk_expr(rcx, expr); } - ast::ExprProc(_, ref body) | ast::ExprClosure(_, _, _, ref body) => { check_expr_fn_block(rcx, expr, &**body); } @@ -936,8 +935,9 @@ fn check_expr_fn_block(rcx: &mut Rcx, let cause = traits::ObligationCause::new(freevar.span, rcx.fcx.body_id, code); rcx.fcx.register_builtin_bound(var_ty, builtin_bound, cause); } + type_must_outlive( - rcx, infer::RelateProcBound(expr.span, var_node_id, var_ty), + rcx, infer::FreeVariable(expr.span, var_node_id), var_ty, bounds.region_bound); } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 48f1ef8da1d..8d94cf5dd5e 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -121,8 +121,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> { MethodCall::expr(e.id)); match e.node { - ast::ExprClosure(_, _, ref decl, _) | - ast::ExprProc(ref decl, _) => { + ast::ExprClosure(_, _, ref decl, _) => { for input in decl.inputs.iter() { let _ = self.visit_node_id(ResolvingExpr(e.span), input.id); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ea8de458ce2..ae7a2127e9f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -719,7 +719,6 @@ pub enum Expr_ { ExprLoop(P, Option), ExprMatch(P, Vec, MatchSource), ExprClosure(CaptureClause, Option, P, P), - ExprProc(P, P), ExprBlock(P), ExprAssign(P, P), @@ -1225,8 +1224,6 @@ pub enum Ty_ { TyRptr(Option, MutTy), /// A closure (e.g. `|uint| -> bool`) TyClosure(P), - /// A procedure (e.g `proc(uint) -> bool`) - TyProc(P), /// A bare function (e.g. `fn(uint) -> bool`) TyBareFn(P), /// A tuple (`(A, B, C, D,...)`) diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 75f69f2f6d0..5462918b662 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -37,7 +37,7 @@ use visit; /// /// More specifically, it is one of either: /// - A function item, -/// - A closure expr (i.e. an ExprClosure or ExprProc), or +/// - A closure expr (i.e. an ExprClosure), or /// - The default implementation for a trait method. /// /// To construct one, use the `Code::from_node` function. @@ -73,7 +73,7 @@ impl MaybeFnLike for ast::TraitItem { impl MaybeFnLike for ast::Expr { fn is_fn_like(&self) -> bool { match self.node { - ast::ExprClosure(..) | ast::ExprProc(..) => true, + ast::ExprClosure(..) => true, _ => false, } } @@ -222,8 +222,6 @@ impl<'a> FnLikeNode<'a> { ast_map::NodeExpr(e) => match e.node { ast::ExprClosure(_, _, ref decl, ref block) => closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), - ast::ExprProc(ref decl, ref block) => - closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), _ => panic!("expr FnLikeNode that is not fn-like"), }, _ => panic!("other FnLikeNode that is not fn-like"), diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 907ac6b19fc..6f1d2d39b30 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -859,7 +859,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { fn visit_ty(&mut self, ty: &'ast Ty) { match ty.node { - TyClosure(ref fd) | TyProc(ref fd) => { + TyClosure(ref fd) => { self.visit_fn_decl(&*fd.decl); } TyBareFn(ref fd) => { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9c4e85f16ff..1a004ca7c44 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -217,13 +217,6 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)}) } - ast::ExprProc(fn_decl, block) => { - let (rewritten_fn_decl, rewritten_block) - = expand_and_rename_fn_decl_and_block(fn_decl, block, fld); - let new_node = ast::ExprProc(rewritten_fn_decl, rewritten_block); - P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)}) - } - _ => { P(noop_fold_expr(ast::Expr { id: id, @@ -1576,17 +1569,6 @@ mod test { 0) } - // closure arg hygiene (ExprProc) - // expands to fn f(){(proc(x_1 : int) {(x_2 + x_1)})(3);} - #[test] fn closure_arg_hygiene_2(){ - run_renaming_test( - &("macro_rules! inject_x (()=>(x)) - fn f(){ (proc(x : int){(inject_x!() + x)})(3); }", - vec!(vec!(1)), - true), - 0) - } - // macro_rules in method position. Sadly, unimplemented. #[test] fn macro_in_method_posn(){ expand_crate_str( diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2ee4957ec0f..66fe672c3e5 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -306,12 +306,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { fn visit_expr(&mut self, e: &ast::Expr) { match e.node { - ast::ExprClosure(_, Some(_), _, _) => { - self.gate_feature("unboxed_closures", - e.span, - "unboxed closures are a work-in-progress \ - feature with known bugs"); - } ast::ExprSlice(..) => { self.gate_feature("slicing_syntax", e.span, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0318dd5b0cd..611faa2c2c9 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -425,17 +425,6 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { } })) } - TyProc(f) => { - TyProc(f.map(|ClosureTy {fn_style, onceness, bounds, decl, lifetimes}| { - ClosureTy { - fn_style: fn_style, - onceness: onceness, - bounds: fld.fold_bounds(bounds), - decl: fld.fold_fn_decl(decl), - lifetimes: fld.fold_lifetime_defs(lifetimes) - } - })) - } TyBareFn(f) => { TyBareFn(f.map(|BareFnTy {lifetimes, fn_style, abi, decl}| BareFnTy { lifetimes: fld.fold_lifetime_defs(lifetimes), @@ -1360,10 +1349,6 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> arms.move_map(|x| folder.fold_arm(x)), source) } - ExprProc(decl, body) => { - ExprProc(folder.fold_fn_decl(decl), - folder.fold_block(body)) - } ExprClosure(capture_clause, opt_kind, decl, body) => { ExprClosure(capture_clause, opt_kind, diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 2a2bb42cef0..3a7cc77515d 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -32,6 +32,8 @@ pub enum ObsoleteSyntax { ObsoleteImportRenaming, ObsoleteSubsliceMatch, ObsoleteExternCrateRenaming, + ObsoleteProcType, + ObsoleteProcExpr, } impl Copy for ObsoleteSyntax {} @@ -55,6 +57,14 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { /// Reports an obsolete syntax non-fatal error. fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { + ObsoleteProcType => ( + "the `proc` type", + "use unboxed closures instead", + ), + ObsoleteProcExpr => ( + "`proc` expression", + "use a `move ||` expression instead", + ), ObsoleteOwnedType => ( "`~` notation for owned pointers", "use `Box` in `std::owned` instead" diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e9cc91d9415..381942a3e62 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -27,10 +27,10 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex, ExprSlice}; use ast::{ExprLit, ExprLoop, ExprMac}; -use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc}; +use ast::{ExprMethodCall, ExprParen, ExprPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; -use ast::{Once, Many}; +use ast::{Many}; use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind}; use ast::{FnOnceUnboxedClosureKind}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; @@ -54,7 +54,7 @@ use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; use ast::{TtDelimited, TtSequence, TtToken}; use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; -use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn}; +use ast::{TypeField, TyFixedLengthVec, TyClosure, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; @@ -1064,7 +1064,6 @@ impl<'a> Parser<'a> { Deprecated: - for <'lt> |S| -> T - - for <'lt> proc(S) -> T Eventually: @@ -1158,26 +1157,21 @@ impl<'a> Parser<'a> { | | | Bounds | | Argument types | Legacy lifetimes - the `proc` keyword + the `proc` keyword (already consumed) */ - let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs); - let (inputs, variadic) = self.parse_fn_args(false, false); - let bounds = self.parse_colon_then_ty_param_bounds(); - let ret_ty = self.parse_ret_ty(); - let decl = P(FnDecl { - inputs: inputs, - output: ret_ty, - variadic: variadic - }); - TyProc(P(ClosureTy { - fn_style: NormalFn, - onceness: Once, - bounds: bounds, - decl: decl, - lifetimes: lifetime_defs, - })) + let proc_span = self.last_span; + + // To be helpful, parse the proc as ever + let _ = self.parse_legacy_lifetime_defs(lifetime_defs); + let _ = self.parse_fn_args(false, false); + let _ = self.parse_colon_then_ty_param_bounds(); + let _ = self.parse_ret_ty(); + + self.obsolete(proc_span, ObsoleteProcType); + + TyInfer } /// Parses an optional unboxed closure kind (`&:`, `&mut:`, or `:`). @@ -2294,17 +2288,10 @@ impl<'a> Parser<'a> { return self.parse_lambda_expr(CaptureByValue); } if self.eat_keyword(keywords::Proc) { - let decl = self.parse_proc_decl(); - let body = self.parse_expr(); - let fakeblock = P(ast::Block { - id: ast::DUMMY_NODE_ID, - view_items: Vec::new(), - stmts: Vec::new(), - rules: DefaultBlock, - span: body.span, - expr: Some(body), - }); - return self.mk_expr(lo, fakeblock.span.hi, ExprProc(decl, fakeblock)); + let span = self.last_span; + let _ = self.parse_proc_decl(); + let _ = self.parse_expr(); + return self.obsolete_expr(span, ObsoleteProcExpr); } if self.eat_keyword(keywords::If) { return self.parse_if_expr(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6d8b8dcb8ba..87905db22f3 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -450,7 +450,7 @@ pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String { fn needs_parentheses(expr: &ast::Expr) -> bool { match expr.node { ast::ExprAssign(..) | ast::ExprBinary(..) | - ast::ExprClosure(..) | ast::ExprProc(..) | + ast::ExprClosure(..) | ast::ExprAssignOp(..) | ast::ExprCast(..) => true, _ => false, } @@ -734,25 +734,6 @@ impl<'a> State<'a> { Some(&generics), None)); } - ast::TyProc(ref f) => { - let generics = ast::Generics { - lifetimes: f.lifetimes.clone(), - ty_params: OwnedSlice::empty(), - where_clause: ast::WhereClause { - id: ast::DUMMY_NODE_ID, - predicates: Vec::new(), - }, - }; - try!(self.print_ty_fn(None, - Some('~'), - f.fn_style, - f.onceness, - &*f.decl, - None, - &f.bounds, - Some(&generics), - None)); - } ast::TyPath(ref path, _) => { try!(self.print_path(path, false)); } @@ -1696,33 +1677,6 @@ impl<'a> State<'a> { // empty box to satisfy the close. try!(self.ibox(0)); } - ast::ExprProc(ref decl, ref body) => { - // in do/for blocks we don't want to show an empty - // argument list, but at this point we don't know which - // we are inside. - // - // if !decl.inputs.is_empty() { - try!(self.print_proc_args(&**decl)); - try!(space(&mut self.s)); - // } - assert!(body.stmts.is_empty()); - assert!(body.expr.is_some()); - // we extract the block, so as not to create another set of boxes - match body.expr.as_ref().unwrap().node { - ast::ExprBlock(ref blk) => { - try!(self.print_block_unclosed(&**blk)); - } - _ => { - // this is a bare expression - try!(self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())); - try!(self.end()); // need to close a box - } - } - // a box will be closed by print_expr, but we didn't want an overall - // wrapper so we closed the corresponding opening. so create an - // empty box to satisfy the close. - try!(self.ibox(0)); - } ast::ExprBlock(ref blk) => { // containing cbox, will be closed by print-block at } try!(self.cbox(indent_unit)); @@ -2010,6 +1964,7 @@ impl<'a> State<'a> { match data.output { None => { } Some(ref ty) => { + try!(self.space_if_not_bol()); try!(self.word_space("->")); try!(self.print_type(&**ty)); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a36f8b23ca3..eca99df8e55 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -389,14 +389,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_ty_param_bounds_helper(visitor, &function_declaration.bounds); walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } - TyProc(ref function_declaration) => { - for argument in function_declaration.decl.inputs.iter() { - visitor.visit_ty(&*argument.ty) - } - walk_fn_ret_ty(visitor, &function_declaration.decl.output); - walk_ty_param_bounds_helper(visitor, &function_declaration.bounds); - walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); - } TyBareFn(ref function_declaration) => { for argument in function_declaration.decl.inputs.iter() { visitor.visit_ty(&*argument.ty) @@ -831,13 +823,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { expression.span, expression.id) } - ExprProc(ref function_declaration, ref body) => { - visitor.visit_fn(FkFnBlock, - &**function_declaration, - &**body, - expression.span, - expression.id) - } ExprBlock(ref block) => visitor.visit_block(&**block), ExprAssign(ref left_hand_expression, ref right_hand_expression) => { visitor.visit_expr(&**right_hand_expression); -- cgit 1.4.1-3-g733a5 From 092d04a40a3db44af2dd50e43a77449a7e56dd13 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 9 Dec 2014 10:36:46 -0500 Subject: Rename FnStyle trait to Unsafety. --- src/librustc/metadata/tydecode.rs | 16 ++++----- src/librustc/metadata/tyencode.rs | 10 +++--- src/librustc/middle/effect.rs | 8 ++--- src/librustc/middle/infer/coercion.rs | 2 +- src/librustc/middle/infer/combine.rs | 16 ++++----- src/librustc/middle/infer/equate.rs | 6 ++-- src/librustc/middle/infer/error_reporting.rs | 14 ++++---- src/librustc/middle/infer/glb.rs | 9 +++-- src/librustc/middle/infer/lub.rs | 9 +++-- src/librustc/middle/infer/sub.rs | 8 ++--- src/librustc/middle/traits/select.rs | 4 +-- src/librustc/middle/ty.rs | 18 +++++----- src/librustc/middle/ty_fold.rs | 4 +-- src/librustc/util/ppaux.rs | 24 ++++++------- src/librustc_driver/test.rs | 2 +- src/librustc_trans/trans/callee.rs | 4 +-- src/librustc_trans/trans/debuginfo.rs | 16 ++++----- src/librustc_typeck/astconv.rs | 20 +++++------ src/librustc_typeck/check/closure.rs | 10 +++--- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 50 +++++++++++++--------------- src/librustc_typeck/collect.rs | 18 +++++----- src/librustc_typeck/lib.rs | 4 +-- src/librustdoc/clean/inline.rs | 8 ++--- src/librustdoc/clean/mod.rs | 28 ++++++++-------- src/librustdoc/doctree.rs | 2 +- src/librustdoc/html/format.rs | 22 ++++++------ src/librustdoc/html/render.rs | 16 ++++----- src/librustdoc/visit_ast.rs | 4 +-- src/libsyntax/ast.rs | 29 +++++++--------- src/libsyntax/ast_map/blocks.rs | 8 ++--- src/libsyntax/ast_util.rs | 8 ++--- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/ext/deriving/generic/mod.rs | 2 +- src/libsyntax/fold.rs | 20 +++++------ src/libsyntax/parse/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 48 +++++++++++--------------- src/libsyntax/print/pprust.rs | 48 +++++++++++++------------- src/libsyntax/test.rs | 2 +- src/libsyntax/visit.rs | 2 +- 41 files changed, 254 insertions(+), 273 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 7358b3bc9c9..d649c649131 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -549,11 +549,11 @@ fn parse_hex(st: &mut PState) -> uint { }; } -fn parse_fn_style(c: char) -> ast::FnStyle { +fn parse_unsafety(c: char) -> ast::Unsafety { match c { - 'u' => ast::UnsafeFn, - 'n' => ast::NormalFn, - _ => panic!("parse_fn_style: bad fn_style {}", c) + 'u' => ast::Unsafety::Unsafe, + 'n' => ast::Unsafety::Normal, + _ => panic!("parse_unsafety: bad unsafety {}", c) } } @@ -575,14 +575,14 @@ fn parse_onceness(c: char) -> ast::Onceness { fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::ClosureTy<'tcx> { - let fn_style = parse_fn_style(next(st)); + let unsafety = parse_unsafety(next(st)); let onceness = parse_onceness(next(st)); let store = parse_trait_store(st, |x,y| conv(x,y)); let bounds = parse_existential_bounds(st, |x,y| conv(x,y)); let sig = parse_sig(st, |x,y| conv(x,y)); let abi = parse_abi_set(st); ty::ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: onceness, store: store, bounds: bounds, @@ -593,11 +593,11 @@ fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::BareFnTy<'tcx> { - let fn_style = parse_fn_style(next(st)); + let unsafety = parse_unsafety(next(st)); let abi = parse_abi_set(st); let sig = parse_sig(st, |x,y| conv(x,y)); ty::BareFnTy { - fn_style: fn_style, + unsafety: unsafety, abi: abi, sig: sig } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 54376cd7b90..9b9d2ab42df 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -313,10 +313,10 @@ fn enc_sty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, } } -fn enc_fn_style(w: &mut SeekableMemWriter, p: ast::FnStyle) { +fn enc_unsafety(w: &mut SeekableMemWriter, p: ast::Unsafety) { match p { - ast::NormalFn => mywrite!(w, "n"), - ast::UnsafeFn => mywrite!(w, "u"), + ast::Unsafety::Normal => mywrite!(w, "n"), + ast::Unsafety::Unsafe => mywrite!(w, "u"), } } @@ -335,14 +335,14 @@ fn enc_onceness(w: &mut SeekableMemWriter, o: ast::Onceness) { pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, ft: &ty::BareFnTy<'tcx>) { - enc_fn_style(w, ft.fn_style); + enc_unsafety(w, ft.unsafety); enc_abi(w, ft.abi); enc_fn_sig(w, cx, &ft.sig); } pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, ft: &ty::ClosureTy<'tcx>) { - enc_fn_style(w, ft.fn_style); + enc_unsafety(w, ft.unsafety); enc_onceness(w, ft.onceness); enc_trait_store(w, cx, ft.store); enc_existential_bounds(w, cx, &ft.bounds); diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 8bf43c70c26..d16ce3ad678 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -34,8 +34,8 @@ impl Copy for UnsafeContext {} fn type_is_unsafe_function(ty: Ty) -> bool { match ty.sty { - ty::ty_bare_fn(ref f) => f.fn_style == ast::UnsafeFn, - ty::ty_closure(ref f) => f.fn_style == ast::UnsafeFn, + ty::ty_bare_fn(ref f) => f.unsafety == ast::Unsafety::Unsafe, + ty::ty_closure(ref f) => f.unsafety == ast::Unsafety::Unsafe, _ => false, } } @@ -92,9 +92,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { let (is_item_fn, is_unsafe_fn) = match fn_kind { visit::FkItemFn(_, _, fn_style, _) => - (true, fn_style == ast::UnsafeFn), + (true, fn_style == ast::Unsafety::Unsafe), visit::FkMethod(_, _, method) => - (true, method.pe_fn_style() == ast::UnsafeFn), + (true, method.pe_unsafety() == ast::Unsafety::Unsafe), _ => (false, false), }; diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs index c6422b36e38..1d1ee39d684 100644 --- a/src/librustc/middle/infer/coercion.rs +++ b/src/librustc/middle/infer/coercion.rs @@ -521,7 +521,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { debug!("coerce_from_bare_fn(a={}, b={})", a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx)); - if fn_ty_a.abi != abi::Rust || fn_ty_a.fn_style != ast::NormalFn { + if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal { return self.subtype(a, b); } diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index ab9c5b86aeb..26bba55594b 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -51,7 +51,7 @@ use middle::ty_fold; use middle::ty_fold::{TypeFoldable}; use util::ppaux::Repr; -use syntax::ast::{Onceness, FnStyle}; +use syntax::ast::{Onceness, Unsafety}; use syntax::ast; use syntax::abi; use syntax::codemap::Span; @@ -193,12 +193,12 @@ pub trait Combine<'tcx> { fn bare_fn_tys(&self, a: &ty::BareFnTy<'tcx>, b: &ty::BareFnTy<'tcx>) -> cres<'tcx, ty::BareFnTy<'tcx>> { - let fn_style = try!(self.fn_styles(a.fn_style, b.fn_style)); + let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety)); let abi = try!(self.abi(a.abi, b.abi)); let sig = try!(self.fn_sigs(&a.sig, &b.sig)); - Ok(ty::BareFnTy {fn_style: fn_style, - abi: abi, - sig: sig}) + Ok(ty::BareFnTy {unsafety: unsafety, + abi: abi, + sig: sig}) } fn closure_tys(&self, a: &ty::ClosureTy<'tcx>, @@ -219,13 +219,13 @@ pub trait Combine<'tcx> { return Err(ty::terr_sigil_mismatch(expected_found(self, a.store, b.store))) } }; - let fn_style = try!(self.fn_styles(a.fn_style, b.fn_style)); + let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety)); let onceness = try!(self.oncenesses(a.onceness, b.onceness)); let bounds = try!(self.existential_bounds(a.bounds, b.bounds)); let sig = try!(self.fn_sigs(&a.sig, &b.sig)); let abi = try!(self.abi(a.abi, b.abi)); Ok(ty::ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: onceness, store: store, bounds: bounds, @@ -240,7 +240,7 @@ pub trait Combine<'tcx> { self.contratys(a, b).and_then(|t| Ok(t)) } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle>; + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety>; fn abi(&self, a: abi::Abi, b: abi::Abi) -> cres<'tcx, abi::Abi> { if a == b { diff --git a/src/librustc/middle/infer/equate.rs b/src/librustc/middle/infer/equate.rs index a79a50b1781..1738b8db99b 100644 --- a/src/librustc/middle/infer/equate.rs +++ b/src/librustc/middle/infer/equate.rs @@ -21,7 +21,7 @@ use middle::infer::{TypeTrace, Subtype}; use middle::infer::type_variable::{EqTo}; use util::ppaux::{Repr}; -use syntax::ast::{Onceness, FnStyle}; +use syntax::ast::{Onceness, Unsafety}; pub struct Equate<'f, 'tcx: 'f> { fields: CombineFields<'f, 'tcx> @@ -70,9 +70,9 @@ impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> { Ok(ty::mt { mutbl: a.mutbl, ty: t }) } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> { + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { if a != b { - Err(ty::terr_fn_style_mismatch(expected_found(self, a, b))) + Err(ty::terr_unsafety_mismatch(expected_found(self, a, b))) } else { Ok(a) } diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 0c346519672..c638182d7f3 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -157,7 +157,7 @@ trait ErrorReportingHelpers<'tcx> { fn give_expl_lifetime_param(&self, decl: &ast::FnDecl, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, ident: ast::Ident, opt_explicit_self: Option<&ast::ExplicitSelf_>, generics: &ast::Generics, @@ -828,7 +828,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ast::MethodImplItem(ref m) => { Some((m.pe_fn_decl(), m.pe_generics(), - m.pe_fn_style(), + m.pe_unsafety(), m.pe_ident(), Some(&m.pe_explicit_self().node), m.span)) @@ -841,7 +841,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ast::ProvidedMethod(ref m) => { Some((m.pe_fn_decl(), m.pe_generics(), - m.pe_fn_style(), + m.pe_unsafety(), m.pe_ident(), Some(&m.pe_explicit_self().node), m.span)) @@ -853,14 +853,14 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { }, None => None }; - let (fn_decl, generics, fn_style, ident, expl_self, span) + let (fn_decl, generics, unsafety, ident, expl_self, span) = node_inner.expect("expect item fn"); let taken = lifetimes_in_scope(self.tcx, scope_id); let life_giver = LifeGiver::with_taken(taken.as_slice()); let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self, generics, same_regions, &life_giver); let (fn_decl, expl_self, generics) = rebuilder.rebuild(); - self.give_expl_lifetime_param(&fn_decl, fn_style, ident, + self.give_expl_lifetime_param(&fn_decl, unsafety, ident, expl_self.as_ref(), &generics, span); } } @@ -1407,12 +1407,12 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { fn give_expl_lifetime_param(&self, decl: &ast::FnDecl, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, ident: ast::Ident, opt_explicit_self: Option<&ast::ExplicitSelf_>, generics: &ast::Generics, span: codemap::Span) { - let suggested_fn = pprust::fun_to_string(decl, fn_style, ident, + let suggested_fn = pprust::fun_to_string(decl, unsafety, ident, opt_explicit_self, generics); let msg = format!("consider using an explicit lifetime \ parameter as shown: {}", suggested_fn); diff --git a/src/librustc/middle/infer/glb.rs b/src/librustc/middle/infer/glb.rs index 4237a7af32f..9fc4e095c43 100644 --- a/src/librustc/middle/infer/glb.rs +++ b/src/librustc/middle/infer/glb.rs @@ -20,8 +20,7 @@ use super::{TypeTrace, Subtype}; use middle::ty::{BuiltinBounds}; use middle::ty::{mod, Ty}; use syntax::ast::{Many, Once, MutImmutable, MutMutable}; -use syntax::ast::{NormalFn, UnsafeFn}; -use syntax::ast::{Onceness, FnStyle}; +use syntax::ast::{Onceness, Unsafety}; use util::ppaux::mt_to_string; use util::ppaux::Repr; @@ -81,10 +80,10 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> { self.lub().tys(a, b) } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> { + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { match (a, b) { - (NormalFn, _) | (_, NormalFn) => Ok(NormalFn), - (UnsafeFn, UnsafeFn) => Ok(UnsafeFn) + (Unsafety::Normal, _) | (_, Unsafety::Normal) => Ok(Unsafety::Normal), + (Unsafety::Unsafe, Unsafety::Unsafe) => Ok(Unsafety::Unsafe) } } diff --git a/src/librustc/middle/infer/lub.rs b/src/librustc/middle/infer/lub.rs index f53ba571062..f27b07c9c9d 100644 --- a/src/librustc/middle/infer/lub.rs +++ b/src/librustc/middle/infer/lub.rs @@ -20,8 +20,7 @@ use super::{TypeTrace, Subtype}; use middle::ty::{BuiltinBounds}; use middle::ty::{mod, Ty}; use syntax::ast::{Many, Once}; -use syntax::ast::{NormalFn, UnsafeFn}; -use syntax::ast::{Onceness, FnStyle}; +use syntax::ast::{Onceness, Unsafety}; use syntax::ast::{MutMutable, MutImmutable}; use util::ppaux::mt_to_string; use util::ppaux::Repr; @@ -77,10 +76,10 @@ impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> { self.glb().tys(a, b) } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> { + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { match (a, b) { - (UnsafeFn, _) | (_, UnsafeFn) => Ok(UnsafeFn), - (NormalFn, NormalFn) => Ok(NormalFn), + (Unsafety::Unsafe, _) | (_, Unsafety::Unsafe) => Ok(Unsafety::Unsafe), + (Unsafety::Normal, Unsafety::Normal) => Ok(Unsafety::Normal), } } diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs index c470b248827..00c79bc726c 100644 --- a/src/librustc/middle/infer/sub.rs +++ b/src/librustc/middle/infer/sub.rs @@ -23,7 +23,7 @@ use middle::ty::{mod, Ty}; use middle::ty::TyVar; use util::ppaux::{Repr}; -use syntax::ast::{Onceness, FnStyle, MutImmutable, MutMutable}; +use syntax::ast::{Onceness, MutImmutable, MutMutable, Unsafety}; /// "Greatest lower bound" (common subtype) @@ -93,9 +93,9 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> { Ok(*a) // return is meaningless in sub, just return *a } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> { - self.lub().fn_styles(a, b).compare(b, || { - ty::terr_fn_style_mismatch(expected_found(self, a, b)) + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { + self.lub().unsafeties(a, b).compare(b, || { + ty::terr_unsafety_mismatch(expected_found(self, a, b)) }) } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index c3c4acd8191..8b31132f736 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -791,7 +791,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // provide an impl, but only for suitable `fn` pointers ty::ty_bare_fn(ty::BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::FnSig { inputs: _, @@ -1505,7 +1505,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); let sig = match self_ty.sty { ty::ty_bare_fn(ty::BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, ref sig }) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 98d4761508a..9673b9ab586 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -80,7 +80,7 @@ use std::rc::Rc; use std::collections::enum_set::{EnumSet, CLike}; use std::collections::hash_map::{HashMap, Occupied, Vacant}; use syntax::abi; -use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, FnStyle, Ident, ItemTrait, LOCAL_CRATE}; +use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, Ident, ItemTrait, LOCAL_CRATE}; use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField}; use syntax::ast::{Visibility}; @@ -908,14 +908,14 @@ pub fn type_escapes_depth(ty: Ty, depth: uint) -> bool { #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct BareFnTy<'tcx> { - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub abi: abi::Abi, pub sig: FnSig<'tcx>, } #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct ClosureTy<'tcx> { - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub onceness: ast::Onceness, pub store: TraitStore, pub bounds: ExistentialBounds, @@ -1380,7 +1380,7 @@ impl Copy for expected_found {} #[deriving(Clone, Show)] pub enum type_err<'tcx> { terr_mismatch, - terr_fn_style_mismatch(expected_found), + terr_unsafety_mismatch(expected_found), terr_onceness_mismatch(expected_found), terr_abi_mismatch(expected_found), terr_mutability, @@ -2354,7 +2354,7 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>, let input_args = input_tys.iter().map(|ty| *ty).collect(); mk_bare_fn(cx, BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: FnSig { inputs: input_args, @@ -3994,7 +3994,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, ty::mk_closure( cx, - ty::ClosureTy {fn_style: b.fn_style, + ty::ClosureTy {unsafety: b.unsafety, onceness: ast::Many, store: store, bounds: bounds, @@ -4404,7 +4404,7 @@ pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String { match *err { terr_cyclic_ty => "cyclic type of infinite size".to_string(), terr_mismatch => "types differ".to_string(), - terr_fn_style_mismatch(values) => { + terr_unsafety_mismatch(values) => { format!("expected {} fn, found {} fn", values.expected.to_string(), values.found.to_string()) @@ -5871,12 +5871,12 @@ pub fn hash_crate_independent(tcx: &ctxt, ty: Ty, svh: &Svh) -> u64 { } ty_bare_fn(ref b) => { byte!(14); - hash!(b.fn_style); + hash!(b.unsafety); hash!(b.abi); } ty_closure(ref c) => { byte!(15); - hash!(c.fn_style); + hash!(c.unsafety); hash!(c.onceness); hash!(c.bounds); match c.store { diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 63ee71dc6a5..5d0c584864d 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -563,7 +563,7 @@ pub fn super_fold_bare_fn_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, { ty::BareFnTy { sig: fty.sig.fold_with(this), abi: fty.abi, - fn_style: fty.fn_style } + unsafety: fty.unsafety } } pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, @@ -573,7 +573,7 @@ pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, ty::ClosureTy { store: fty.store.fold_with(this), sig: fty.sig.fold_with(this), - fn_style: fty.fn_style, + unsafety: fty.unsafety, onceness: fty.onceness, bounds: fty.bounds.fold_with(this), abi: fty.abi, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index f8276fa8f84..74e312803f3 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -259,16 +259,16 @@ pub fn trait_ref_to_string<'tcx>(cx: &ctxt<'tcx>, pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, abi: abi::Abi, ident: Option, sig: &ty::FnSig<'tcx>) -> String { let mut s = String::new(); - match fn_style { - ast::NormalFn => {} - _ => { - s.push_str(fn_style.to_string().as_slice()); + match unsafety { + ast::Unsafety::Normal => {} + ast::Unsafety::Unsafe => { + s.push_str(unsafety.to_string().as_slice()); s.push(' '); } }; @@ -302,10 +302,10 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { } } - match cty.fn_style { - ast::NormalFn => {} - _ => { - s.push_str(cty.fn_style.to_string().as_slice()); + match cty.unsafety { + ast::Unsafety::Normal => {} + ast::Unsafety::Unsafe => { + s.push_str(cty.unsafety.to_string().as_slice()); s.push(' '); } }; @@ -414,7 +414,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { closure_to_string(cx, &**f) } ty_bare_fn(ref f) => { - bare_fn_to_string(cx, f.fn_style, f.abi, None, &f.sig) + bare_fn_to_string(cx, f.unsafety, f.abi, None, &f.sig) } ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty), ty_err => "[type error]".to_string(), @@ -1001,8 +1001,8 @@ impl<'tcx> Repr<'tcx> for ast::Visibility { impl<'tcx> Repr<'tcx> for ty::BareFnTy<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("BareFnTy {{fn_style: {}, abi: {}, sig: {}}}", - self.fn_style, + format!("BareFnTy {{unsafety: {}, abi: {}, sig: {}}}", + self.unsafety, self.abi.to_string(), self.sig.repr(tcx)) } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index dda3754cf73..6a50af3bc79 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -270,7 +270,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { -> Ty<'tcx> { ty::mk_closure(self.infcx.tcx, ty::ClosureTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, onceness: ast::Many, store: ty::RegionTraitStore(region_bound, ast::MutMutable), bounds: ty::region_existential_bound(region_bound), diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 67e1735d9a3..81d44d84414 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -278,7 +278,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( // which is the fn pointer, and `args`, which is the arguments tuple. let (input_tys, output_ty) = match bare_fn_ty.sty { - ty::ty_bare_fn(ty::BareFnTy { fn_style: ast::NormalFn, + ty::ty_bare_fn(ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: synabi::Rust, sig: ty::FnSig { inputs: ref input_tys, output: output_ty, @@ -294,7 +294,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( }; let tuple_input_ty = ty::mk_tup(tcx, input_tys.to_vec()); let tuple_fn_ty = ty::mk_bare_fn(tcx, - ty::BareFnTy { fn_style: ast::NormalFn, + ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: synabi::RustCall, sig: ty::FnSig { inputs: vec![bare_fn_ty_ref, diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 66258f228cd..3f8c951786d 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -433,8 +433,8 @@ impl<'tcx> TypeMap<'tcx> { &trait_data.principal.substs, &mut unique_type_id); }, - ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => { - if fn_style == ast::UnsafeFn { + ty::ty_bare_fn(ty::BareFnTy{ unsafety, abi, ref sig } ) => { + if unsafety == ast::Unsafety::Unsafe { unique_type_id.push_str("unsafe "); } @@ -551,13 +551,13 @@ impl<'tcx> TypeMap<'tcx> { cx: &CrateContext<'a, 'tcx>, closure_ty: ty::ClosureTy<'tcx>, unique_type_id: &mut String) { - let ty::ClosureTy { fn_style, + let ty::ClosureTy { unsafety, onceness, store, ref bounds, ref sig, abi: _ } = closure_ty; - if fn_style == ast::UnsafeFn { + if unsafety == ast::Unsafety::Unsafe { unique_type_id.push_str("unsafe "); } @@ -3767,8 +3767,8 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_item_name(cx, trait_data.principal.def_id, false, output); push_type_params(cx, &trait_data.principal.substs, output); }, - ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => { - if fn_style == ast::UnsafeFn { + ty::ty_bare_fn(ty::BareFnTy{ unsafety, abi, ref sig } ) => { + if unsafety == ast::Unsafety::Unsafe { output.push_str("unsafe "); } @@ -3810,13 +3810,13 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } }, - ty::ty_closure(box ty::ClosureTy { fn_style, + ty::ty_closure(box ty::ClosureTy { unsafety, onceness, store, ref sig, .. // omitting bounds ... }) => { - if fn_style == ast::UnsafeFn { + if unsafety == ast::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 762aed3dfa8..b3272a14753 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -924,7 +924,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( tcx.sess.span_err(ast_ty.span, "variadic function must have C calling convention"); } - ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.fn_style, bf.abi, &*bf.decl)) + ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl)) } ast::TyClosure(ref f) => { // Use corresponding trait store to figure out default bounds @@ -935,7 +935,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( None, f.bounds.as_slice()); let fn_decl = ty_of_closure(this, - f.fn_style, + f.unsafety, f.onceness, bounds, ty::RegionTraitStore( @@ -1082,7 +1082,7 @@ struct SelfInfo<'a, 'tcx> { pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>( this: &AC, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, untransformed_self_ty: Ty<'tcx>, explicit_self: &ast::ExplicitSelf, decl: &ast::FnDecl, @@ -1094,22 +1094,22 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>( }); let (bare_fn_ty, optional_explicit_self_category) = ty_of_method_or_bare_fn(this, - fn_style, + unsafety, abi, self_info, decl); (bare_fn_ty, optional_explicit_self_category.unwrap()) } -pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, fn_style: ast::FnStyle, abi: abi::Abi, +pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, unsafety: ast::Unsafety, abi: abi::Abi, decl: &ast::FnDecl) -> ty::BareFnTy<'tcx> { - let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, fn_style, abi, None, decl); + let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl); bare_fn_ty } fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( this: &AC, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, abi: abi::Abi, opt_self_info: Option>, decl: &ast::FnDecl) @@ -1207,7 +1207,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( }; (ty::BareFnTy { - fn_style: fn_style, + unsafety: unsafety, abi: abi, sig: ty::FnSig { inputs: self_and_input_tys, @@ -1301,7 +1301,7 @@ fn determine_explicit_self_category<'a, 'tcx, AC: AstConv<'tcx>, pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( this: &AC, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, onceness: ast::Onceness, bounds: ty::ExistentialBounds, store: ty::TraitStore, @@ -1346,7 +1346,7 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( debug!("ty_of_closure: output_ty={}", output_ty.repr(this.tcx())); ty::ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: onceness, store: store, bounds: bounds, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 692bd31638e..e3fec2c8b1d 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -89,7 +89,7 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, let mut fn_ty = astconv::ty_of_closure( fcx, - ast::NormalFn, + ast::Unsafety::Normal, ast::Many, // The `RegionTraitStore` and region_existential_bounds @@ -119,7 +119,7 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fcx.write_ty(expr.id, closure_type); check_fn(fcx.ccx, - ast::NormalFn, + ast::Unsafety::Normal, expr.id, &fn_ty.sig, decl, @@ -304,7 +304,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, // construct the function type let fn_ty = astconv::ty_of_closure(fcx, - ast::NormalFn, + ast::Unsafety::Normal, expected_onceness, expected_bounds, store, @@ -321,9 +321,9 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, // style inferred for it, then check it under its parent's style. // Otherwise, use its own let (inherited_style, inherited_style_id) = match store { - ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style, + ty::RegionTraitStore(..) => (fcx.ps.borrow().unsafety, fcx.ps.borrow().def), - ty::UniqTraitStore => (ast::NormalFn, expr.id) + ty::UniqTraitStore => (ast::Unsafety::Normal, expr.id) }; check_fn(fcx.ccx, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 3c7cecc96a3..7463652a931 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -115,7 +115,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Create the final `MethodCallee`. let fty = ty::mk_bare_fn(self.tcx(), ty::BareFnTy { sig: method_sig, - fn_style: pick.method_ty.fty.fn_style, + unsafety: pick.method_ty.fty.unsafety, abi: pick.method_ty.fty.abi.clone(), }); let callee = MethodCallee { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index d081b97b71a..d97a9c9e39b 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -205,7 +205,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, let transformed_self_ty = fn_sig.inputs[0]; let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { sig: fn_sig, - fn_style: bare_fn_ty.fn_style, + unsafety: bare_fn_ty.unsafety, abi: bare_fn_ty.abi.clone(), }); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fdc57579d07..5b1ca8fc1c0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -180,35 +180,33 @@ enum Expectation<'tcx> { impl<'tcx> Copy for Expectation<'tcx> {} -#[deriving(Clone)] -pub struct FnStyleState { +#[deriving(Copy, Clone)] +pub struct UnsafetyState { pub def: ast::NodeId, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, from_fn: bool } -impl Copy for FnStyleState {} - -impl FnStyleState { - pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState { - FnStyleState { def: def, fn_style: fn_style, from_fn: true } +impl UnsafetyState { + pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState { + UnsafetyState { def: def, unsafety: unsafety, from_fn: true } } - pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState { - match self.fn_style { + pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState { + match self.unsafety { // If this unsafe, then if the outer function was already marked as // unsafe we shouldn't attribute the unsafe'ness to the block. This // way the block can be warned about instead of ignoring this // extraneous block (functions are never warned about). - ast::UnsafeFn if self.from_fn => *self, + ast::Unsafety::Unsafe if self.from_fn => *self, - fn_style => { - let (fn_style, def) = match blk.rules { - ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id), - ast::DefaultBlock => (fn_style, self.def), + unsafety => { + let (unsafety, def) = match blk.rules { + ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id), + ast::DefaultBlock => (unsafety, self.def), }; - FnStyleState{ def: def, - fn_style: fn_style, + UnsafetyState{ def: def, + unsafety: unsafety, from_fn: false } } } @@ -240,7 +238,7 @@ pub struct FnCtxt<'a, 'tcx: 'a> { ret_ty: ty::FnOutput<'tcx>, - ps: RefCell, + ps: RefCell, inh: &'a Inherited<'a, 'tcx>, @@ -312,7 +310,7 @@ pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, writeback_errors: Cell::new(false), err_count_on_creation: ccx.tcx.sess.err_count(), ret_ty: rty, - ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)), + ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)), inh: inh, ccx: ccx } @@ -374,7 +372,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, match fty.sty { ty::ty_bare_fn(ref fn_ty) => { let inh = Inherited::new(ccx.tcx, param_env); - let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig, + let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_ty.sig, decl, id, body, &inh); vtable::select_all_fcx_obligations_or_error(&fcx); @@ -476,8 +474,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { /// * ... /// * inherited: other fields inherited from the enclosing fn (if any) fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, - fn_style: ast::FnStyle, - fn_style_id: ast::NodeId, + unsafety: ast::Unsafety, + unsafety_id: ast::NodeId, fn_sig: &ty::FnSig<'tcx>, decl: &ast::FnDecl, fn_id: ast::NodeId, @@ -506,7 +504,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, writeback_errors: Cell::new(false), err_count_on_creation: err_count_on_creation, ret_ty: ret_ty, - ps: RefCell::new(FnStyleState::function(fn_style, fn_style_id)), + ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)), inh: inherited, ccx: ccx }; @@ -4493,8 +4491,8 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expected: Expectation<'tcx>) { let prev = { let mut fcx_ps = fcx.ps.borrow_mut(); - let fn_style_state = fcx_ps.recurse(blk); - replace(&mut *fcx_ps, fn_style_state) + let unsafety_state = fcx_ps.recurse(blk); + replace(&mut *fcx_ps, unsafety_state) }; let mut warned = false; @@ -5696,7 +5694,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { (n_tps, inputs, ty::FnConverging(output)) }; let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { - fn_style: ast::UnsafeFn, + unsafety: ast::Unsafety::Unsafe, abi: abi::RustIntrinsic, sig: FnSig { inputs: inputs, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 09cf7080476..0bb0f95a66b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -277,7 +277,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, &m.explicit_self, m.abi, &m.generics, - &m.fn_style, + &m.unsafety, &*m.decl) } ast::ProvidedMethod(ref m) => { @@ -291,7 +291,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m.pe_explicit_self(), m.pe_abi(), m.pe_generics(), - &m.pe_fn_style(), + &m.pe_unsafety(), &*m.pe_fn_decl()) } ast::TypeTraitItem(ref at) => { @@ -366,7 +366,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m_explicit_self: &ast::ExplicitSelf, m_abi: abi::Abi, m_generics: &ast::Generics, - m_fn_style: &ast::FnStyle, + m_unsafety: &ast::Unsafety, m_decl: &ast::FnDecl) -> ty::Method<'tcx> { let ty_generics = @@ -386,7 +386,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let trait_self_ty = ty::mk_self_type(tmcx.tcx(), local_def(trait_id)); astconv::ty_of_method(&tmcx, - *m_fn_style, + *m_unsafety, trait_self_ty, m_explicit_self, m_decl, @@ -572,7 +572,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, method_generics: &m_ty_generics, }; astconv::ty_of_method(&imcx, - m.pe_fn_style(), + m.pe_unsafety(), untransformed_rcvr_ty, m.pe_explicit_self(), &*m.pe_fn_decl(), @@ -586,7 +586,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, method_generics: &m_ty_generics, }; astconv::ty_of_method(&tmcx, - m.pe_fn_style(), + m.pe_unsafety(), untransformed_rcvr_ty, m.pe_explicit_self(), &*m.pe_fn_decl(), @@ -1446,7 +1446,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone()); return pty; } - ast::ItemFn(ref decl, fn_style, abi, ref generics, _) => { + ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => { let ty_generics = ty_generics_for_fn_or_method( ccx, generics, @@ -1457,7 +1457,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) ccx: ccx, generics: &ty_generics, }; - astconv::ty_of_bare_fn(&fcx, fn_style, abi, &**decl) + astconv::ty_of_bare_fn(&fcx, unsafety, abi, &**decl) }; let pty = Polytype { generics: ty_generics, @@ -2151,7 +2151,7 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ccx.tcx, ty::BareFnTy { abi: abi, - fn_style: ast::UnsafeFn, + unsafety: ast::Unsafety::Unsafe, sig: ty::FnSig {inputs: input_tys, output: output, variadic: decl.variadic} diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 32c732c2467..d55d642f746 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -226,7 +226,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, _ => () } let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::FnSig { inputs: Vec::new(), @@ -274,7 +274,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, } let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::FnSig { inputs: vec!( diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3ee07df6ed4..75cf0c7a26b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -171,13 +171,13 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Function { let t = ty::lookup_item_type(tcx, did); let (decl, style) = match t.ty.sty { - ty::ty_bare_fn(ref f) => ((did, &f.sig).clean(cx), f.fn_style), + ty::ty_bare_fn(ref f) => ((did, &f.sig).clean(cx), f.unsafety), _ => panic!("bad function"), }; clean::Function { decl: decl, generics: (&t.generics, subst::FnSpace).clean(cx), - fn_style: style, + unsafety: style, } } @@ -299,10 +299,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt, let mut item = method.clean(cx); item.inner = match item.inner.clone() { clean::TyMethodItem(clean::TyMethod { - fn_style, decl, self_, generics + unsafety, decl, self_, generics }) => { clean::MethodItem(clean::Method { - fn_style: fn_style, + unsafety: unsafety, decl: decl, self_: self_, generics: generics, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8045dab6c2d..1d0929746c2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -740,7 +740,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, subst::ParamSpace) { pub struct Method { pub generics: Generics, pub self_: SelfTy, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub decl: FnDecl, } @@ -768,7 +768,7 @@ impl Clean for ast::Method { inner: MethodItem(Method { generics: self.pe_generics().clean(cx), self_: self.pe_explicit_self().node.clean(cx), - fn_style: self.pe_fn_style().clone(), + unsafety: self.pe_unsafety().clone(), decl: decl, }), } @@ -777,7 +777,7 @@ impl Clean for ast::Method { #[deriving(Clone, Encodable, Decodable)] pub struct TyMethod { - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub decl: FnDecl, pub generics: Generics, pub self_: SelfTy, @@ -804,7 +804,7 @@ impl Clean for ast::TypeMethod { visibility: None, stability: get_stability(cx, ast_util::local_def(self.id)), inner: TyMethodItem(TyMethod { - fn_style: self.fn_style.clone(), + unsafety: self.unsafety.clone(), decl: decl, self_: self.explicit_self.node.clean(cx), generics: self.generics.clean(cx), @@ -838,7 +838,7 @@ impl Clean for ast::ExplicitSelf_ { pub struct Function { pub decl: FnDecl, pub generics: Generics, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, } impl Clean for doctree::Function { @@ -853,7 +853,7 @@ impl Clean for doctree::Function { inner: FunctionItem(Function { decl: self.decl.clean(cx), generics: self.generics.clean(cx), - fn_style: self.fn_style, + unsafety: self.unsafety, }), } } @@ -864,7 +864,7 @@ pub struct ClosureDecl { pub lifetimes: Vec, pub decl: FnDecl, pub onceness: ast::Onceness, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub bounds: Vec, } @@ -874,7 +874,7 @@ impl Clean for ast::ClosureTy { lifetimes: self.lifetimes.clean(cx), decl: self.decl.clean(cx), onceness: self.onceness, - fn_style: self.fn_style, + unsafety: self.unsafety, bounds: self.bounds.clean(cx) } } @@ -1111,7 +1111,7 @@ impl<'tcx> Clean for ty::Method<'tcx> { attrs: inline::load_attrs(cx, cx.tcx(), self.def_id), source: Span::empty(), inner: TyMethodItem(TyMethod { - fn_style: self.fty.fn_style, + unsafety: self.fty.unsafety, generics: (&self.generics, subst::FnSpace).clean(cx), self_: self_, decl: (self.def_id, &sig).clean(cx), @@ -1364,7 +1364,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { type_: box mt.ty.clean(cx), }, ty::ty_bare_fn(ref fty) => BareFunction(box BareFunctionDecl { - fn_style: fty.fn_style, + unsafety: fty.unsafety, generics: Generics { lifetimes: Vec::new(), type_params: Vec::new(), @@ -1378,7 +1378,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { lifetimes: Vec::new(), // FIXME: this looks wrong... decl: (ast_util::local_def(0), &fty.sig).clean(cx), onceness: fty.onceness, - fn_style: fty.fn_style, + unsafety: fty.unsafety, bounds: fty.bounds.clean(cx), }; match fty.store { @@ -1789,7 +1789,7 @@ impl Clean for doctree::Typedef { #[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct BareFunctionDecl { - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub generics: Generics, pub decl: FnDecl, pub abi: String, @@ -1798,7 +1798,7 @@ pub struct BareFunctionDecl { impl Clean for ast::BareFnTy { fn clean(&self, cx: &DocContext) -> BareFunctionDecl { BareFunctionDecl { - fn_style: self.fn_style, + unsafety: self.unsafety, generics: Generics { lifetimes: self.lifetimes.clean(cx), type_params: Vec::new(), @@ -2071,7 +2071,7 @@ impl Clean for ast::ForeignItem { ForeignFunctionItem(Function { decl: decl.clean(cx), generics: generics.clean(cx), - fn_style: ast::UnsafeFn, + unsafety: ast::Unsafety::Unsafe, }) } ast::ForeignItemStatic(ref ty, mutbl) => { diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 1aac91c4a5c..a25d4352430 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -129,7 +129,7 @@ pub struct Function { pub name: Ident, pub vis: ast::Visibility, pub stab: Option, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub whence: Span, pub generics: ast::Generics, } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index cf92a71369f..6a2929beca2 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -32,7 +32,7 @@ use html::render::{cache, CURRENT_LOCATION_KEY}; pub struct VisSpace(pub Option); /// Similarly to VisSpace, this structure is used to render a function style with a /// space after it. -pub struct FnStyleSpace(pub ast::FnStyle); +pub struct UnsafetySpace(pub ast::Unsafety); /// Wrapper struct for properly emitting a method declaration. pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl); /// Similar to VisSpace, but used for mutability @@ -49,7 +49,7 @@ pub struct WhereClause<'a>(pub &'a clean::Generics); pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]); impl Copy for VisSpace {} -impl Copy for FnStyleSpace {} +impl Copy for UnsafetySpace {} impl Copy for MutableSpace {} impl Copy for RawMutableSpace {} @@ -59,9 +59,9 @@ impl VisSpace { } } -impl FnStyleSpace { - pub fn get(&self) -> ast::FnStyle { - let FnStyleSpace(v) = *self; v +impl UnsafetySpace { + pub fn get(&self) -> ast::Unsafety { + let UnsafetySpace(v) = *self; v } } @@ -404,7 +404,7 @@ impl fmt::Show for clean::Type { clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()), clean::Closure(ref decl) => { write!(f, "{style}{lifetimes}|{args}|{bounds}{arrow}", - style = FnStyleSpace(decl.fn_style), + style = UnsafetySpace(decl.unsafety), lifetimes = if decl.lifetimes.len() == 0 { "".to_string() } else { @@ -433,7 +433,7 @@ impl fmt::Show for clean::Type { } clean::Proc(ref decl) => { write!(f, "{style}{lifetimes}proc({args}){bounds}{arrow}", - style = FnStyleSpace(decl.fn_style), + style = UnsafetySpace(decl.unsafety), lifetimes = if decl.lifetimes.len() == 0 { "".to_string() } else { @@ -454,7 +454,7 @@ impl fmt::Show for clean::Type { } clean::BareFunction(ref decl) => { write!(f, "{}{}fn{}{}", - FnStyleSpace(decl.fn_style), + UnsafetySpace(decl.unsafety), match decl.abi.as_slice() { "" => " extern ".to_string(), "\"Rust\"" => "".to_string(), @@ -584,11 +584,11 @@ impl fmt::Show for VisSpace { } } -impl fmt::Show for FnStyleSpace { +impl fmt::Show for UnsafetySpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.get() { - ast::UnsafeFn => write!(f, "unsafe "), - ast::NormalFn => Ok(()) + ast::Unsafety::Unsafe => write!(f, "unsafe "), + ast::Unsafety::Normal => Ok(()) } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 542169620e6..54b7ead5469 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -58,7 +58,7 @@ use rustc::util::nodemap::NodeSet; use clean; use doctree; use fold::DocFolder; -use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability}; +use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace, Stability}; use html::format::{ConciseStability, TyParamBounds, WhereClause}; use html::highlight; use html::item_type::ItemType; @@ -1664,10 +1664,10 @@ fn item_static(w: &mut fmt::Formatter, it: &clean::Item, fn item_function(w: &mut fmt::Formatter, it: &clean::Item, f: &clean::Function) -> fmt::Result { - try!(write!(w, "
{vis}{fn_style}fn \
+    try!(write!(w, "
{vis}{unsafety}fn \
                     {name}{generics}{decl}{where_clause}
", vis = VisSpace(it.visibility), - fn_style = FnStyleSpace(f.fn_style), + unsafety = UnsafetySpace(f.unsafety), name = it.name.as_ref().unwrap().as_slice(), generics = f.generics, where_clause = WhereClause(&f.generics), @@ -1813,13 +1813,13 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result { - fn method(w: &mut fmt::Formatter, it: &clean::Item, fn_style: ast::FnStyle, + fn method(w: &mut fmt::Formatter, it: &clean::Item, unsafety: ast::Unsafety, g: &clean::Generics, selfty: &clean::SelfTy, d: &clean::FnDecl) -> fmt::Result { write!(w, "{}fn
{name}\ {generics}{decl}{where_clause}", - match fn_style { - ast::UnsafeFn => "unsafe ", + match unsafety { + ast::Unsafety::Unsafe => "unsafe ", _ => "", }, ty = shortty(it), @@ -1841,10 +1841,10 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result { } match meth.inner { clean::TyMethodItem(ref m) => { - method(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl) + method(w, meth, m.unsafety, &m.generics, &m.self_, &m.decl) } clean::MethodItem(ref m) => { - method(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl) + method(w, meth, m.unsafety, &m.generics, &m.self_, &m.decl) } clean::AssociatedTypeItem(ref typ) => { assoc_type(w, meth, typ) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b5b34ef6efe..1706df10d9a 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -121,7 +121,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub fn visit_fn(&mut self, item: &ast::Item, name: ast::Ident, fd: &ast::FnDecl, - fn_style: &ast::FnStyle, _abi: &abi::Abi, + unsafety: &ast::Unsafety, _abi: &abi::Abi, gen: &ast::Generics) -> Function { debug!("Visiting fn"); Function { @@ -133,7 +133,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { name: name, whence: item.span, generics: gen.clone(), - fn_style: *fn_style, + unsafety: *unsafety, } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ae7a2127e9f..812b1baa8f7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -20,7 +20,6 @@ pub use self::Decl_::*; pub use self::ExplicitSelf_::*; pub use self::Expr_::*; pub use self::FloatTy::*; -pub use self::FnStyle::*; pub use self::FunctionRetTy::*; pub use self::ForeignItem_::*; pub use self::ImplItem::*; @@ -1027,7 +1026,7 @@ pub struct TypeField { pub struct TypeMethod { pub ident: Ident, pub attrs: Vec, - pub fn_style: FnStyle, + pub unsafety: Unsafety, pub abi: Abi, pub decl: P, pub generics: Generics, @@ -1198,7 +1197,7 @@ impl fmt::Show for Onceness { #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct ClosureTy { pub lifetimes: Vec, - pub fn_style: FnStyle, + pub unsafety: Unsafety, pub onceness: Onceness, pub decl: P, pub bounds: TyParamBounds, @@ -1206,7 +1205,7 @@ pub struct ClosureTy { #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct BareFnTy { - pub fn_style: FnStyle, + pub unsafety: Unsafety, pub abi: Abi, pub lifetimes: Vec, pub decl: P @@ -1304,21 +1303,17 @@ pub struct FnDecl { pub variadic: bool } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] -pub enum FnStyle { - /// Declared with "unsafe fn" - UnsafeFn, - /// Declared with "fn" - NormalFn, +#[deriving(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +pub enum Unsafety { + Unsafe, + Normal, } -impl Copy for FnStyle {} - -impl fmt::Show for FnStyle { +impl fmt::Show for Unsafety { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - NormalFn => "normal".fmt(f), - UnsafeFn => "unsafe".fmt(f), + Unsafety::Normal => "normal".fmt(f), + Unsafety::Unsafe => "unsafe".fmt(f), } } } @@ -1371,7 +1366,7 @@ pub enum Method_ { Generics, Abi, ExplicitSelf, - FnStyle, + Unsafety, P, P, Visibility), @@ -1609,7 +1604,7 @@ pub struct Item { pub enum Item_ { ItemStatic(P, Mutability, P), ItemConst(P, P), - ItemFn(P, FnStyle, Abi, Generics, P), + ItemFn(P, Unsafety, Abi, Generics, P), ItemMod(Mod), ItemForeignMod(ForeignMod), ItemTy(P, Generics), diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 5462918b662..6decfd1c3ad 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -122,7 +122,7 @@ impl<'a> Code<'a> { struct ItemFnParts<'a> { ident: ast::Ident, decl: &'a ast::FnDecl, - style: ast::FnStyle, + unsafety: ast::Unsafety, abi: abi::Abi, generics: &'a ast::Generics, body: &'a Block, @@ -182,7 +182,7 @@ impl<'a> FnLikeNode<'a> { pub fn kind(self) -> visit::FnKind<'a> { let item = |: p: ItemFnParts<'a>| -> visit::FnKind<'a> { - visit::FkItemFn(p.ident, p.generics, p.style, p.abi) + visit::FkItemFn(p.ident, p.generics, p.unsafety, p.abi) }; let closure = |: _: ClosureParts| { visit::FkFnBlock @@ -200,9 +200,9 @@ impl<'a> FnLikeNode<'a> { { match self.node { ast_map::NodeItem(i) => match i.node { - ast::ItemFn(ref decl, style, abi, ref generics, ref block) => + ast::ItemFn(ref decl, unsafety, abi, ref generics, ref block) => item_fn(ItemFnParts{ - ident: i.ident, decl: &**decl, style: style, body: &**block, + ident: i.ident, decl: &**decl, unsafety: unsafety, body: &**block, generics: generics, abi: abi, id: i.id, span: i.span }), _ => panic!("item FnLikeNode that is not fn-like"), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 7579972c6d8..63c95a976d4 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -233,14 +233,14 @@ pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod { ref generics, abi, ref explicit_self, - fn_style, + unsafety, ref decl, _, vis) => { TypeMethod { ident: ident, attrs: method.attrs.clone(), - fn_style: fn_style, + unsafety: unsafety, decl: (*decl).clone(), generics: generics.clone(), explicit_self: (*explicit_self).clone(), @@ -722,7 +722,7 @@ pub trait PostExpansionMethod { fn pe_generics<'a>(&'a self) -> &'a ast::Generics; fn pe_abi(&self) -> Abi; fn pe_explicit_self<'a>(&'a self) -> &'a ast::ExplicitSelf; - fn pe_fn_style(&self) -> ast::FnStyle; + fn pe_unsafety(&self) -> ast::Unsafety; fn pe_fn_decl<'a>(&'a self) -> &'a ast::FnDecl; fn pe_body<'a>(&'a self) -> &'a ast::Block; fn pe_vis(&self) -> ast::Visibility; @@ -749,7 +749,7 @@ impl PostExpansionMethod for Method { mf_method!(pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi) mf_method!(pe_explicit_self,&'a ast::ExplicitSelf, MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self) - mf_method!(pe_fn_style,ast::FnStyle,MethDecl(_,_,_,_,fn_style,_,_,_),fn_style) + mf_method!(pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety) mf_method!(pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl) mf_method!(pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body) mf_method!(pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 84040bcfa9f..d35091f8ab0 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -969,7 +969,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { name, Vec::new(), ast::ItemFn(self.fn_decl(inputs, output), - ast::NormalFn, + ast::Unsafety::Normal, abi::Rust, generics, body)) diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index a75be40604e..820ff08a255 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -684,7 +684,7 @@ impl<'a> MethodDef<'a> { fn_generics, abi, explicit_self, - ast::NormalFn, + ast::Unsafety::Normal, fn_decl, body_block, ast::Inherited) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 611faa2c2c9..c2c77e5a16c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -415,9 +415,9 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt)) } TyClosure(f) => { - TyClosure(f.map(|ClosureTy {fn_style, onceness, bounds, decl, lifetimes}| { + TyClosure(f.map(|ClosureTy {unsafety, onceness, bounds, decl, lifetimes}| { ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: onceness, bounds: fld.fold_bounds(bounds), decl: fld.fold_fn_decl(decl), @@ -426,9 +426,9 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { })) } TyBareFn(f) => { - TyBareFn(f.map(|BareFnTy {lifetimes, fn_style, abi, decl}| BareFnTy { + TyBareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy { lifetimes: fld.fold_lifetime_defs(lifetimes), - fn_style: fn_style, + unsafety: unsafety, abi: abi, decl: fld.fold_fn_decl(decl) })) @@ -983,10 +983,10 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { ItemConst(t, e) => { ItemConst(folder.fold_ty(t), folder.fold_expr(e)) } - ItemFn(decl, fn_style, abi, generics, body) => { + ItemFn(decl, unsafety, abi, generics, body) => { ItemFn( folder.fold_fn_decl(decl), - fn_style, + unsafety, abi, folder.fold_generics(generics), folder.fold_block(body) @@ -1077,7 +1077,7 @@ pub fn noop_fold_type_method(m: TypeMethod, fld: &mut T) -> TypeMetho id, ident, attrs, - fn_style, + unsafety, abi, decl, generics, @@ -1089,7 +1089,7 @@ pub fn noop_fold_type_method(m: TypeMethod, fld: &mut T) -> TypeMetho id: fld.new_id(id), ident: fld.fold_ident(ident), attrs: attrs.move_map(|a| fld.fold_attribute(a)), - fn_style: fn_style, + unsafety: unsafety, abi: abi, decl: fld.fold_fn_decl(decl), generics: fld.fold_generics(generics), @@ -1211,7 +1211,7 @@ pub fn noop_fold_method(m: P, folder: &mut T) -> SmallVector< generics, abi, explicit_self, - fn_style, + unsafety, decl, body, vis) => { @@ -1219,7 +1219,7 @@ pub fn noop_fold_method(m: P, folder: &mut T) -> SmallVector< folder.fold_generics(generics), abi, folder.fold_explicit_self(explicit_self), - fn_style, + unsafety, folder.fold_fn_decl(decl), folder.fold_block(body), vis) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 310d5662afa..d6f5d0e248a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1062,7 +1062,7 @@ mod test { span:sp(15,15)})), // not sure variadic: false }), - ast::NormalFn, + ast::Unsafety::Normal, abi::Rust, ast::Generics{ // no idea on either of these: lifetimes: Vec::new(), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 381942a3e62..cc96d45a1c8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -16,7 +16,7 @@ use self::ItemOrViewItem::*; use abi; use ast::{AssociatedType, BareFnTy, ClosureTy}; use ast::{RegionTyParamBound, TraitTyParamBound}; -use ast::{ProvidedMethod, Public, FnStyle}; +use ast::{ProvidedMethod, Public, Unsafety}; use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue}; use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, Block}; use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause}; @@ -34,7 +34,7 @@ use ast::{Many}; use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind}; use ast::{FnOnceUnboxedClosureKind}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; -use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic}; +use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; use ast::{LifetimeDef, Lit, Lit_}; @@ -60,7 +60,7 @@ use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; use ast::{UnnamedField, UnsafeBlock}; -use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; +use ast::{ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; use ast; @@ -1121,7 +1121,7 @@ impl<'a> Parser<'a> { Function Style */ - let fn_style = self.parse_unsafety(); + let unsafety = self.parse_unsafety(); let abi = if self.eat_keyword(keywords::Extern) { self.parse_opt_abi().unwrap_or(abi::C) } else { @@ -1139,7 +1139,7 @@ impl<'a> Parser<'a> { }); TyBareFn(P(BareFnTy { abi: abi, - fn_style: fn_style, + unsafety: unsafety, lifetimes: lifetime_defs, decl: decl })) @@ -1240,7 +1240,7 @@ impl<'a> Parser<'a> { */ - let fn_style = self.parse_unsafety(); + let unsafety = self.parse_unsafety(); let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs); @@ -1266,7 +1266,7 @@ impl<'a> Parser<'a> { }); TyClosure(P(ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: Many, bounds: bounds, decl: decl, @@ -1274,11 +1274,11 @@ impl<'a> Parser<'a> { })) } - pub fn parse_unsafety(&mut self) -> FnStyle { + pub fn parse_unsafety(&mut self) -> Unsafety { if self.eat_keyword(keywords::Unsafe) { - return UnsafeFn; + return Unsafety::Unsafe; } else { - return NormalFn; + return Unsafety::Normal; } } @@ -1351,7 +1351,7 @@ impl<'a> Parser<'a> { let lo = p.span.lo; let vis = p.parse_visibility(); - let style = p.parse_fn_style(); + let style = p.parse_unsafety(); let abi = if p.eat_keyword(keywords::Extern) { p.parse_opt_abi().unwrap_or(abi::C) } else { @@ -1379,7 +1379,7 @@ impl<'a> Parser<'a> { RequiredMethod(TypeMethod { ident: ident, attrs: attrs, - fn_style: style, + unsafety: style, decl: d, generics: generics, abi: abi, @@ -4548,12 +4548,12 @@ impl<'a> Parser<'a> { } /// Parse an item-position function declaration. - fn parse_item_fn(&mut self, fn_style: FnStyle, abi: abi::Abi) -> ItemInfo { + fn parse_item_fn(&mut self, unsafety: Unsafety, abi: abi::Abi) -> ItemInfo { let (ident, mut generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(false); self.parse_where_clause(&mut generics); let (inner_attrs, body) = self.parse_inner_attrs_and_block(); - (ident, ItemFn(decl, fn_style, abi, generics, body), Some(inner_attrs)) + (ident, ItemFn(decl, unsafety, abi, generics, body), Some(inner_attrs)) } /// Parse a method in a trait impl @@ -4591,7 +4591,7 @@ impl<'a> Parser<'a> { self.span.hi) }; (ast::MethMac(m), self.span.hi, attrs) } else { - let fn_style = self.parse_fn_style(); + let unsafety = self.parse_unsafety(); let abi = if self.eat_keyword(keywords::Extern) { self.parse_opt_abi().unwrap_or(abi::C) } else { @@ -4612,7 +4612,7 @@ impl<'a> Parser<'a> { generics, abi, explicit_self, - fn_style, + unsafety, decl, body, visa), @@ -5143,16 +5143,6 @@ impl<'a> Parser<'a> { }) } - /// Parse unsafe or not - fn parse_fn_style(&mut self) -> FnStyle { - if self.eat_keyword(keywords::Unsafe) { - UnsafeFn - } else { - NormalFn - } - } - - /// At this point, this is essentially a wrapper for /// parse_foreign_items. fn parse_foreign_mod_items(&mut self, @@ -5491,7 +5481,7 @@ impl<'a> Parser<'a> { // EXTERN FUNCTION ITEM let abi = opt_abi.unwrap_or(abi::C); let (ident, item_, extra_attrs) = - self.parse_item_fn(NormalFn, abi); + self.parse_item_fn(Unsafety::Normal, abi); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -5554,7 +5544,7 @@ impl<'a> Parser<'a> { // FUNCTION ITEM self.bump(); let (ident, item_, extra_attrs) = - self.parse_item_fn(NormalFn, abi::Rust); + self.parse_item_fn(Unsafety::Normal, abi::Rust); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -5575,7 +5565,7 @@ impl<'a> Parser<'a> { }; self.expect_keyword(keywords::Fn); let (ident, item_, extra_attrs) = - self.parse_item_fn(UnsafeFn, abi); + self.parse_item_fn(Unsafety::Unsafe, abi); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 87905db22f3..53399aba99a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -363,11 +363,11 @@ pub fn ident_to_string(id: &ast::Ident) -> String { $to_string(|s| s.print_ident(*id)) } -pub fn fun_to_string(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident, +pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, name: ast::Ident, opt_explicit_self: Option<&ast::ExplicitSelf_>, generics: &ast::Generics) -> String { $to_string(|s| { - try!(s.print_fn(decl, Some(fn_style), abi::Rust, + try!(s.print_fn(decl, Some(unsafety), abi::Rust, name, generics, opt_explicit_self, ast::Inherited)); try!(s.end()); // Close the head box s.end() // Close the outer box @@ -707,7 +707,7 @@ impl<'a> State<'a> { }; try!(self.print_ty_fn(Some(f.abi), None, - f.fn_style, + f.unsafety, ast::Many, &*f.decl, None, @@ -726,7 +726,7 @@ impl<'a> State<'a> { }; try!(self.print_ty_fn(None, Some('&'), - f.fn_style, + f.unsafety, f.onceness, &*f.decl, None, @@ -858,10 +858,10 @@ impl<'a> State<'a> { try!(word(&mut self.s, ";")); try!(self.end()); // end the outer cbox } - ast::ItemFn(ref decl, fn_style, abi, ref typarams, ref body) => { + ast::ItemFn(ref decl, unsafety, abi, ref typarams, ref body) => { try!(self.print_fn( &**decl, - Some(fn_style), + Some(unsafety), abi, item.ident, typarams, @@ -1188,7 +1188,7 @@ impl<'a> State<'a> { try!(self.print_outer_attributes(m.attrs.as_slice())); try!(self.print_ty_fn(None, None, - m.fn_style, + m.unsafety, ast::Many, &*m.decl, Some(m.ident), @@ -1223,12 +1223,12 @@ impl<'a> State<'a> { ref generics, abi, ref explicit_self, - fn_style, + unsafety, ref decl, ref body, vis) => { try!(self.print_fn(&**decl, - Some(fn_style), + Some(unsafety), abi, ident, generics, @@ -2164,14 +2164,14 @@ impl<'a> State<'a> { pub fn print_fn(&mut self, decl: &ast::FnDecl, - fn_style: Option, + unsafety: Option, abi: abi::Abi, name: ast::Ident, generics: &ast::Generics, opt_explicit_self: Option<&ast::ExplicitSelf_>, vis: ast::Visibility) -> IoResult<()> { try!(self.head("")); - try!(self.print_fn_header_info(opt_explicit_self, fn_style, abi, vis)); + try!(self.print_fn_header_info(opt_explicit_self, unsafety, abi, vis)); try!(self.nbsp()); try!(self.print_ident(name)); try!(self.print_generics(generics)); @@ -2588,7 +2588,7 @@ impl<'a> State<'a> { pub fn print_ty_fn(&mut self, opt_abi: Option, opt_sigil: Option, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, onceness: ast::Onceness, decl: &ast::FnDecl, id: Option, @@ -2603,11 +2603,11 @@ impl<'a> State<'a> { if opt_sigil == Some('~') && onceness == ast::Once { try!(word(&mut self.s, "proc")); } else if opt_sigil == Some('&') { - try!(self.print_fn_style(fn_style)); + try!(self.print_unsafety(unsafety)); try!(self.print_extern_opt_abi(opt_abi)); } else { assert!(opt_sigil.is_none()); - try!(self.print_fn_style(fn_style)); + try!(self.print_unsafety(unsafety)); try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi)); try!(word(&mut self.s, "fn")); } @@ -2872,10 +2872,10 @@ impl<'a> State<'a> { } } - pub fn print_opt_fn_style(&mut self, - opt_fn_style: Option) -> IoResult<()> { - match opt_fn_style { - Some(fn_style) => self.print_fn_style(fn_style), + pub fn print_opt_unsafety(&mut self, + opt_unsafety: Option) -> IoResult<()> { + match opt_unsafety { + Some(unsafety) => self.print_unsafety(unsafety), None => Ok(()) } } @@ -2906,11 +2906,11 @@ impl<'a> State<'a> { pub fn print_fn_header_info(&mut self, _opt_explicit_self: Option<&ast::ExplicitSelf_>, - opt_fn_style: Option, + opt_unsafety: Option, abi: abi::Abi, vis: ast::Visibility) -> IoResult<()> { try!(word(&mut self.s, visibility_qualified(vis, "").as_slice())); - try!(self.print_opt_fn_style(opt_fn_style)); + try!(self.print_opt_unsafety(opt_unsafety)); if abi != abi::Rust { try!(self.word_nbsp("extern")); @@ -2920,10 +2920,10 @@ impl<'a> State<'a> { word(&mut self.s, "fn") } - pub fn print_fn_style(&mut self, s: ast::FnStyle) -> IoResult<()> { + pub fn print_unsafety(&mut self, s: ast::Unsafety) -> IoResult<()> { match s { - ast::NormalFn => Ok(()), - ast::UnsafeFn => self.word_nbsp("unsafe"), + ast::Unsafety::Normal => Ok(()), + ast::Unsafety::Unsafe => self.word_nbsp("unsafe"), } } } @@ -2950,7 +2950,7 @@ mod test { variadic: false }; let generics = ast_util::empty_generics(); - assert_eq!(fun_to_string(&decl, ast::NormalFn, abba_ident, + assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, abba_ident, None, &generics), "fn abba()"); } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index ca2f190ce76..155cabb153c 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -123,7 +123,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) { match i.node { - ast::ItemFn(_, ast::UnsafeFn, _, _, _) => { + ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _) => { let diag = self.cx.span_diagnostic; diag.span_fatal(i.span, "unsafe functions cannot be used for \ diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index eca99df8e55..6eedb77889a 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -34,7 +34,7 @@ use owned_slice::OwnedSlice; pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() - FkItemFn(Ident, &'a Generics, FnStyle, Abi), + FkItemFn(Ident, &'a Generics, Unsafety, Abi), /// fn foo(&self) FkMethod(Ident, &'a Generics, &'a Method), -- cgit 1.4.1-3-g733a5 From 5686a91914ac678ccb78220367daefe585a0d66a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 9 Dec 2014 19:59:20 -0500 Subject: Parse `unsafe trait` but do not do anything with it beyond parsing and integrating into rustdoc etc. --- src/librustc/lint/builtin.rs | 2 +- src/librustc/metadata/common.rs | 2 ++ src/librustc/metadata/decoder.rs | 5 +++++ src/librustc/metadata/encoder.rs | 11 ++++++++++- src/librustc/middle/privacy.rs | 10 +++++----- src/librustc/middle/resolve.rs | 4 ++-- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/middle/ty.rs | 4 +++- src/librustc_trans/save/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/collect.rs | 12 +++++++----- src/librustc_typeck/variance.rs | 2 +- src/librustdoc/clean/inline.rs | 1 + src/librustdoc/clean/mod.rs | 2 ++ src/librustdoc/doctree.rs | 1 + src/librustdoc/html/render.rs | 3 ++- src/librustdoc/visit_ast.rs | 3 ++- src/libsyntax/ast.rs | 3 ++- src/libsyntax/ast_map/mod.rs | 2 +- src/libsyntax/config.rs | 4 ++-- src/libsyntax/fold.rs | 5 +++-- src/libsyntax/parse/parser.rs | 24 +++++++++++++++++++++--- src/libsyntax/print/pprust.rs | 8 +++++--- src/libsyntax/visit.rs | 2 +- src/test/pretty/trait-safety.rs | 21 +++++++++++++++++++++ 25 files changed, 103 insertions(+), 34 deletions(-) create mode 100644 src/test/pretty/trait-safety.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index e19fa01b2e4..5af7fec4181 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1721,7 +1721,7 @@ impl LintPass for Stability { if self.is_internal(cx, item.span) { return } match item.node { - ast::ItemTrait(_, _, ref supertraits, _) => { + ast::ItemTrait(_, _, _, ref supertraits, _) => { for t in supertraits.iter() { if let ast::TraitTyParamBound(ref t) = *t { let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref); diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 99e7966b66f..b698e4fcc7f 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -255,3 +255,5 @@ pub const tag_method_ty_generics: uint = 0xa7; pub const tag_predicate: uint = 0xa8; pub const tag_predicate_space: uint = 0xa9; pub const tag_predicate_data: uint = 0xb0; + +pub const tag_unsafety: uint = 0xb1; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 4e892f53186..37124286398 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -368,8 +368,13 @@ pub fn get_trait_def<'tcx>(cdata: Cmd, let item_doc = lookup_item(item_id, cdata.data()); let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); let bounds = trait_def_bounds(item_doc, tcx, cdata); + let unsafety = match reader::maybe_get_doc(item_doc, tag_unsafety) { + Some(_) => ast::Unsafety::Unsafe, + None => ast::Unsafety::Normal, + }; ty::TraitDef { + unsafety: unsafety, generics: generics, bounds: bounds, trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata)) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 9804e3c20aa..cb8de256448 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1308,13 +1308,22 @@ fn encode_info_for_item(ecx: &EncodeContext, } } } - ast::ItemTrait(_, _, _, ref ms) => { + ast::ItemTrait(_, _, _, _, ref ms) => { add_to_index(item, rbml_w, index); rbml_w.start_tag(tag_items_data_item); encode_def_id(rbml_w, def_id); encode_family(rbml_w, 'I'); encode_item_variances(rbml_w, ecx, item.id); let trait_def = ty::lookup_trait_def(tcx, def_id); + + match trait_def.unsafety { + ast::Unsafety::Unsafe => { + rbml_w.start_tag(tag_unsafety); + rbml_w.end_tag(); + } + ast::Unsafety::Normal => { } + } + encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics); encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref); encode_name(rbml_w, item.ident.name); diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 79bb19a1e53..352c2add000 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -76,7 +76,7 @@ impl<'v> Visitor<'v> for ParentVisitor { // method to the root. In this case, if the trait is private, then // parent all the methods to the trait to indicate that they're // private. - ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => { + ast::ItemTrait(_, _, _, _, ref methods) if item.vis != ast::Public => { for m in methods.iter() { match *m { ast::ProvidedMethod(ref m) => { @@ -282,7 +282,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // Default methods on traits are all public so long as the trait // is public - ast::ItemTrait(_, _, _, ref methods) if public_first => { + ast::ItemTrait(_, _, _, _, ref methods) if public_first => { for method in methods.iter() { match *method { ast::ProvidedMethod(ref m) => { @@ -1134,7 +1134,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } - ast::ItemTrait(_, _, _, ref methods) => { + ast::ItemTrait(_, _, _, _, ref methods) => { for m in methods.iter() { match *m { ast::ProvidedMethod(ref m) => { @@ -1198,7 +1198,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { ast::ItemStruct(ref def, _) => check_struct(&**def), - ast::ItemTrait(_, _, _, ref methods) => { + ast::ItemTrait(_, _, _, _, ref methods) => { for m in methods.iter() { match *m { ast::RequiredMethod(..) => {} @@ -1305,7 +1305,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // namespace (the contents have their own privacies). ast::ItemForeignMod(_) => {} - ast::ItemTrait(_, _, ref bounds, _) => { + ast::ItemTrait(_, _, _, ref bounds, _) => { if !self.trait_is_public(item.id) { return } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index f2c83291b79..2e52bab2ae3 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1583,7 +1583,7 @@ impl<'a> Resolver<'a> { ItemImpl(_, Some(_), _, _) => parent, - ItemTrait(_, _, _, ref items) => { + ItemTrait(_, _, _, _, ref items) => { let name_bindings = self.add_child(name, parent.clone(), @@ -4241,7 +4241,7 @@ impl<'a> Resolver<'a> { impl_items.as_slice()); } - ItemTrait(ref generics, ref unbound, ref bounds, ref trait_items) => { + ItemTrait(_, ref generics, ref unbound, ref bounds, ref trait_items) => { // Create a new rib for the self type. let mut self_type_rib = Rib::new(ItemRibKind); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ee0fc327020..683948cd2e7 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -106,7 +106,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { ast::ItemTy(_, ref generics) | ast::ItemEnum(_, ref generics) | ast::ItemStruct(_, ref generics) | - ast::ItemTrait(ref generics, _, _, _) => { + ast::ItemTrait(_, ref generics, _, _, _) => { // These kinds of items have only early bound lifetime parameters. let lifetimes = &generics.lifetimes; self.with(EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE), |this| { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9673b9ab586..4c4df698f33 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1915,6 +1915,8 @@ pub struct Polytype<'tcx> { /// As `Polytype` but for a trait ref. pub struct TraitDef<'tcx> { + pub unsafety: ast::Unsafety, + /// Generic type definitions. Note that `Self` is listed in here /// as having a single bound, the trait itself (e.g., in the trait /// `Eq`, there is a single bound `Self : Eq`). This is so that @@ -4572,7 +4574,7 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) match cx.map.find(id.node) { Some(ast_map::NodeItem(item)) => { match item.node { - ItemTrait(_, _, _, ref ms) => { + ItemTrait(_, _, _, _, ref ms) => { let (_, p) = ast_util::split_trait_methods(ms.as_slice()); p.iter() diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 329241b24e6..779fcd70864 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1050,7 +1050,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { &**typ, impl_items) } - ast::ItemTrait(ref generics, _, ref trait_refs, ref methods) => + ast::ItemTrait(_, ref generics, _, ref trait_refs, ref methods) => self.process_trait(item, generics, trait_refs, methods), ast::ItemMod(ref m) => self.process_mod(item, m), ast::ItemTy(ref ty, ref ty_params) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5b1ca8fc1c0..c64519c96dd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -625,7 +625,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { } } - ast::ItemTrait(_, _, _, ref trait_methods) => { + ast::ItemTrait(_, _, _, _, ref trait_methods) => { let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); for trait_method in trait_methods.iter() { match *trait_method { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0bb0f95a66b..643d8eb60ce 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -258,7 +258,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_def: &ty::TraitDef<'tcx>) { let tcx = ccx.tcx; if let ast_map::NodeItem(item) = tcx.map.get(trait_id) { - if let ast::ItemTrait(_, _, _, ref trait_items) = item.node { + if let ast::ItemTrait(_, _, _, _, ref trait_items) = item.node { // For each method, construct a suitable ty::Method and // store it into the `tcx.impl_or_trait_items` table: for trait_item in trait_items.iter() { @@ -1144,7 +1144,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { AllowEqConstraints::DontAllow); } }, - ast::ItemTrait(_, _, _, ref trait_methods) => { + ast::ItemTrait(_, _, _, _, ref trait_methods) => { let trait_def = trait_def_of_item(ccx, it); debug!("trait_def: ident={} trait_def={}", @@ -1335,12 +1335,13 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return def.clone(); } - let (generics, unbound, bounds, items) = match it.node { - ast::ItemTrait(ref generics, + let (unsafety, generics, unbound, bounds, items) = match it.node { + ast::ItemTrait(unsafety, + ref generics, ref unbound, ref supertraits, ref items) => { - (generics, unbound, supertraits, items.as_slice()) + (unsafety, generics, unbound, supertraits, items.as_slice()) } ref s => { tcx.sess.span_bug( @@ -1369,6 +1370,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let substs = mk_item_substs(ccx, &ty_generics); let trait_def = Rc::new(ty::TraitDef { + unsafety: unsafety, generics: ty_generics, bounds: bounds, trait_ref: Rc::new(ty::TraitRef { diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index bd7db560d9e..8fe14bae0f5 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -358,7 +358,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { match item.node { ast::ItemEnum(_, ref generics) | ast::ItemStruct(_, ref generics) | - ast::ItemTrait(ref generics, _, _, _) => { + ast::ItemTrait(_, ref generics, _, _, _) => { for (i, p) in generics.lifetimes.iter().enumerate() { let id = p.lifetime.id; self.add_inferred(item.id, RegionParam, TypeSpace, i, id); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 75cf0c7a26b..a7d7c520755 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -161,6 +161,7 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, let trait_def = ty::lookup_trait_def(tcx, did); let (bounds, default_unbound) = trait_def.bounds.clean(cx); clean::Trait { + unsafety: def.unsafety, generics: (&def.generics, subst::TypeSpace).clean(cx), items: items.collect(), bounds: bounds, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1d0929746c2..92184ce93de 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -974,6 +974,7 @@ impl Clean for ast::FunctionRetTy { #[deriving(Clone, Encodable, Decodable)] pub struct Trait { + pub unsafety: ast::Unsafety, pub items: Vec, pub generics: Generics, pub bounds: Vec, @@ -991,6 +992,7 @@ impl Clean for doctree::Trait { visibility: self.vis.clean(cx), stability: self.stab.clean(cx), inner: TraitItem(Trait { + unsafety: self.unsafety, items: self.items.clean(cx), generics: self.generics.clean(cx), bounds: self.bounds.clean(cx), diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index a25d4352430..79f04e91260 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -170,6 +170,7 @@ pub struct Constant { } pub struct Trait { + pub unsafety: ast::Unsafety, pub name: Ident, pub items: Vec, //should be TraitItem pub generics: ast::Generics, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 54b7ead5469..1977b6320d0 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1693,8 +1693,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } // Output the trait definition - try!(write!(w, "
{}trait {}{}{}{} ",
+    try!(write!(w, "
{}{}trait {}{}{}{} ",
                   VisSpace(it.visibility),
+                  UnsafetySpace(t.unsafety),
                   it.name.as_ref().unwrap().as_slice(),
                   t.generics,
                   bounds,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 1706df10d9a..f94e647b1cf 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -322,8 +322,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.constants.push(s);
             },
-            ast::ItemTrait(ref gen, ref def_ub, ref b, ref items) => {
+            ast::ItemTrait(unsafety, ref gen, ref def_ub, ref b, ref items) => {
                 let t = Trait {
+                    unsafety: unsafety,
                     name: name,
                     items: items.clone(),
                     generics: gen.clone(),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 812b1baa8f7..1cc6b6feee8 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1611,7 +1611,8 @@ pub enum Item_ {
     ItemEnum(EnumDef, Generics),
     ItemStruct(P, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Generics,
+    ItemTrait(Unsafety,
+              Generics,
               Option, // (optional) default bound not required for Self.
                                 // Currently, only Sized makes sense here.
               TyParamBounds,
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 6f1d2d39b30..a2cdc4d2fbc 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -786,7 +786,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                     None => {}
                 }
             }
-            ItemTrait(_, _, ref bounds, ref trait_items) => {
+            ItemTrait(_, _, _, ref bounds, ref trait_items) => {
                 for b in bounds.iter() {
                     if let TraitTyParamBound(ref t) = *b {
                         self.insert(t.trait_ref.ref_id, NodeItem(i));
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 87426dce918..ee651592117 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -139,11 +139,11 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_
                                        .collect();
             ast::ItemImpl(a, b, c, impl_items)
         }
-        ast::ItemTrait(a, b, c, methods) => {
+        ast::ItemTrait(u, a, b, c, methods) => {
             let methods = methods.into_iter()
                                  .filter(|m| trait_method_in_cfg(cx, m))
                                  .collect();
-            ast::ItemTrait(a, b, c, methods)
+            ast::ItemTrait(u, a, b, c, methods)
         }
         ast::ItemStruct(def, generics) => {
             ast::ItemStruct(fold_struct(cx, def), generics)
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index c2c77e5a16c..daed014f4eb 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1035,7 +1035,7 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
                      folder.fold_ty(ty),
                      new_impl_items)
         }
-        ItemTrait(generics, unbound, bounds, methods) => {
+        ItemTrait(unsafety, generics, unbound, bounds, methods) => {
             let bounds = folder.fold_bounds(bounds);
             let methods = methods.into_iter().flat_map(|method| {
                 let r = match method {
@@ -1063,7 +1063,8 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
                 };
                 r
             }).collect();
-            ItemTrait(folder.fold_generics(generics),
+            ItemTrait(unsafety,
+                      folder.fold_generics(generics),
                       unbound,
                       bounds,
                       methods)
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index cc96d45a1c8..b2c30797cac 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4628,7 +4628,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse trait Foo { ... }
-    fn parse_item_trait(&mut self) -> ItemInfo {
+    fn parse_item_trait(&mut self, unsafety: Unsafety) -> ItemInfo {
         let ident = self.parse_ident();
         let mut tps = self.parse_generics();
         let sized = self.parse_for_sized();
@@ -4639,7 +4639,7 @@ impl<'a> Parser<'a> {
         self.parse_where_clause(&mut tps);
 
         let meths = self.parse_trait_items();
-        (ident, ItemTrait(tps, sized, bounds, meths), None)
+        (ident, ItemTrait(unsafety, tps, sized, bounds, meths), None)
     }
 
     fn parse_impl_items(&mut self) -> (Vec, Vec) {
@@ -5539,6 +5539,23 @@ impl<'a> Parser<'a> {
                                     maybe_append(attrs, extra_attrs));
             return IoviItem(item);
         }
+        if self.token.is_keyword(keywords::Unsafe) &&
+            self.look_ahead(1u, |t| t.is_keyword(keywords::Trait))
+        {
+            // UNSAFE TRAIT ITEM
+            self.expect_keyword(keywords::Unsafe);
+            self.expect_keyword(keywords::Trait);
+            let (ident, item_, extra_attrs) =
+                self.parse_item_trait(ast::Unsafety::Unsafe);
+            let last_span = self.last_span;
+            let item = self.mk_item(lo,
+                                    last_span.hi,
+                                    ident,
+                                    item_,
+                                    visibility,
+                                    maybe_append(attrs, extra_attrs));
+            return IoviItem(item);
+        }
         if self.token.is_keyword(keywords::Fn) &&
                 self.look_ahead(1, |f| !Parser::fn_expr_lookahead(f)) {
             // FUNCTION ITEM
@@ -5614,7 +5631,8 @@ impl<'a> Parser<'a> {
         }
         if self.eat_keyword(keywords::Trait) {
             // TRAIT ITEM
-            let (ident, item_, extra_attrs) = self.parse_item_trait();
+            let (ident, item_, extra_attrs) =
+                self.parse_item_trait(ast::Unsafety::Normal);
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 53399aba99a..037118b145f 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -955,9 +955,11 @@ impl<'a> State<'a> {
                 }
                 try!(self.bclose(item.span));
             }
-            ast::ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => {
-                try!(self.head(visibility_qualified(item.vis,
-                                                    "trait").as_slice()));
+            ast::ItemTrait(unsafety, ref generics, ref unbound, ref bounds, ref methods) => {
+                try!(self.head(""));
+                try!(self.print_visibility(item.vis));
+                try!(self.print_unsafety(unsafety));
+                try!(self.word_nbsp("trait"));
                 try!(self.print_ident(item.ident));
                 try!(self.print_generics(generics));
                 if let &Some(ref tref) = unbound {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 6eedb77889a..7bb79a15f45 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -311,7 +311,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
                                      generics,
                                      item.id)
         }
-        ItemTrait(ref generics, _, ref bounds, ref methods) => {
+        ItemTrait(_, ref generics, _, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
             walk_ty_param_bounds_helper(visitor, bounds);
             for method in methods.iter() {
diff --git a/src/test/pretty/trait-safety.rs b/src/test/pretty/trait-safety.rs
new file mode 100644
index 00000000000..42e578482e6
--- /dev/null
+++ b/src/test/pretty/trait-safety.rs
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+// pp-exact
+
+unsafe trait UnsafeTrait {
+    fn foo(&self);
+}
+
+pub unsafe trait PubUnsafeTrait {
+    fn foo(&self);
+}
+
+fn main() { }
-- 
cgit 1.4.1-3-g733a5


From 22f777ba2ecfcd8d914d37db310a6feb4ad5219e Mon Sep 17 00:00:00 2001
From: Niko Matsakis 
Date: Wed, 10 Dec 2014 06:15:06 -0500
Subject: Parse `unsafe impl` but don't do anything particularly interesting
 with the results.

---
 src/librustc/lint/builtin.rs                 |  2 +-
 src/librustc/metadata/decoder.rs             | 14 ++++++++++----
 src/librustc/metadata/encoder.rs             | 23 ++++++++++++-----------
 src/librustc/middle/dead.rs                  |  2 +-
 src/librustc/middle/infer/error_reporting.rs |  2 +-
 src/librustc/middle/privacy.rs               | 10 +++++-----
 src/librustc/middle/reachable.rs             |  4 ++--
 src/librustc/middle/resolve.rs               |  7 ++++---
 src/librustc/middle/resolve_lifetime.rs      |  2 +-
 src/librustc/middle/ty.rs                    |  4 ++--
 src/librustc_trans/save/mod.rs               |  5 +++--
 src/librustc_trans/trans/base.rs             |  2 +-
 src/librustc_typeck/check/mod.rs             |  2 +-
 src/librustc_typeck/coherence/mod.rs         |  4 ++--
 src/librustc_typeck/coherence/orphan.rs      |  4 ++--
 src/librustc_typeck/collect.rs               |  3 ++-
 src/librustdoc/doctree.rs                    |  1 +
 src/librustdoc/visit_ast.rs                  |  3 ++-
 src/libsyntax/ast.rs                         |  3 ++-
 src/libsyntax/ast_map/mod.rs                 |  2 +-
 src/libsyntax/config.rs                      |  4 ++--
 src/libsyntax/ext/deriving/generic/mod.rs    |  3 ++-
 src/libsyntax/feature_gate.rs                |  2 +-
 src/libsyntax/fold.rs                        |  7 ++++---
 src/libsyntax/parse/parser.rs                | 22 +++++++++++++++++++---
 src/libsyntax/print/pprust.rs                | 10 +++++++---
 src/libsyntax/visit.rs                       |  3 ++-
 src/test/pretty/trait-safety.rs              |  4 ++++
 28 files changed, 97 insertions(+), 57 deletions(-)

(limited to 'src/libsyntax/parse/parser.rs')

diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 5af7fec4181..3040125d97e 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -1729,7 +1729,7 @@ impl LintPass for Stability {
                     }
                 }
             }
-            ast::ItemImpl(_, Some(ref t), _, _) => {
+            ast::ItemImpl(_, _, Some(ref t), _, _) => {
                 let id = ty::trait_ref_to_def_id(cx.tcx, t);
                 self.lint(cx, id, t.path.span);
             }
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 37124286398..b78112f1f78 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -361,6 +361,15 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
     }
 }
 
+fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety {
+    let unsafety_doc = reader::get_doc(item_doc, tag_unsafety);
+    if reader::doc_as_u8(unsafety_doc) != 0 {
+        ast::Unsafety::Unsafe
+    } else {
+        ast::Unsafety::Normal
+    }
+}
+
 pub fn get_trait_def<'tcx>(cdata: Cmd,
                            item_id: ast::NodeId,
                            tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx>
@@ -368,10 +377,7 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
     let item_doc = lookup_item(item_id, cdata.data());
     let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
     let bounds = trait_def_bounds(item_doc, tcx, cdata);
-    let unsafety = match reader::maybe_get_doc(item_doc, tag_unsafety) {
-        Some(_) => ast::Unsafety::Unsafe,
-        None => ast::Unsafety::Normal,
-    };
+    let unsafety = parse_unsafety(item_doc);
 
     ty::TraitDef {
         unsafety: unsafety,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index cb8de256448..a1f04b7412b 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -1205,7 +1205,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             None => {}
         }
       }
-      ast::ItemImpl(_, ref opt_trait, ref ty, ref ast_items) => {
+      ast::ItemImpl(unsafety, _, ref opt_trait, ref ty, ref ast_items) => {
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
         let impl_items = tcx.impl_items.borrow();
@@ -1218,6 +1218,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
         encode_name(rbml_w, item.ident.name);
         encode_attributes(rbml_w, item.attrs.as_slice());
+        encode_unsafety(rbml_w, unsafety);
         match ty.node {
             ast::TyPath(ref path, _) if path.segments
                                                         .len() == 1 => {
@@ -1315,15 +1316,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_family(rbml_w, 'I');
         encode_item_variances(rbml_w, ecx, item.id);
         let trait_def = ty::lookup_trait_def(tcx, def_id);
-
-        match trait_def.unsafety {
-            ast::Unsafety::Unsafe => {
-                rbml_w.start_tag(tag_unsafety);
-                rbml_w.end_tag();
-            }
-            ast::Unsafety::Normal => { }
-        }
-
+        encode_unsafety(rbml_w, trait_def.unsafety);
         encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
         encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
         encode_name(rbml_w, item.ident.name);
@@ -1683,6 +1676,14 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
     rbml_w.end_tag();
 }
 
+fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
+    let byte: u8 = match unsafety {
+        ast::Unsafety::Normal => 0,
+        ast::Unsafety::Unsafe => 1,
+    };
+    rbml_w.wr_tagged_u8(tag_unsafety, byte);
+}
+
 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
     fn get_ordered_deps(cstore: &cstore::CStore) -> Vec {
         // Pull the cnums and name,vers,hash out of cstore
@@ -1864,7 +1865,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
 
 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
     fn visit_item(&mut self, item: &ast::Item) {
-        if let ast::ItemImpl(_, Some(ref trait_ref), _, _) = item.node {
+        if let ast::ItemImpl(_, _, Some(ref trait_ref), _, _) = item.node {
             let def_map = &self.ecx.tcx.def_map;
             let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
             let def_id = trait_def.def_id();
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index d2f43faa003..939775e7507 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -355,7 +355,7 @@ impl<'v> Visitor<'v> for LifeSeeder {
             ast::ItemEnum(ref enum_def, _) if allow_dead_code => {
                 self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
             }
-            ast::ItemImpl(_, Some(ref _trait_ref), _, ref impl_items) => {
+            ast::ItemImpl(_, _, Some(ref _trait_ref), _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
                         ast::MethodImplItem(ref method) => {
diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index c638182d7f3..5c2944f898e 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -1690,7 +1690,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
         match tcx.map.find(parent) {
             Some(node) => match node {
                 ast_map::NodeItem(item) => match item.node {
-                    ast::ItemImpl(ref gen, _, _, _) => {
+                    ast::ItemImpl(_, ref gen, _, _, _) => {
                         taken.push_all(gen.lifetimes.as_slice());
                     }
                     _ => ()
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 352c2add000..8cce1321d72 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -241,7 +241,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
             //   undefined symbols at linkage time if this case is not handled.
             //
             // * Private trait impls for private types can be completely ignored
-            ast::ItemImpl(_, _, ref ty, ref impl_items) => {
+            ast::ItemImpl(_, _, _, ref ty, ref impl_items) => {
                 let public_ty = match ty.node {
                     ast::TyPath(_, id) => {
                         match self.tcx.def_map.borrow()[id].clone() {
@@ -611,7 +611,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                     // invoked, and the struct/enum itself is private. Crawl
                     // back up the chains to find the relevant struct/enum that
                     // was private.
-                    ast::ItemImpl(_, _, ref ty, _) => {
+                    ast::ItemImpl(_, _, _, ref ty, _) => {
                         let id = match ty.node {
                             ast::TyPath(_, id) => id,
                             _ => return Some((err_span, err_msg, None)),
@@ -1096,7 +1096,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
         match item.node {
             // implementations of traits don't need visibility qualifiers because
             // that's controlled by having the trait in scope.
-            ast::ItemImpl(_, Some(..), _, ref impl_items) => {
+            ast::ItemImpl(_, _, Some(..), _, ref impl_items) => {
                 check_inherited(item.span, item.vis,
                                 "visibility qualifiers have no effect on trait \
                                  impls");
@@ -1175,7 +1175,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
         };
         check_inherited(tcx, item.span, item.vis);
         match item.node {
-            ast::ItemImpl(_, _, _, ref impl_items) => {
+            ast::ItemImpl(_, _, _, _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
                         ast::MethodImplItem(ref m) => {
@@ -1320,7 +1320,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
             // (i.e. we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
             // publicly visible.
-            ast::ItemImpl(ref g, ref trait_ref, ref self_, ref impl_items) => {
+            ast::ItemImpl(_, ref g, ref trait_ref, ref self_, ref impl_items) => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // impl [... for] Public<...>, but not `impl [... for]
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index fa02c940aa7..38d3b859c9d 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -55,7 +55,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
     }
 
     match item.node {
-        ast::ItemImpl(ref generics, _, _, _) |
+        ast::ItemImpl(_, ref generics, _, _, _) |
         ast::ItemFn(_, _, _, ref generics, _) => {
             generics_require_inlining(generics)
         }
@@ -216,7 +216,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                                       .map
                                       .expect_item(impl_did.node)
                                       .node {
-                                ast::ItemImpl(ref generics, _, _, _) => {
+                                ast::ItemImpl(_, ref generics, _, _, _) => {
                                     generics_require_inlining(generics)
                                 }
                                 _ => false
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 2e52bab2ae3..c6fdd845ea7 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -1432,7 +1432,7 @@ impl<'a> Resolver<'a> {
                 parent
             }
 
-            ItemImpl(_, None, ref ty, ref impl_items) => {
+            ItemImpl(_, _, None, ref ty, ref impl_items) => {
                 // If this implements an anonymous trait, then add all the
                 // methods within to a new module, if the type was defined
                 // within this module.
@@ -1581,7 +1581,7 @@ impl<'a> Resolver<'a> {
                 parent
             }
 
-            ItemImpl(_, Some(_), _, _) => parent,
+            ItemImpl(_, _, Some(_), _, _) => parent,
 
             ItemTrait(_, _, _, _, ref items) => {
                 let name_bindings =
@@ -4230,7 +4230,8 @@ impl<'a> Resolver<'a> {
                 });
             }
 
-            ItemImpl(ref generics,
+            ItemImpl(_,
+                     ref generics,
                      ref implemented_traits,
                      ref self_type,
                      ref impl_items) => {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 683948cd2e7..48d6ac847d8 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -114,7 +114,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                     visit::walk_item(this, item);
                 });
             }
-            ast::ItemImpl(ref generics, _, _, _) => {
+            ast::ItemImpl(_, ref generics, _, _, _) => {
                 // Impls have both early- and late-bound lifetimes.
                 self.visit_early_late(subst::TypeSpace, generics, |this| {
                     this.check_lifetime_defs(&generics.lifetimes);
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 4c4df698f33..d6fd3d9a943 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -4741,7 +4741,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
             match cx.map.find(id.node) {
                 Some(ast_map::NodeItem(item)) => {
                     match item.node {
-                        ast::ItemImpl(_, ref opt_trait, _, _) => {
+                        ast::ItemImpl(_, _, ref opt_trait, _, _) => {
                             match opt_trait {
                                 &Some(ref t) => {
                                     Some(ty::node_id_to_trait_ref(cx, t.ref_id))
@@ -5722,7 +5722,7 @@ pub fn trait_id_of_impl(tcx: &ctxt,
     match node {
         ast_map::NodeItem(item) => {
             match item.node {
-                ast::ItemImpl(_, Some(ref trait_ref), _, _) => {
+                ast::ItemImpl(_, _, Some(ref trait_ref), _, _) => {
                     Some(node_id_to_trait_ref(tcx, trait_ref.ref_id).def_id)
                 }
                 _ => None
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index 779fcd70864..712d6217dde 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -282,7 +282,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                 NodeItem(item) => {
                     scope_id = item.id;
                     match item.node {
-                        ast::ItemImpl(_, _, ref ty, _) => {
+                        ast::ItemImpl(_, _, _, ref ty, _) => {
                             let mut result = String::from_str("<");
                             result.push_str(ty_to_string(&**ty).as_slice());
 
@@ -1040,7 +1040,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                 self.process_const(item, &**typ, &**expr),
             ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params),
             ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
-            ast::ItemImpl(ref ty_params,
+            ast::ItemImpl(_,
+                          ref ty_params,
                           ref trait_ref,
                           ref typ,
                           ref impl_items) => {
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index b2578fdbc05..83779ffbe16 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -2304,7 +2304,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
         let mut v = TransItemVisitor{ ccx: ccx };
         v.visit_block(&**body);
       }
-      ast::ItemImpl(ref generics, _, _, ref impl_items) => {
+      ast::ItemImpl(_, ref generics, _, _, ref impl_items) => {
         meth::trans_impl(ccx,
                          item.ident,
                          impl_items.as_slice(),
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index c64519c96dd..e0df94745d6 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -595,7 +595,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
         let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
         check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
       }
-      ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
+      ast::ItemImpl(_, _, ref opt_trait_ref, _, ref impl_items) => {
         debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
 
         let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index defad95f749..7bc79d6e4a4 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -145,7 +145,7 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
         //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
 
         match item.node {
-            ItemImpl(_, ref opt_trait, _, _) => {
+            ItemImpl(_, _, ref opt_trait, _, _) => {
                 match opt_trait.clone() {
                     Some(opt_trait) => {
                         self.cc.check_implementation(item, &[opt_trait]);
@@ -325,7 +325,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
     // Converts an implementation in the AST to a vector of items.
     fn create_impl_from_item(&self, item: &Item) -> Vec {
         match item.node {
-            ItemImpl(_, ref trait_refs, _, ref ast_items) => {
+            ItemImpl(_, _, ref trait_refs, _, ref ast_items) => {
                 let mut items: Vec =
                         ast_items.iter()
                                  .map(|ast_item| {
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index dc3afaae35f..1803bf766dd 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -44,7 +44,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v ast::Item) {
         let def_id = ast_util::local_def(item.id);
         match item.node {
-            ast::ItemImpl(_, None, _, _) => {
+            ast::ItemImpl(_, _, None, _, _) => {
                 // For inherent impls, self type must be a nominal type
                 // defined in this crate.
                 debug!("coherence2::orphan check: inherent impl {}", item.repr(self.tcx));
@@ -64,7 +64,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
                     }
                 }
             }
-            ast::ItemImpl(_, Some(_), _, _) => {
+            ast::ItemImpl(_, _, Some(_), _, _) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
                 if traits::is_orphan_impl(self.tcx, def_id) {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 643d8eb60ce..61b8e6c956c 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1045,7 +1045,8 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                                    enum_definition.variants.as_slice(),
                                    generics);
         },
-        ast::ItemImpl(ref generics,
+        ast::ItemImpl(_,
+                      ref generics,
                       ref opt_trait_ref,
                       ref selfty,
                       ref impl_items) => {
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 79f04e91260..6592ca498dc 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -184,6 +184,7 @@ pub struct Trait {
 }
 
 pub struct Impl {
+    pub unsafety: ast::Unsafety,
     pub generics: ast::Generics,
     pub trait_: Option,
     pub for_: P,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index f94e647b1cf..4374ce5deef 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -338,8 +338,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.traits.push(t);
             },
-            ast::ItemImpl(ref gen, ref tr, ref ty, ref items) => {
+            ast::ItemImpl(unsafety, ref gen, ref tr, ref ty, ref items) => {
                 let i = Impl {
+                    unsafety: unsafety,
                     generics: gen.clone(),
                     trait_: tr.clone(),
                     for_: ty.clone(),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 1cc6b6feee8..206fb26eb55 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1617,7 +1617,8 @@ pub enum Item_ {
                                 // Currently, only Sized makes sense here.
               TyParamBounds,
               Vec),
-    ItemImpl(Generics,
+    ItemImpl(Unsafety,
+             Generics,
              Option, // (optional) trait this impl implements
              P, // self
              Vec),
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index a2cdc4d2fbc..6089f39e828 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -755,7 +755,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
         let parent = self.parent;
         self.parent = i.id;
         match i.node {
-            ItemImpl(_, _, _, ref impl_items) => {
+            ItemImpl(_, _, _, _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
                         MethodImplItem(ref m) => {
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index ee651592117..d2185a00876 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -133,11 +133,11 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_
     F: FnMut(&[ast::Attribute]) -> bool
 {
     let item = match item {
-        ast::ItemImpl(a, b, c, impl_items) => {
+        ast::ItemImpl(u, a, b, c, impl_items) => {
             let impl_items = impl_items.into_iter()
                                        .filter(|ii| impl_item_in_cfg(cx, ii))
                                        .collect();
-            ast::ItemImpl(a, b, c, impl_items)
+            ast::ItemImpl(u, a, b, c, impl_items)
         }
         ast::ItemTrait(u, a, b, c, methods) => {
             let methods = methods.into_iter()
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 820ff08a255..f40be823a1a 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -462,7 +462,8 @@ impl<'a> TraitDef<'a> {
             self.span,
             ident,
             a,
-            ast::ItemImpl(trait_generics,
+            ast::ItemImpl(ast::Unsafety::Normal,
+                          trait_generics,
                           opt_trait_ref,
                           self_type,
                           methods.into_iter()
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 66fe672c3e5..9656629e14d 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -215,7 +215,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
                 }
             }
 
-            ast::ItemImpl(_, _, _, ref items) => {
+            ast::ItemImpl(_, _, _, _, ref items) => {
                 if attr::contains_name(i.attrs.as_slice(),
                                        "unsafe_destructor") {
                     self.gate_feature("unsafe_destructor",
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index daed014f4eb..8a578c2cb05 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1008,7 +1008,7 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
             let struct_def = folder.fold_struct_def(struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
-        ItemImpl(generics, ifce, ty, impl_items) => {
+        ItemImpl(unsafety, generics, ifce, ty, impl_items) => {
             let mut new_impl_items = Vec::new();
             for impl_item in impl_items.iter() {
                 match *impl_item {
@@ -1030,7 +1030,8 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
                     Some(folder.fold_trait_ref((*trait_ref).clone()))
                 }
             };
-            ItemImpl(folder.fold_generics(generics),
+            ItemImpl(unsafety,
+                     folder.fold_generics(generics),
                      ifce,
                      folder.fold_ty(ty),
                      new_impl_items)
@@ -1160,7 +1161,7 @@ pub fn noop_fold_item_simple(Item {id, ident, attrs, node, vis, span}
     let node = folder.fold_item_underscore(node);
     let ident = match node {
         // The node may have changed, recompute the "pretty" impl name.
-        ItemImpl(_, ref maybe_trait, ref ty, _) => {
+        ItemImpl(_, _, ref maybe_trait, ref ty, _) => {
             ast_util::impl_pretty_name(maybe_trait, &**ty)
         }
         _ => ident
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index b2c30797cac..d1991c0463f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4667,7 +4667,7 @@ impl<'a> Parser<'a> {
     /// Parses two variants (with the region/type params always optional):
     ///    impl Foo { ... }
     ///    impl ToString for ~[T] { ... }
-    fn parse_item_impl(&mut self) -> ItemInfo {
+    fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
         // First, parse type parameters if necessary.
         let mut generics = self.parse_generics();
 
@@ -4706,7 +4706,7 @@ impl<'a> Parser<'a> {
         let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
 
         (ident,
-         ItemImpl(generics, opt_trait, ty, impl_items),
+         ItemImpl(unsafety, generics, opt_trait, ty, impl_items),
          Some(attrs))
     }
 
@@ -5556,6 +5556,22 @@ impl<'a> Parser<'a> {
                                     maybe_append(attrs, extra_attrs));
             return IoviItem(item);
         }
+        if self.token.is_keyword(keywords::Unsafe) &&
+            self.look_ahead(1u, |t| t.is_keyword(keywords::Impl))
+        {
+            // IMPL ITEM
+            self.expect_keyword(keywords::Unsafe);
+            self.expect_keyword(keywords::Impl);
+            let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe);
+            let last_span = self.last_span;
+            let item = self.mk_item(lo,
+                                    last_span.hi,
+                                    ident,
+                                    item_,
+                                    visibility,
+                                    maybe_append(attrs, extra_attrs));
+            return IoviItem(item);
+        }
         if self.token.is_keyword(keywords::Fn) &&
                 self.look_ahead(1, |f| !Parser::fn_expr_lookahead(f)) {
             // FUNCTION ITEM
@@ -5644,7 +5660,7 @@ impl<'a> Parser<'a> {
         }
         if self.eat_keyword(keywords::Impl) {
             // IMPL ITEM
-            let (ident, item_, extra_attrs) = self.parse_item_impl();
+            let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal);
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 037118b145f..db122f271a9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -917,12 +917,16 @@ impl<'a> State<'a> {
                 try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
             }
 
-            ast::ItemImpl(ref generics,
+            ast::ItemImpl(unsafety,
+                          ref generics,
                           ref opt_trait,
                           ref ty,
                           ref impl_items) => {
-                try!(self.head(visibility_qualified(item.vis,
-                                                    "impl").as_slice()));
+                try!(self.head(""));
+                try!(self.print_visibility(item.vis));
+                try!(self.print_unsafety(unsafety));
+                try!(self.word_nbsp("impl"));
+
                 if generics.is_parameterized() {
                     try!(self.print_generics(generics));
                     try!(space(&mut self.s));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 7bb79a15f45..3535c6e267e 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -282,7 +282,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_generics(type_parameters);
             walk_enum_def(visitor, enum_definition, type_parameters)
         }
-        ItemImpl(ref type_parameters,
+        ItemImpl(_,
+                 ref type_parameters,
                  ref trait_reference,
                  ref typ,
                  ref impl_items) => {
diff --git a/src/test/pretty/trait-safety.rs b/src/test/pretty/trait-safety.rs
index 42e578482e6..b96dbbf3cc9 100644
--- a/src/test/pretty/trait-safety.rs
+++ b/src/test/pretty/trait-safety.rs
@@ -14,6 +14,10 @@ unsafe trait UnsafeTrait {
     fn foo(&self);
 }
 
+unsafe impl UnsafeTrait for int {
+    fn foo(&self) { }
+}
+
 pub unsafe trait PubUnsafeTrait {
     fn foo(&self);
 }
-- 
cgit 1.4.1-3-g733a5


From 7d4e7f079552a524440d8b5fb656d52661592aee Mon Sep 17 00:00:00 2001
From: "Felix S. Klock II" 
Date: Tue, 16 Dec 2014 14:30:30 +0100
Subject: AST refactor: make the place in ExprBox an option.

This is to allow us to migrate away from UnUniq in a followup commit,
and thus unify the code paths related to all forms of `box`.
---
 src/librustc/middle/cfg/construct.rs    |  6 ++----
 src/librustc/middle/expr_use_visitor.rs |  5 ++++-
 src/librustc/middle/liveness.rs         |  3 ++-
 src/librustc/middle/ty.rs               |  3 ++-
 src/librustc_trans/trans/debuginfo.rs   |  3 ++-
 src/librustc_typeck/check/mod.rs        | 27 +++++++++++++++------------
 src/libsyntax/ast.rs                    |  2 +-
 src/libsyntax/fold.rs                   |  2 +-
 src/libsyntax/parse/parser.rs           |  5 ++++-
 src/libsyntax/print/pprust.rs           |  2 +-
 src/libsyntax/visit.rs                  |  2 +-
 11 files changed, 35 insertions(+), 25 deletions(-)

(limited to 'src/libsyntax/parse/parser.rs')

diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 5c39c9fa74d..0e10155beb4 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -462,15 +462,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.straightline(expr, pred, [r, l].iter().map(|&e| &**e))
             }
 
+            ast::ExprBox(Some(ref l), ref r) |
             ast::ExprIndex(ref l, ref r) |
             ast::ExprBinary(_, ref l, ref r) => { // NB: && and || handled earlier
                 self.straightline(expr, pred, [l, r].iter().map(|&e| &**e))
             }
 
-            ast::ExprBox(ref p, ref e) => {
-                self.straightline(expr, pred, [p, e].iter().map(|&e| &**e))
-            }
-
+            ast::ExprBox(None, ref e) |
             ast::ExprAddrOf(_, ref e) |
             ast::ExprCast(ref e, _) |
             ast::ExprUnary(_, ref e) |
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 746a6fc6e70..2cb78beff4c 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -631,7 +631,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             }
 
             ast::ExprBox(ref place, ref base) => {
-                self.consume_expr(&**place);
+                match *place {
+                    Some(ref place) => self.consume_expr(&**place),
+                    None => {}
+                }
                 self.consume_expr(&**base);
             }
 
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 31bcdff9cd5..c76d9bc6b1f 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1199,7 +1199,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
           ast::ExprIndex(ref l, ref r) |
           ast::ExprBinary(_, ref l, ref r) |
-          ast::ExprBox(ref l, ref r) => {
+          ast::ExprBox(Some(ref l), ref r) => {
             let r_succ = self.propagate_through_expr(&**r, succ);
             self.propagate_through_expr(&**l, r_succ)
           }
@@ -1210,6 +1210,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**e1, succ)
           }
 
+          ast::ExprBox(None, ref e) |
           ast::ExprAddrOf(_, ref e) |
           ast::ExprCast(ref e, _) |
           ast::ExprUnary(_, ref e) |
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 50c324c49c3..b5a8f4869e2 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -4320,12 +4320,13 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
 
         ast::ExprLit(_) | // Note: LitStr is carved out above
         ast::ExprUnary(..) |
+        ast::ExprBox(None, _) |
         ast::ExprAddrOf(..) |
         ast::ExprBinary(..) => {
             RvalueDatumExpr
         }
 
-        ast::ExprBox(ref place, _) => {
+        ast::ExprBox(Some(ref place), _) => {
             // Special case `Box` for now:
             let definition = match tcx.def_map.borrow().get(&place.id) {
                 Some(&def) => def,
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index 3f8c951786d..c97e6a09529 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -3472,7 +3472,8 @@ fn populate_scope_map(cx: &CrateContext,
                 walk_expr(cx, &**sub_exp, scope_stack, scope_map),
 
             ast::ExprBox(ref place, ref sub_expr) => {
-                walk_expr(cx, &**place, scope_stack, scope_map);
+                place.as_ref().map(
+                    |e| walk_expr(cx, &**e, scope_stack, scope_map));
                 walk_expr(cx, &**sub_expr, scope_stack, scope_map);
             }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 482284c07dc..4b2e91977fb 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3658,22 +3658,25 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
     let tcx = fcx.ccx.tcx;
     let id = expr.id;
     match expr.node {
-      ast::ExprBox(ref place, ref subexpr) => {
-          check_expr(fcx, &**place);
+      ast::ExprBox(ref opt_place, ref subexpr) => {
+          opt_place.as_ref().map(|place|check_expr(fcx, &**place));
           check_expr(fcx, &**subexpr);
 
           let mut checked = false;
-          if let ast::ExprPath(ref path) = place.node {
-              // FIXME(pcwalton): For now we hardcode the two permissible
-              // places: the exchange heap and the managed heap.
-              let definition = lookup_def(fcx, path.span, place.id);
-              let def_id = definition.def_id();
-              let referent_ty = fcx.expr_ty(&**subexpr);
-              if tcx.lang_items.exchange_heap() == Some(def_id) {
-                  fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
-                  checked = true
+          opt_place.as_ref().map(|place| match place.node {
+              ast::ExprPath(ref path) => {
+                  // FIXME(pcwalton): For now we hardcode the two permissible
+                  // places: the exchange heap and the managed heap.
+                  let definition = lookup_def(fcx, path.span, place.id);
+                  let def_id = definition.def_id();
+                  let referent_ty = fcx.expr_ty(&**subexpr);
+                  if tcx.lang_items.exchange_heap() == Some(def_id) {
+                      fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
+                      checked = true
+                  }
               }
-          }
+              _ => {}
+          });
 
           if !checked {
               span_err!(tcx.sess, expr.span, E0066,
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 206fb26eb55..98d858babb1 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -696,7 +696,7 @@ pub struct Expr {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Expr_ {
     /// First expr is the place; second expr is the value.
-    ExprBox(P, P),
+    ExprBox(Option>, P),
     ExprVec(Vec>),
     ExprCall(P, Vec>),
     ExprMethodCall(SpannedIdent, Vec>, Vec>),
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 8a578c2cb05..7d2acd08d94 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1282,7 +1282,7 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) ->
         id: folder.new_id(id),
         node: match node {
             ExprBox(p, e) => {
-                ExprBox(folder.fold_expr(p), folder.fold_expr(e))
+                ExprBox(p.map(|e|folder.fold_expr(e)), folder.fold_expr(e))
             }
             ExprVec(exprs) => {
                 ExprVec(exprs.move_map(|x| folder.fold_expr(x)))
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index b9ef3fdbd49..6e3cfe5854a 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2888,7 +2888,7 @@ impl<'a> Parser<'a> {
                     }
                     let subexpression = self.parse_prefix_expr();
                     hi = subexpression.span.hi;
-                    ex = ExprBox(place, subexpression);
+                    ex = ExprBox(Some(place), subexpression);
                     return self.mk_expr(lo, hi, ex);
                 }
             }
@@ -2896,6 +2896,9 @@ impl<'a> Parser<'a> {
             // Otherwise, we use the unique pointer default.
             let subexpression = self.parse_prefix_expr();
             hi = subexpression.span.hi;
+            // FIXME (pnkfelix): After working out kinks with box
+            // desugaring, should be `ExprBox(None, subexpression)`
+            // instead.
             ex = self.mk_unary(UnUniq, subexpression);
           }
           _ => return self.parse_dot_or_call_expr()
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index db122f271a9..4f45b69883b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1495,7 +1495,7 @@ impl<'a> State<'a> {
             ast::ExprBox(ref p, ref e) => {
                 try!(word(&mut self.s, "box"));
                 try!(word(&mut self.s, "("));
-                try!(self.print_expr(&**p));
+                try!(p.as_ref().map_or(Ok(()), |e|self.print_expr(&**e)));
                 try!(self.word_space(")"));
                 try!(self.print_expr(&**e));
             }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 3535c6e267e..f5a86bafea1 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -739,7 +739,7 @@ pub fn walk_mac<'v, V: Visitor<'v>>(_: &mut V, _: &'v Mac) {
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
     match expression.node {
         ExprBox(ref place, ref subexpression) => {
-            visitor.visit_expr(&**place);
+            place.as_ref().map(|e|visitor.visit_expr(&**e));
             visitor.visit_expr(&**subexpression)
         }
         ExprVec(ref subexpressions) => {
-- 
cgit 1.4.1-3-g733a5


From ddb2466f6a1bb66f22824334022a4cee61c73bdc Mon Sep 17 00:00:00 2001
From: Patrick Walton 
Date: Fri, 14 Nov 2014 09:18:10 -0800
Subject: librustc: Always parse `macro!()`/`macro![]` as expressions if not
 followed by a semicolon.

This allows code like `vec![1i, 2, 3].len();` to work.

This breaks code that uses macros as statements without putting
semicolons after them, such as:

    fn main() {
        ...
        assert!(a == b)
        assert!(c == d)
        println(...);
    }

It also breaks code that uses macros as items without semicolons:

    local_data_key!(foo)

    fn main() {
        println("hello world")
    }

Add semicolons to fix this code. Those two examples can be fixed as
follows:

    fn main() {
        ...
        assert!(a == b);
        assert!(c == d);
        println(...);
    }

    local_data_key!(foo);

    fn main() {
        println("hello world")
    }

RFC #378.

Closes #18635.

[breaking-change]
---
 src/doc/guide-macros.md                            |  34 +-
 src/etc/regex-match-tests.py                       |   2 +-
 src/libcollections/bit.rs                          |  18 +-
 src/libcollections/enum_set.rs                     |  26 +-
 src/libcollections/macros.rs                       |   5 +-
 src/libcollections/slice.rs                        |   2 +-
 src/libcollections/str.rs                          |   8 +-
 src/libcollections/string.rs                       |   6 +-
 src/libcollections/tree/map.rs                     |  12 +-
 src/libcollections/trie/map.rs                     |   4 +-
 src/libcollections/vec.rs                          |  10 +-
 src/libcollections/vec_map.rs                      |   8 +-
 src/libcore/clone.rs                               |  56 +-
 src/libcore/cmp.rs                                 |  26 +-
 src/libcore/default.rs                             |  35 +-
 src/libcore/fmt/mod.rs                             |  18 +-
 src/libcore/fmt/num.rs                             |  50 +-
 src/libcore/hash/mod.rs                            |  52 +-
 src/libcore/hash/sip.rs                            |  12 +-
 src/libcore/iter.rs                                |  50 +-
 src/libcore/macros.rs                              |  39 +-
 src/libcore/num/float_macros.rs                    |   5 +-
 src/libcore/num/i16.rs                             |   2 +-
 src/libcore/num/i32.rs                             |   2 +-
 src/libcore/num/i64.rs                             |   2 +-
 src/libcore/num/i8.rs                              |   2 +-
 src/libcore/num/int.rs                             |   4 +-
 src/libcore/num/int_macros.rs                      |   5 +-
 src/libcore/num/mod.rs                             | 276 ++++----
 src/libcore/num/u16.rs                             |   2 +-
 src/libcore/num/u32.rs                             |   2 +-
 src/libcore/num/u64.rs                             |   2 +-
 src/libcore/num/u8.rs                              |   2 +-
 src/libcore/num/uint.rs                            |   2 +-
 src/libcore/num/uint_macros.rs                     |   5 +-
 src/libcore/ops.rs                                 | 138 ++--
 src/libcore/ptr.rs                                 |  14 +-
 src/libcore/result.rs                              |   2 +-
 src/libcore/slice.rs                               |  18 +-
 src/libcore/str.rs                                 |  34 +-
 src/libcoretest/iter.rs                            |  20 +-
 src/libcoretest/num/i16.rs                         |   2 +-
 src/libcoretest/num/i32.rs                         |   2 +-
 src/libcoretest/num/i64.rs                         |   2 +-
 src/libcoretest/num/i8.rs                          |   2 +-
 src/libcoretest/num/int.rs                         |   2 +-
 src/libcoretest/num/int_macros.rs                  |   2 +-
 src/libcoretest/num/mod.rs                         |   4 +-
 src/libcoretest/num/u16.rs                         |   2 +-
 src/libcoretest/num/u32.rs                         |   2 +-
 src/libcoretest/num/u64.rs                         |   2 +-
 src/libcoretest/num/u8.rs                          |   2 +-
 src/libcoretest/num/uint.rs                        |   2 +-
 src/libcoretest/num/uint_macros.rs                 |   2 +-
 src/liblog/lib.rs                                  |   8 +-
 src/liblog/macros.rs                               |  25 +-
 src/librand/isaac.rs                               |   2 +-
 src/librand/rand_impls.rs                          |   4 +-
 src/librbml/lib.rs                                 |   4 +-
 src/libregex/parse.rs                              |  26 +-
 src/libregex/test/bench.rs                         |  28 +-
 src/libregex/test/matches.rs                       | 698 ++++++++++-----------
 src/libregex/test/mod.rs                           |   4 +-
 src/libregex/test/tests.rs                         | 224 +++----
 src/librustc/diagnostics.rs                        |   8 +-
 src/librustc/lib.rs                                |   2 +-
 src/librustc/lint/builtin.rs                       | 287 ++++++---
 src/librustc/lint/context.rs                       |  18 +-
 src/librustc/lint/mod.rs                           |  12 +-
 src/librustc/metadata/tyencode.rs                  |   2 +-
 src/librustc/middle/const_eval.rs                  |   2 +-
 src/librustc/middle/expr_use_visitor.rs            |   4 +-
 src/librustc/middle/infer/error_reporting.rs       |   6 +-
 src/librustc/middle/mem_categorization.rs          |   4 +-
 src/librustc/middle/ty.rs                          |  16 +-
 src/librustc/middle/weak_lang_items.rs             |   9 +-
 src/librustc/session/config.rs                     |  18 +-
 src/librustc_back/sha2.rs                          |   6 +-
 src/librustc_back/svh.rs                           |   9 +-
 src/librustc_back/target/mod.rs                    |   6 +-
 src/librustc_borrowck/borrowck/mod.rs              |   4 +-
 src/librustc_llvm/lib.rs                           |   2 +-
 src/librustc_trans/trans/_match.rs                 |   4 +-
 src/librustc_trans/trans/adt.rs                    |   2 +-
 src/librustc_trans/trans/base.rs                   |   8 +-
 src/librustc_trans/trans/context.rs                |   6 +-
 src/librustc_trans/trans/datum.rs                  |   2 +-
 src/librustc_trans/trans/debuginfo.rs              |   4 +-
 src/librustc_trans/trans/macros.rs                 |   8 +-
 src/librustc_trans/trans/type_.rs                  |   4 +-
 src/librustc_trans/trans/value.rs                  |   4 +-
 src/librustc_typeck/check/regionck.rs              |   4 +-
 src/librustc_typeck/diagnostics.rs                 |  10 +-
 src/librustdoc/html/format.rs                      |   2 +-
 src/librustdoc/html/markdown.rs                    |   6 +-
 src/librustdoc/html/render.rs                      |   4 +-
 src/librustdoc/lib.rs                              |   2 +-
 src/librustrt/macros.rs                            |  16 +-
 src/libserialize/base64.rs                         |   2 +-
 src/libserialize/json.rs                           |  42 +-
 src/libserialize/serialize.rs                      |  10 +-
 src/libstd/ascii.rs                                |  16 +-
 src/libstd/collections/hash/map.rs                 |   2 +-
 src/libstd/comm/mod.rs                             | 376 +++++------
 src/libstd/comm/select.rs                          | 160 ++---
 src/libstd/failure.rs                              |   8 +-
 src/libstd/io/extensions.rs                        |   4 +-
 src/libstd/io/fs.rs                                |   8 +-
 src/libstd/io/net/ip.rs                            |   4 +-
 src/libstd/io/stdio.rs                             |   8 +-
 src/libstd/macros.rs                               |  92 +--
 src/libstd/num/f32.rs                              |   4 +-
 src/libstd/num/f64.rs                              |   4 +-
 src/libstd/num/float_macros.rs                     |   4 +-
 src/libstd/num/i16.rs                              |   2 +-
 src/libstd/num/i32.rs                              |   2 +-
 src/libstd/num/i64.rs                              |   2 +-
 src/libstd/num/i8.rs                               |   2 +-
 src/libstd/num/int.rs                              |   2 +-
 src/libstd/num/int_macros.rs                       |   4 +-
 src/libstd/num/mod.rs                              |  36 +-
 src/libstd/num/u16.rs                              |   2 +-
 src/libstd/num/u32.rs                              |   2 +-
 src/libstd/num/u64.rs                              |   2 +-
 src/libstd/num/u8.rs                               |   2 +-
 src/libstd/num/uint.rs                             |   2 +-
 src/libstd/num/uint_macros.rs                      |   4 +-
 src/libstd/path/posix.rs                           |  42 +-
 src/libstd/path/windows.rs                         |  42 +-
 src/libstd/rand/mod.rs                             |   2 +-
 src/libstd/rt/backtrace.rs                         |  15 +-
 src/libstd/sys/unix/mod.rs                         |   4 +-
 src/libstd/sys/unix/process.rs                     |   2 +-
 src/libstd/sys/unix/timer.rs                       |   2 +-
 src/libstd/sys/windows/c.rs                        |  12 +-
 src/libstd/sys/windows/mod.rs                      |   4 +-
 src/libstd/sys/windows/timer.rs                    |   2 +-
 src/libstd/thread_local/mod.rs                     |  32 +-
 src/libstd/thread_local/scoped.rs                  |  18 +-
 src/libstd/time/duration.rs                        |   4 +-
 src/libsyntax/ast.rs                               |  17 +-
 src/libsyntax/ast_util.rs                          |  24 +-
 src/libsyntax/attr.rs                              |   4 +-
 src/libsyntax/codemap.rs                           |   2 +-
 src/libsyntax/diagnostics/macros.rs                |  31 +-
 src/libsyntax/diagnostics/plugin.rs                |  16 +-
 src/libsyntax/ext/expand.rs                        |  63 +-
 src/libsyntax/ext/mtwt.rs                          |   4 +-
 src/libsyntax/ext/quote.rs                         | 122 ++--
 src/libsyntax/fold.rs                              |   6 +-
 src/libsyntax/parse/parser.rs                      | 151 +++--
 src/libsyntax/parse/token.rs                       |   2 +-
 src/libsyntax/print/pprust.rs                      |  42 +-
 src/libterm/terminfo/parser/compiled.rs            |   2 +-
 src/libtest/stats.rs                               |   4 +-
 src/test/auxiliary/lint_group_plugin_test.rs       |   6 +-
 src/test/auxiliary/lint_plugin_test.rs             |   3 +-
 src/test/auxiliary/lint_stability.rs               |   6 +-
 src/test/auxiliary/macro_crate_def_only.rs         |   2 +-
 src/test/auxiliary/macro_crate_test.rs             |   4 +-
 src/test/auxiliary/macro_export_inner_module.rs    |   2 +-
 src/test/bench/core-std.rs                         |   2 +-
 .../compile-fail/const-block-non-item-statement.rs |   2 +-
 src/test/compile-fail/gated-macro-rules.rs         |   2 +-
 src/test/compile-fail/infinite-macro-expansion.rs  |   2 +-
 src/test/compile-fail/issue-19734.rs               |   2 +-
 src/test/compile-fail/issue-6596.rs                |   2 +-
 .../compile-fail/liveness-return-last-stmt-semi.rs |   2 +-
 src/test/compile-fail/macro-incomplete-parse.rs    |   4 +-
 src/test/compile-fail/macro-inner-attributes.rs    |   6 +-
 src/test/compile-fail/macro-invocation-dot-help.rs |  14 -
 src/test/compile-fail/macro-local-data-key-priv.rs |   2 +-
 src/test/compile-fail/macro-match-nonterminal.rs   |   2 +-
 src/test/compile-fail/macro-outer-attributes.rs    |   6 +-
 src/test/compile-fail/macros-no-semicolon-items.rs |  15 +
 src/test/compile-fail/macros-no-semicolon.rs       |  16 +
 src/test/compile-fail/method-macro-backtrace.rs    |  18 +-
 src/test/compile-fail/pattern-macro-hygeine.rs     |  18 -
 src/test/compile-fail/pattern-macro-hygiene.rs     |  18 +
 src/test/compile-fail/recursion_limit.rs           |  26 +-
 src/test/debuginfo/lexical-scope-with-macro.rs     |  20 +-
 .../issue_16723_multiple_items_syntax_ext.rs       |   2 +-
 src/test/run-pass/cleanup-rvalue-scopes.rs         |   4 +-
 src/test/run-pass/const-binops.rs                  |   2 +-
 src/test/run-pass/core-run-destroy.rs              |   2 +-
 src/test/run-pass/deriving-in-macro.rs             |   4 +-
 src/test/run-pass/exponential-notation.rs          |  12 +-
 src/test/run-pass/html-literals.rs                 |   4 +-
 src/test/run-pass/ifmt.rs                          |   2 +-
 src/test/run-pass/intrinsics-math.rs               |   2 +-
 src/test/run-pass/issue-15189.rs                   |   2 +-
 src/test/run-pass/issue-15221.rs                   |   4 +-
 src/test/run-pass/issue-5060.rs                    |   2 +-
 src/test/run-pass/issue-7911.rs                    |   4 +-
 src/test/run-pass/issue-8709.rs                    |   8 +-
 src/test/run-pass/issue-8851.rs                    |   4 +-
 src/test/run-pass/issue-9110.rs                    |   4 +-
 src/test/run-pass/issue-9129.rs                    |   2 +-
 src/test/run-pass/let-var-hygiene.rs               |   2 +-
 .../log_syntax-trace_macros-macro-locations.rs     |   4 +-
 src/test/run-pass/macro-2.rs                       |   4 +-
 src/test/run-pass/macro-attribute-expansion.rs     |   4 +-
 src/test/run-pass/macro-attributes.rs              |   2 +-
 src/test/run-pass/macro-delimiter-significance.rs  |  14 +
 src/test/run-pass/macro-include-items.rs           |   2 +-
 src/test/run-pass/macro-interpolation.rs           |   3 +-
 ...ro-invocation-in-count-expr-fixed-array-type.rs |   3 +-
 src/test/run-pass/macro-meta-items.rs              |   4 +-
 src/test/run-pass/macro-method-issue-4621.rs       |   2 +-
 src/test/run-pass/macro-multiple-items.rs          |   4 +-
 src/test/run-pass/macro-nt-list.rs                 |   4 +-
 src/test/run-pass/macro-of-higher-order.rs         |   4 +-
 src/test/run-pass/macro-pat.rs                     |  10 +-
 src/test/run-pass/macro-stmt.rs                    |   6 +-
 src/test/run-pass/macro-with-attrs1.rs             |   4 +-
 src/test/run-pass/macro-with-attrs2.rs             |   4 +-
 .../run-pass/macro-with-braces-in-expr-position.rs |   2 +-
 src/test/run-pass/match-in-macro.rs                |   2 +-
 src/test/run-pass/non-built-in-quote.rs            |   2 +-
 src/test/run-pass/overloaded-index-assoc-list.rs   |   8 +-
 src/test/run-pass/slice-2.rs                       |  32 +-
 src/test/run-pass/syntax-extension-source-utils.rs |   2 +-
 .../typeck-macro-interaction-issue-8852.rs         |   4 +-
 src/test/run-pass/vec-macro-with-brackets.rs       |   2 +-
 224 files changed, 2367 insertions(+), 2076 deletions(-)
 delete mode 100644 src/test/compile-fail/macro-invocation-dot-help.rs
 create mode 100644 src/test/compile-fail/macros-no-semicolon-items.rs
 create mode 100644 src/test/compile-fail/macros-no-semicolon.rs
 delete mode 100644 src/test/compile-fail/pattern-macro-hygeine.rs
 create mode 100644 src/test/compile-fail/pattern-macro-hygiene.rs
 create mode 100644 src/test/run-pass/macro-delimiter-significance.rs

(limited to 'src/libsyntax/parse/parser.rs')

diff --git a/src/doc/guide-macros.md b/src/doc/guide-macros.md
index a7f4d103aca..58af5917407 100644
--- a/src/doc/guide-macros.md
+++ b/src/doc/guide-macros.md
@@ -58,7 +58,7 @@ macro_rules! early_return(
             _ => {}
         }
     );
-)
+);
 // ...
 early_return!(input_1 T::SpecialA);
 // ...
@@ -179,8 +179,8 @@ macro_rules! early_return(
             )+
             _ => {}
         }
-    );
-)
+    )
+);
 // ...
 early_return!(input_1, [T::SpecialA|T::SpecialC|T::SpecialD]);
 // ...
@@ -275,17 +275,17 @@ macro_rules! biased_match (
             _ => { $err }
         };
     )
-)
+);
 
 # enum T1 { Good1(T2, uint), Bad1}
 # struct T2 { body: T3 }
 # enum T3 { Good2(uint), Bad2}
 # fn f(x: T1) -> uint {
 biased_match!((x)       ~ (T1::Good1(g1, val)) else { return 0 };
-              binds g1, val )
+              binds g1, val );
 biased_match!((g1.body) ~ (T3::Good2(result) )
                   else { panic!("Didn't get good_2") };
-              binds result )
+              binds result );
 // complicated stuff goes here
 return result + val;
 # }
@@ -303,7 +303,7 @@ pattern we want is clear:
     ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
       binds $( $bind_res:ident ),*
     )
-# => (0))
+# => (0));
 ~~~~
 
 However, it's not possible to directly expand to nested match statements. But
@@ -323,7 +323,7 @@ input patterns:
 # #![feature(macro_rules)]
 # macro_rules! b(
     ( binds $( $bind_res:ident ),* )
-# => (0))
+# => (0));
 # fn main() {}
 ~~~~
 
@@ -337,7 +337,7 @@ input patterns:
       $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
       binds  $( $bind_res:ident ),*
     )
-# => (0))
+# => (0));
 ~~~~
 
 The resulting macro looks like this. Note that the separation into
@@ -366,7 +366,7 @@ macro_rules! biased_match_rec (
     );
     // Produce the requested values
     ( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
-)
+);
 
 // Wrap the whole thing in a `let`.
 macro_rules! biased_match (
@@ -388,7 +388,7 @@ macro_rules! biased_match (
             binds $( $bind_res ),*
         );
     )
-)
+);
 
 
 # enum T1 { Good1(T2, uint), Bad1}
@@ -398,7 +398,7 @@ macro_rules! biased_match (
 biased_match!(
     (x)       ~ (T1::Good1(g1, val)) else { return 0 };
     (g1.body) ~ (T3::Good2(result) ) else { panic!("Didn't get Good2") };
-    binds val, result )
+    binds val, result );
 // complicated stuff goes here
 return result + val;
 # }
@@ -444,7 +444,7 @@ macro_rules! loop_x (
             $e
         }
     );
-)
+);
 
 fn main() {
     'x: loop {
@@ -482,7 +482,7 @@ An example:
 
 ```rust
 # #![feature(macro_rules)]
-macro_rules! m1 (() => (()))
+macro_rules! m1 (() => (()));
 
 // visible here: m1
 
@@ -490,14 +490,14 @@ mod foo {
     // visible here: m1
 
     #[macro_export]
-    macro_rules! m2 (() => (()))
+    macro_rules! m2 (() => (()));
 
     // visible here: m1, m2
 }
 
 // visible here: m1
 
-macro_rules! m3 (() => (()))
+macro_rules! m3 (() => (()));
 
 // visible here: m1, m3
 
@@ -505,7 +505,7 @@ macro_rules! m3 (() => (()))
 mod bar {
     // visible here: m1, m3
 
-    macro_rules! m4 (() => (()))
+    macro_rules! m4 (() => (()));
 
     // visible here: m1, m3, m4
 }
diff --git a/src/etc/regex-match-tests.py b/src/etc/regex-match-tests.py
index 826af961fce..ea7f51c86f8 100755
--- a/src/etc/regex-match-tests.py
+++ b/src/etc/regex-match-tests.py
@@ -63,7 +63,7 @@ def read_tests(f):
 def test_tostr(t):
     lineno, pat, text, groups = t
     options = map(group_tostr, groups)
-    return 'mat!(match_%s, r"%s", r"%s", %s)' \
+    return 'mat!{match_%s, r"%s", r"%s", %s}' \
            % (lineno, pat, '' if text == "NULL" else text, ', '.join(options))
 
 
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index df860d6000e..7f78d56607e 100644
--- a/src/libcollections/bit.rs
+++ b/src/libcollections/bit.rs
@@ -2083,7 +2083,7 @@ mod tests {
         let bools = vec![true, false, true, true];
         let bitv: Bitv = bools.iter().map(|n| *n).collect();
 
-        assert_eq!(bitv.iter().collect::>(), bools)
+        assert_eq!(bitv.iter().collect::>(), bools);
 
         let long = Vec::from_fn(10000, |i| i % 2 == 0);
         let bitv: Bitv = long.iter().map(|n| *n).collect();
@@ -2112,8 +2112,8 @@ mod tests {
         for &b in bools.iter() {
             for &l in lengths.iter() {
                 let bitset = BitvSet::from_bitv(Bitv::with_capacity(l, b));
-                assert_eq!(bitset.contains(&1u), b)
-                assert_eq!(bitset.contains(&(l-1u)), b)
+                assert_eq!(bitset.contains(&1u), b);
+                assert_eq!(bitset.contains(&(l-1u)), b);
                 assert!(!bitset.contains(&l))
             }
         }
@@ -2321,12 +2321,12 @@ mod tests {
         assert!(!a.is_disjoint(&d));
         assert!(!d.is_disjoint(&a));
 
-        assert!(a.is_disjoint(&b))
-        assert!(a.is_disjoint(&c))
-        assert!(b.is_disjoint(&a))
-        assert!(b.is_disjoint(&c))
-        assert!(c.is_disjoint(&a))
-        assert!(c.is_disjoint(&b))
+        assert!(a.is_disjoint(&b));
+        assert!(a.is_disjoint(&c));
+        assert!(b.is_disjoint(&a));
+        assert!(b.is_disjoint(&c));
+        assert!(c.is_disjoint(&a));
+        assert!(c.is_disjoint(&b));
     }
 
     #[test]
diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs
index 4df1be1bb35..49b66ce25f5 100644
--- a/src/libcollections/enum_set.rs
+++ b/src/libcollections/enum_set.rs
@@ -411,7 +411,7 @@ mod test {
 
         assert!(e1.is_subset(&e2));
         assert!(e2.is_superset(&e1));
-        assert!(!e3.is_superset(&e2))
+        assert!(!e3.is_superset(&e2));
         assert!(!e2.is_superset(&e3))
     }
 
@@ -438,23 +438,23 @@ mod test {
         let mut e1: EnumSet = EnumSet::new();
 
         let elems: ::vec::Vec = e1.iter().collect();
-        assert!(elems.is_empty())
+        assert!(elems.is_empty());
 
         e1.insert(A);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A], elems)
+        assert_eq!(vec![A], elems);
 
         e1.insert(C);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,C], elems)
+        assert_eq!(vec![A,C], elems);
 
         e1.insert(C);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,C], elems)
+        assert_eq!(vec![A,C], elems);
 
         e1.insert(B);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,B,C], elems)
+        assert_eq!(vec![A,B,C], elems);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -472,35 +472,35 @@ mod test {
 
         let e_union = e1 | e2;
         let elems: ::vec::Vec<_> = e_union.iter().collect();
-        assert_eq!(vec![A,B,C], elems)
+        assert_eq!(vec![A,B,C], elems);
 
         let e_intersection = e1 & e2;
         let elems: ::vec::Vec<_> = e_intersection.iter().collect();
-        assert_eq!(vec![C], elems)
+        assert_eq!(vec![C], elems);
 
         // Another way to express intersection
         let e_intersection = e1 - (e1 - e2);
         let elems: ::vec::Vec<_> = e_intersection.iter().collect();
-        assert_eq!(vec![C], elems)
+        assert_eq!(vec![C], elems);
 
         let e_subtract = e1 - e2;
         let elems: ::vec::Vec<_> = e_subtract.iter().collect();
-        assert_eq!(vec![A], elems)
+        assert_eq!(vec![A], elems);
 
         // Bitwise XOR of two sets, aka symmetric difference
         let e_symmetric_diff = e1 ^ e2;
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems)
+        assert_eq!(vec![A,B], elems);
 
         // Another way to express symmetric difference
         let e_symmetric_diff = (e1 - e2) | (e2 - e1);
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems)
+        assert_eq!(vec![A,B], elems);
 
         // Yet another way to express symmetric difference
         let e_symmetric_diff = (e1 | e2) - (e1 & e2);
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems)
+        assert_eq!(vec![A,B], elems);
     }
 
     #[test]
diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs
index ba8b3b8c7d3..ce4b1e46773 100644
--- a/src/libcollections/macros.rs
+++ b/src/libcollections/macros.rs
@@ -11,7 +11,7 @@
 #![macro_escape]
 
 /// Creates a `std::vec::Vec` containing the arguments.
-macro_rules! vec(
+macro_rules! vec {
     ($($e:expr),*) => ({
         // leading _ to allow empty construction without a warning.
         let mut _temp = ::vec::Vec::new();
@@ -19,4 +19,5 @@ macro_rules! vec(
         _temp
     });
     ($($e:expr),+,) => (vec!($($e),+))
-)
+}
+
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 1ec3f1033e1..bba00a80f68 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -2515,7 +2515,7 @@ mod tests {
                 assert_eq!(format!("{}", x), x_str);
                 assert_eq!(format!("{}", x.as_slice()), x_str);
             })
-        )
+        );
         let empty: Vec = vec![];
         test_show_vec!(empty, "[]");
         test_show_vec!(vec![1i], "[1]");
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 19ca1c9fd2b..9ac5f04efe5 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -415,14 +415,14 @@ Section: Misc
 // Return the initial codepoint accumulator for the first byte.
 // The first byte is special, only want bottom 5 bits for width 2, 4 bits
 // for width 3, and 3 bits for width 4
-macro_rules! utf8_first_byte(
+macro_rules! utf8_first_byte {
     ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
-)
+}
 
 // return the value of $ch updated with continuation byte $byte
-macro_rules! utf8_acc_cont_byte(
+macro_rules! utf8_acc_cont_byte {
     ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32)
-)
+}
 
 /*
 Section: MaybeOwned
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index ba89fc133c4..38ebd686ddb 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -167,7 +167,7 @@ impl String {
                     subseqidx = i;
                     res.as_mut_vec().push_all(REPLACEMENT);
                 }
-            }))
+            }));
 
             if byte < 128u8 {
                 // subseqidx handles this
@@ -788,8 +788,8 @@ macro_rules! impl_eq {
     }
 }
 
-impl_eq!(String, &'a str)
-impl_eq!(CowString<'a>, String)
+impl_eq! { String, &'a str }
+impl_eq! { CowString<'a>, String }
 
 impl<'a, 'b> PartialEq<&'b str> for CowString<'a> {
     #[inline]
diff --git a/src/libcollections/tree/map.rs b/src/libcollections/tree/map.rs
index 2b14f9569b0..cc667285d29 100644
--- a/src/libcollections/tree/map.rs
+++ b/src/libcollections/tree/map.rs
@@ -900,7 +900,7 @@ macro_rules! define_iterator {
      ) => {
         // private methods on the forward iterator (item!() for the
         // addr_mut in the next_ return value)
-        item!(impl<'a, K, V> $name<'a, K, V> {
+        item! { impl<'a, K, V> $name<'a, K, V> {
             #[inline(always)]
             fn next_(&mut self, forward: bool) -> Option<(&'a K, &'a $($addr_mut)* V)> {
                 while !self.stack.is_empty() || !self.node.is_null() {
@@ -968,10 +968,10 @@ macro_rules! define_iterator {
                     self.node = ptr::RawPtr::null();
                 }
             }
-        })
+        } }
 
         // the forward Iterator impl.
-        item!(impl<'a, K, V> Iterator<(&'a K, &'a $($addr_mut)* V)> for $name<'a, K, V> {
+        item! { impl<'a, K, V> Iterator<(&'a K, &'a $($addr_mut)* V)> for $name<'a, K, V> {
             /// Advances the iterator to the next node (in order) and return a
             /// tuple with a reference to the key and value. If there are no
             /// more nodes, return `None`.
@@ -983,10 +983,10 @@ macro_rules! define_iterator {
             fn size_hint(&self) -> (uint, Option) {
                 (self.remaining_min, Some(self.remaining_max))
             }
-        })
+        } }
 
         // the reverse Iterator impl.
-        item!(impl<'a, K, V> Iterator<(&'a K, &'a $($addr_mut)* V)> for $rev_name<'a, K, V> {
+        item! { impl<'a, K, V> Iterator<(&'a K, &'a $($addr_mut)* V)> for $rev_name<'a, K, V> {
             fn next(&mut self) -> Option<(&'a K, &'a $($addr_mut)* V)> {
                 self.iter.next_(false)
             }
@@ -995,7 +995,7 @@ macro_rules! define_iterator {
             fn size_hint(&self) -> (uint, Option) {
                 self.iter.size_hint()
             }
-        })
+        } }
     }
 } // end of define_iterator
 
diff --git a/src/libcollections/trie/map.rs b/src/libcollections/trie/map.rs
index 67c5407eb6e..9a9ac6a3c58 100644
--- a/src/libcollections/trie/map.rs
+++ b/src/libcollections/trie/map.rs
@@ -1141,7 +1141,7 @@ macro_rules! iterator_impl {
             }
         }
 
-        item!(impl<'a, T> Iterator<(uint, &'a $($mut_)* T)> for $name<'a, T> {
+        item! { impl<'a, T> Iterator<(uint, &'a $($mut_)* T)> for $name<'a, T> {
                 // you might wonder why we're not even trying to act within the
                 // rules, and are just manipulating raw pointers like there's no
                 // such thing as invalid pointers and memory unsafety. The
@@ -1213,7 +1213,7 @@ macro_rules! iterator_impl {
                 fn size_hint(&self) -> (uint, Option) {
                     (self.remaining_min, Some(self.remaining_max))
                 }
-            })
+            } }
     }
 }
 
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 75a389a7c95..94e6103f05f 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -582,8 +582,8 @@ macro_rules! impl_eq {
     }
 }
 
-impl_eq!(Vec, &'b [B])
-impl_eq!(Vec, &'b mut [B])
+impl_eq! { Vec, &'b [B] }
+impl_eq! { Vec, &'b mut [B] }
 
 impl<'a, A, B> PartialEq> for CowVec<'a, A> where A: PartialEq + Clone {
     #[inline]
@@ -617,8 +617,8 @@ macro_rules! impl_eq_for_cowvec {
     }
 }
 
-impl_eq_for_cowvec!(&'b [B])
-impl_eq_for_cowvec!(&'b mut [B])
+impl_eq_for_cowvec! { &'b [B] }
+impl_eq_for_cowvec! { &'b mut [B] }
 
 #[unstable = "waiting on PartialOrd stability"]
 impl PartialOrd for Vec {
@@ -2065,7 +2065,7 @@ mod tests {
 
     #[test]
     fn test_partitioned() {
-        assert_eq!(vec![].partitioned(|x: &int| *x < 3), (vec![], vec![]))
+        assert_eq!(vec![].partitioned(|x: &int| *x < 3), (vec![], vec![]));
         assert_eq!(vec![1i, 2, 3].partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
         assert_eq!(vec![1i, 2, 3].partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
         assert_eq!(vec![1i, 2, 3].partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs
index 9f1a0075352..8faa9c1c522 100644
--- a/src/libcollections/vec_map.rs
+++ b/src/libcollections/vec_map.rs
@@ -612,8 +612,8 @@ pub struct Entries<'a, V:'a> {
     iter: slice::Items<'a, Option>
 }
 
-iterator!(impl Entries -> (uint, &'a V), as_ref)
-double_ended_iterator!(impl Entries -> (uint, &'a V), as_ref)
+iterator! { impl Entries -> (uint, &'a V), as_ref }
+double_ended_iterator! { impl Entries -> (uint, &'a V), as_ref }
 
 /// An iterator over the key-value pairs of a map, with the
 /// values being mutable.
@@ -623,8 +623,8 @@ pub struct MutEntries<'a, V:'a> {
     iter: slice::MutItems<'a, Option>
 }
 
-iterator!(impl MutEntries -> (uint, &'a mut V), as_mut)
-double_ended_iterator!(impl MutEntries -> (uint, &'a mut V), as_mut)
+iterator! { impl MutEntries -> (uint, &'a mut V), as_mut }
+double_ended_iterator! { impl MutEntries -> (uint, &'a mut V), as_mut }
 
 /// An iterator over the keys of a map.
 pub struct Keys<'a, V: 'a> {
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 9f928f57e9e..f6be422813a 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -46,7 +46,7 @@ impl<'a, Sized? T> Clone for &'a T {
     fn clone(&self) -> &'a T { *self }
 }
 
-macro_rules! clone_impl(
+macro_rules! clone_impl {
     ($t:ty) => {
         impl Clone for $t {
             /// Return a deep copy of the value.
@@ -54,28 +54,28 @@ macro_rules! clone_impl(
             fn clone(&self) -> $t { *self }
         }
     }
-)
+}
 
-clone_impl!(int)
-clone_impl!(i8)
-clone_impl!(i16)
-clone_impl!(i32)
-clone_impl!(i64)
+clone_impl! { int }
+clone_impl! { i8 }
+clone_impl! { i16 }
+clone_impl! { i32 }
+clone_impl! { i64 }
 
-clone_impl!(uint)
-clone_impl!(u8)
-clone_impl!(u16)
-clone_impl!(u32)
-clone_impl!(u64)
+clone_impl! { uint }
+clone_impl! { u8 }
+clone_impl! { u16 }
+clone_impl! { u32 }
+clone_impl! { u64 }
 
-clone_impl!(f32)
-clone_impl!(f64)
+clone_impl! { f32 }
+clone_impl! { f64 }
 
-clone_impl!(())
-clone_impl!(bool)
-clone_impl!(char)
+clone_impl! { () }
+clone_impl! { bool }
+clone_impl! { char }
 
-macro_rules! extern_fn_clone(
+macro_rules! extern_fn_clone {
     ($($A:ident),*) => (
         #[experimental = "this may not be sufficient for fns with region parameters"]
         impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType {
@@ -84,15 +84,15 @@ macro_rules! extern_fn_clone(
             fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
         }
     )
-)
+}
 
-extern_fn_clone!()
-extern_fn_clone!(A)
-extern_fn_clone!(A, B)
-extern_fn_clone!(A, B, C)
-extern_fn_clone!(A, B, C, D)
-extern_fn_clone!(A, B, C, D, E)
-extern_fn_clone!(A, B, C, D, E, F)
-extern_fn_clone!(A, B, C, D, E, F, G)
-extern_fn_clone!(A, B, C, D, E, F, G, H)
+extern_fn_clone! {}
+extern_fn_clone! { A }
+extern_fn_clone! { A, B }
+extern_fn_clone! { A, B, C }
+extern_fn_clone! { A, B, C, D }
+extern_fn_clone! { A, B, C, D, E }
+extern_fn_clone! { A, B, C, D, E, F }
+extern_fn_clone! { A, B, C, D, E, F, G }
+extern_fn_clone! { A, B, C, D, E, F, G, H }
 
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 4235531c199..af82e6a00f3 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -296,7 +296,7 @@ mod impls {
     use option::Option;
     use option::Option::{Some, None};
 
-    macro_rules! partial_eq_impl(
+    macro_rules! partial_eq_impl {
         ($($t:ty)*) => ($(
             #[unstable = "Trait is unstable."]
             impl PartialEq for $t {
@@ -306,7 +306,7 @@ mod impls {
                 fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
             }
         )*)
-    )
+    }
 
     #[unstable = "Trait is unstable."]
     impl PartialEq for () {
@@ -316,18 +316,20 @@ mod impls {
         fn ne(&self, _other: &()) -> bool { false }
     }
 
-    partial_eq_impl!(bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+    partial_eq_impl! {
+        bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64
+    }
 
-    macro_rules! eq_impl(
+    macro_rules! eq_impl {
         ($($t:ty)*) => ($(
             #[unstable = "Trait is unstable."]
             impl Eq for $t {}
         )*)
-    )
+    }
 
-    eq_impl!(() bool char uint u8 u16 u32 u64 int i8 i16 i32 i64)
+    eq_impl! { () bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
-    macro_rules! partial_ord_impl(
+    macro_rules! partial_ord_impl {
         ($($t:ty)*) => ($(
             #[unstable = "Trait is unstable."]
             impl PartialOrd for $t {
@@ -350,7 +352,7 @@ mod impls {
                 fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
             }
         )*)
-    )
+    }
 
     #[unstable = "Trait is unstable."]
     impl PartialOrd for () {
@@ -368,9 +370,9 @@ mod impls {
         }
     }
 
-    partial_ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+    partial_ord_impl! { char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 
-    macro_rules! ord_impl(
+    macro_rules! ord_impl {
         ($($t:ty)*) => ($(
             #[unstable = "Trait is unstable."]
             impl Ord for $t {
@@ -382,7 +384,7 @@ mod impls {
                 }
             }
         )*)
-    )
+    }
 
     #[unstable = "Trait is unstable."]
     impl Ord for () {
@@ -398,7 +400,7 @@ mod impls {
         }
     }
 
-    ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64)
+    ord_impl! { char uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
     // & pointers
 
diff --git a/src/libcore/default.rs b/src/libcore/default.rs
index 10facfe4750..0632ffd9c69 100644
--- a/src/libcore/default.rs
+++ b/src/libcore/default.rs
@@ -135,7 +135,7 @@ pub trait Default {
     fn default() -> Self;
 }
 
-macro_rules! default_impl(
+macro_rules! default_impl {
     ($t:ty, $v:expr) => {
         #[stable]
         impl Default for $t {
@@ -144,23 +144,24 @@ macro_rules! default_impl(
             fn default() -> $t { $v }
         }
     }
-)
+}
+
+default_impl! { (), () }
+default_impl! { bool, false }
+default_impl! { char, '\x00' }
 
-default_impl!((), ())
-default_impl!(bool, false)
-default_impl!(char, '\x00')
+default_impl! { uint, 0u }
+default_impl! { u8,  0u8 }
+default_impl! { u16, 0u16 }
+default_impl! { u32, 0u32 }
+default_impl! { u64, 0u64 }
 
-default_impl!(uint, 0u)
-default_impl!(u8,  0u8)
-default_impl!(u16, 0u16)
-default_impl!(u32, 0u32)
-default_impl!(u64, 0u64)
+default_impl! { int, 0i }
+default_impl! { i8,  0i8 }
+default_impl! { i16, 0i16 }
+default_impl! { i32, 0i32 }
+default_impl! { i64, 0i64 }
 
-default_impl!(int, 0i)
-default_impl!(i8,  0i8)
-default_impl!(i16, 0i16)
-default_impl!(i32, 0i32)
-default_impl!(i64, 0i64)
+default_impl! { f32, 0.0f32 }
+default_impl! { f64, 0.0f64 }
 
-default_impl!(f32, 0.0f32)
-default_impl!(f64, 0.0f64)
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 6ece6264d8c..cc940cd9e20 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -639,7 +639,7 @@ impl<'a, T> Pointer for &'a mut T {
     }
 }
 
-macro_rules! floating(($ty:ident) => {
+macro_rules! floating { ($ty:ident) => {
     impl Show for $ty {
         fn fmt(&self, fmt: &mut Formatter) -> Result {
             use num::Float;
@@ -702,9 +702,9 @@ macro_rules! floating(($ty:ident) => {
             })
         }
     }
-})
-floating!(f32)
-floating!(f64)
+} }
+floating! { f32 }
+floating! { f64 }
 
 // Implementation of Show for various core types
 
@@ -716,9 +716,11 @@ impl Show for *mut T {
     fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
 }
 
-macro_rules! peel(($name:ident, $($other:ident,)*) => (tuple!($($other,)*)))
+macro_rules! peel {
+    ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })
+}
 
-macro_rules! tuple (
+macro_rules! tuple {
     () => ();
     ( $($name:ident,)+ ) => (
         impl<$($name:Show),*> Show for ($($name,)*) {
@@ -740,9 +742,9 @@ macro_rules! tuple (
                 write!(f, ")")
             }
         }
-        peel!($($name,)*)
+        peel! { $($name,)* }
     )
-)
+}
 
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index 9cfa7bec22f..13cfcacf8da 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -100,13 +100,13 @@ macro_rules! radix {
     }
 }
 
-radix!(Binary,    2, "0b", x @  0 ...  2 => b'0' + x)
-radix!(Octal,     8, "0o", x @  0 ...  7 => b'0' + x)
-radix!(Decimal,  10, "",   x @  0 ...  9 => b'0' + x)
-radix!(LowerHex, 16, "0x", x @  0 ...  9 => b'0' + x,
-                           x @ 10 ... 15 => b'a' + (x - 10))
-radix!(UpperHex, 16, "0x", x @  0 ...  9 => b'0' + x,
-                           x @ 10 ... 15 => b'A' + (x - 10))
+radix! { Binary,    2, "0b", x @  0 ...  2 => b'0' + x }
+radix! { Octal,     8, "0o", x @  0 ...  7 => b'0' + x }
+radix! { Decimal,  10, "",   x @  0 ...  9 => b'0' + x }
+radix! { LowerHex, 16, "0x", x @  0 ...  9 => b'0' + x,
+                             x @ 10 ... 15 => b'a' + (x - 10) }
+radix! { UpperHex, 16, "0x", x @  0 ...  9 => b'0' + x,
+                             x @ 10 ... 15 => b'A' + (x - 10) }
 
 /// A radix with in the range of `2..36`.
 #[deriving(Clone, PartialEq)]
@@ -174,23 +174,23 @@ macro_rules! int_base {
 }
 macro_rules! integer {
     ($Int:ident, $Uint:ident) => {
-        int_base!(Show     for $Int as $Int   -> Decimal)
-        int_base!(Binary   for $Int as $Uint  -> Binary)
-        int_base!(Octal    for $Int as $Uint  -> Octal)
-        int_base!(LowerHex for $Int as $Uint  -> LowerHex)
-        int_base!(UpperHex for $Int as $Uint  -> UpperHex)
-        radix_fmt!($Int as $Int, fmt_int)
-
-        int_base!(Show     for $Uint as $Uint -> Decimal)
-        int_base!(Binary   for $Uint as $Uint -> Binary)
-        int_base!(Octal    for $Uint as $Uint -> Octal)
-        int_base!(LowerHex for $Uint as $Uint -> LowerHex)
-        int_base!(UpperHex for $Uint as $Uint -> UpperHex)
-        radix_fmt!($Uint as $Uint, fmt_int)
+        int_base! { Show     for $Int as $Int   -> Decimal }
+        int_base! { Binary   for $Int as $Uint  -> Binary }
+        int_base! { Octal    for $Int as $Uint  -> Octal }
+        int_base! { LowerHex for $Int as $Uint  -> LowerHex }
+        int_base! { UpperHex for $Int as $Uint  -> UpperHex }
+        radix_fmt! { $Int as $Int, fmt_int }
+
+        int_base! { Show     for $Uint as $Uint -> Decimal }
+        int_base! { Binary   for $Uint as $Uint -> Binary }
+        int_base! { Octal    for $Uint as $Uint -> Octal }
+        int_base! { LowerHex for $Uint as $Uint -> LowerHex }
+        int_base! { UpperHex for $Uint as $Uint -> UpperHex }
+        radix_fmt! { $Uint as $Uint, fmt_int }
     }
 }
-integer!(int, uint)
-integer!(i8, u8)
-integer!(i16, u16)
-integer!(i32, u32)
-integer!(i64, u64)
+integer! { int, uint }
+integer! { i8, u8 }
+integer! { i16, u16 }
+integer! { i32, u32 }
+integer! { i64, u64 }
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 671ab825829..c1aa605a455 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -109,16 +109,16 @@ macro_rules! impl_hash {
     }
 }
 
-impl_hash!(u8, u8)
-impl_hash!(u16, u16)
-impl_hash!(u32, u32)
-impl_hash!(u64, u64)
-impl_hash!(uint, uint)
-impl_hash!(i8, u8)
-impl_hash!(i16, u16)
-impl_hash!(i32, u32)
-impl_hash!(i64, u64)
-impl_hash!(int, uint)
+impl_hash! { u8, u8 }
+impl_hash! { u16, u16 }
+impl_hash! { u32, u32 }
+impl_hash! { u64, u64 }
+impl_hash! { uint, uint }
+impl_hash! { i8, u8 }
+impl_hash! { i16, u16 }
+impl_hash! { i32, u32 }
+impl_hash! { i64, u64 }
+impl_hash! { int, uint }
 
 impl Hash for bool {
     #[inline]
@@ -142,7 +142,7 @@ impl Hash for str {
     }
 }
 
-macro_rules! impl_hash_tuple(
+macro_rules! impl_hash_tuple {
     () => (
         impl Hash for () {
             #[inline]
@@ -167,21 +167,21 @@ macro_rules! impl_hash_tuple(
             }
         }
     );
-)
-
-impl_hash_tuple!()
-impl_hash_tuple!(A)
-impl_hash_tuple!(A B)
-impl_hash_tuple!(A B C)
-impl_hash_tuple!(A B C D)
-impl_hash_tuple!(A B C D E)
-impl_hash_tuple!(A B C D E F)
-impl_hash_tuple!(A B C D E F G)
-impl_hash_tuple!(A B C D E F G H)
-impl_hash_tuple!(A B C D E F G H I)
-impl_hash_tuple!(A B C D E F G H I J)
-impl_hash_tuple!(A B C D E F G H I J K)
-impl_hash_tuple!(A B C D E F G H I J K L)
+}
+
+impl_hash_tuple! {}
+impl_hash_tuple! { A }
+impl_hash_tuple! { A B }
+impl_hash_tuple! { A B C }
+impl_hash_tuple! { A B C D }
+impl_hash_tuple! { A B C D E }
+impl_hash_tuple! { A B C D E F }
+impl_hash_tuple! { A B C D E F G }
+impl_hash_tuple! { A B C D E F G H }
+impl_hash_tuple! { A B C D E F G H I }
+impl_hash_tuple! { A B C D E F G H I J }
+impl_hash_tuple! { A B C D E F G H I J K }
+impl_hash_tuple! { A B C D E F G H I J K L }
 
 impl> Hash for [T] {
     #[inline]
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index 1f511ed759e..15f6768edce 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -48,7 +48,7 @@ impl Copy for SipState {}
 // because they're needed in the following defs;
 // this design could be improved.
 
-macro_rules! u8to64_le (
+macro_rules! u8to64_le {
     ($buf:expr, $i:expr) =>
     ($buf[0+$i] as u64 |
      $buf[1+$i] as u64 << 8 |
@@ -68,14 +68,14 @@ macro_rules! u8to64_le (
         }
         out
     });
-)
+}
 
-macro_rules! rotl (
+macro_rules! rotl {
     ($x:expr, $b:expr) =>
     (($x << $b) | ($x >> (64 - $b)))
-)
+}
 
-macro_rules! compress (
+macro_rules! compress {
     ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
     ({
         $v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
@@ -85,7 +85,7 @@ macro_rules! compress (
         $v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
         $v2 = rotl!($v2, 32);
     })
-)
+}
 
 impl SipState {
     /// Creates a `SipState` that is keyed off the provided keys.
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 7e0380e8785..de5c0defb1a 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -875,18 +875,18 @@ macro_rules! impl_additive {
         }
     };
 }
-impl_additive!(i8,   0)
-impl_additive!(i16,  0)
-impl_additive!(i32,  0)
-impl_additive!(i64,  0)
-impl_additive!(int,  0)
-impl_additive!(u8,   0)
-impl_additive!(u16,  0)
-impl_additive!(u32,  0)
-impl_additive!(u64,  0)
-impl_additive!(uint, 0)
-impl_additive!(f32,  0.0)
-impl_additive!(f64,  0.0)
+impl_additive! { i8,   0 }
+impl_additive! { i16,  0 }
+impl_additive! { i32,  0 }
+impl_additive! { i64,  0 }
+impl_additive! { int,  0 }
+impl_additive! { u8,   0 }
+impl_additive! { u16,  0 }
+impl_additive! { u32,  0 }
+impl_additive! { u64,  0 }
+impl_additive! { uint, 0 }
+impl_additive! { f32,  0.0 }
+impl_additive! { f64,  0.0 }
 
 /// A trait for iterators over elements which can be multiplied together.
 #[experimental = "needs to be re-evaluated as part of numerics reform"]
@@ -919,18 +919,18 @@ macro_rules! impl_multiplicative {
         }
     };
 }
-impl_multiplicative!(i8,   1)
-impl_multiplicative!(i16,  1)
-impl_multiplicative!(i32,  1)
-impl_multiplicative!(i64,  1)
-impl_multiplicative!(int,  1)
-impl_multiplicative!(u8,   1)
-impl_multiplicative!(u16,  1)
-impl_multiplicative!(u32,  1)
-impl_multiplicative!(u64,  1)
-impl_multiplicative!(uint, 1)
-impl_multiplicative!(f32,  1.0)
-impl_multiplicative!(f64,  1.0)
+impl_multiplicative! { i8,   1 }
+impl_multiplicative! { i16,  1 }
+impl_multiplicative! { i32,  1 }
+impl_multiplicative! { i64,  1 }
+impl_multiplicative! { int,  1 }
+impl_multiplicative! { u8,   1 }
+impl_multiplicative! { u16,  1 }
+impl_multiplicative! { u32,  1 }
+impl_multiplicative! { u64,  1 }
+impl_multiplicative! { uint, 1 }
+impl_multiplicative! { f32,  1.0 }
+impl_multiplicative! { f64,  1.0 }
 
 /// A trait for iterators over elements which can be compared to one another.
 #[unstable = "recently renamed for new extension trait conventions"]
@@ -1084,7 +1084,7 @@ impl MinMaxResult {
     /// use std::iter::{NoElements, OneElement, MinMax, MinMaxResult};
     ///
     /// let r: MinMaxResult = NoElements;
-    /// assert_eq!(r.into_option(), None)
+    /// assert_eq!(r.into_option(), None);
     ///
     /// let r = OneElement(1i);
     /// assert_eq!(r.into_option(), Some((1,1)));
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 9016f40b1b8..7ce1da7d2d0 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -12,7 +12,7 @@
 
 /// Entry point of task panic, for details, see std::macros
 #[macro_export]
-macro_rules! panic(
+macro_rules! panic {
     () => (
         panic!("{}", "explicit panic")
     );
@@ -44,11 +44,11 @@ macro_rules! panic(
         }
         format_args!(_run_fmt, $fmt, $($arg)*)
     });
-)
+}
 
 /// Runtime assertion, for details see std::macros
 #[macro_export]
-macro_rules! assert(
+macro_rules! assert {
     ($cond:expr) => (
         if !$cond {
             panic!(concat!("assertion failed: ", stringify!($cond)))
@@ -59,21 +59,21 @@ macro_rules! assert(
             panic!($($arg)*)
         }
     );
-)
+}
 
 /// Runtime assertion, only without `--cfg ndebug`
 #[macro_export]
-macro_rules! debug_assert(
+macro_rules! debug_assert {
     ($(a:tt)*) => ({
         if cfg!(not(ndebug)) {
             assert!($($a)*);
         }
     })
-)
+}
 
 /// Runtime assertion for equality, for details see std::macros
 #[macro_export]
-macro_rules! assert_eq(
+macro_rules! assert_eq {
     ($cond1:expr, $cond2:expr) => ({
         let c1 = $cond1;
         let c2 = $cond2;
@@ -81,46 +81,47 @@ macro_rules! assert_eq(
             panic!("expressions not equal, left: {}, right: {}", c1, c2);
         }
     })
-)
+}
 
 /// Runtime assertion for equality, only without `--cfg ndebug`
 #[macro_export]
-macro_rules! debug_assert_eq(
+macro_rules! debug_assert_eq {
     ($($a:tt)*) => ({
         if cfg!(not(ndebug)) {
             assert_eq!($($a)*);
         }
     })
-)
+}
 
 /// Runtime assertion, disableable at compile time
 #[macro_export]
-macro_rules! debug_assert(
+macro_rules! debug_assert {
     ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
-)
+}
 
 /// Short circuiting evaluation on Err
 #[macro_export]
-macro_rules! try(
+macro_rules! try {
     ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
-)
+}
 
 /// Writing a formatted string into a writer
 #[macro_export]
-macro_rules! write(
+macro_rules! write {
     ($dst:expr, $($arg:tt)*) => ({
         let dst = &mut *$dst;
         format_args!(|args| { dst.write_fmt(args) }, $($arg)*)
     })
-)
+}
 
 /// Writing a formatted string plus a newline into a writer
 #[macro_export]
-macro_rules! writeln(
+macro_rules! writeln {
     ($dst:expr, $fmt:expr $($arg:tt)*) => (
         write!($dst, concat!($fmt, "\n") $($arg)*)
     )
-)
+}
 
 #[macro_export]
-macro_rules! unreachable( () => (panic!("unreachable code")) )
+macro_rules! unreachable { () => (panic!("unreachable code")) }
+
diff --git a/src/libcore/num/float_macros.rs b/src/libcore/num/float_macros.rs
index d15cff3a8a9..97de61d7e27 100644
--- a/src/libcore/num/float_macros.rs
+++ b/src/libcore/num/float_macros.rs
@@ -11,11 +11,12 @@
 #![macro_escape]
 #![doc(hidden)]
 
-macro_rules! assert_approx_eq(
+macro_rules! assert_approx_eq {
     ($a:expr, $b:expr) => ({
         use num::Float;
         let (a, b) = (&$a, &$b);
         assert!((*a - *b).abs() < 1.0e-6,
                 "{} is not approximately equal to {}", *a, *b);
     })
-)
+}
+
diff --git a/src/libcore/num/i16.rs b/src/libcore/num/i16.rs
index 00c8dc5b68d..eb2a4c3835d 100644
--- a/src/libcore/num/i16.rs
+++ b/src/libcore/num/i16.rs
@@ -13,4 +13,4 @@
 #![stable]
 #![doc(primitive = "i16")]
 
-int_module!(i16, 16)
+int_module! { i16, 16 }
diff --git a/src/libcore/num/i32.rs b/src/libcore/num/i32.rs
index 1879ce1ac86..849fa205756 100644
--- a/src/libcore/num/i32.rs
+++ b/src/libcore/num/i32.rs
@@ -13,4 +13,4 @@
 #![stable]
 #![doc(primitive = "i32")]
 
-int_module!(i32, 32)
+int_module! { i32, 32 }
diff --git a/src/libcore/num/i64.rs b/src/libcore/num/i64.rs
index 5832b2fdc03..b6cba728e44 100644
--- a/src/libcore/num/i64.rs
+++ b/src/libcore/num/i64.rs
@@ -13,4 +13,4 @@
 #![stable]
 #![doc(primitive = "i64")]
 
-int_module!(i64, 64)
+int_module! { i64, 64 }
diff --git a/src/libcore/num/i8.rs b/src/libcore/num/i8.rs
index 65cf5d2b1c1..fd0759898ea 100644
--- a/src/libcore/num/i8.rs
+++ b/src/libcore/num/i8.rs
@@ -13,4 +13,4 @@
 #![stable]
 #![doc(primitive = "i8")]
 
-int_module!(i8, 8)
+int_module! { i8, 8 }
diff --git a/src/libcore/num/int.rs b/src/libcore/num/int.rs
index 835246684df..a0659d38307 100644
--- a/src/libcore/num/int.rs
+++ b/src/libcore/num/int.rs
@@ -13,6 +13,6 @@
 #![unstable]
 #![doc(primitive = "int")]
 
-#[cfg(target_word_size = "32")] int_module!(int, 32)
-#[cfg(target_word_size = "64")] int_module!(int, 64)
+#[cfg(target_word_size = "32")] int_module! { int, 32 }
+#[cfg(target_word_size = "64")] int_module! { int, 64 }
 
diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs
index 0f8950344c8..00b9d88abe1 100644
--- a/src/libcore/num/int_macros.rs
+++ b/src/libcore/num/int_macros.rs
@@ -11,7 +11,7 @@
 #![macro_escape]
 #![doc(hidden)]
 
-macro_rules! int_module (($T:ty, $bits:expr) => (
+macro_rules! int_module { ($T:ty, $bits:expr) => (
 
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `mem::size_of` function.
@@ -32,4 +32,5 @@ pub const MIN: $T = (-1 as $T) << (BITS - 1);
 #[unstable]
 pub const MAX: $T = !MIN;
 
-))
+) }
+
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 2416cf5bcc7..fcb2ca93054 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -458,61 +458,61 @@ macro_rules! uint_impl {
 /// consistency with the other `bswap` intrinsics.
 unsafe fn bswap8(x: u8) -> u8 { x }
 
-uint_impl!(u8 = u8, 8,
+uint_impl! { u8 = u8, 8,
     intrinsics::ctpop8,
     intrinsics::ctlz8,
     intrinsics::cttz8,
     bswap8,
     intrinsics::u8_add_with_overflow,
     intrinsics::u8_sub_with_overflow,
-    intrinsics::u8_mul_with_overflow)
+    intrinsics::u8_mul_with_overflow }
 
-uint_impl!(u16 = u16, 16,
+uint_impl! { u16 = u16, 16,
     intrinsics::ctpop16,
     intrinsics::ctlz16,
     intrinsics::cttz16,
     intrinsics::bswap16,
     intrinsics::u16_add_with_overflow,
     intrinsics::u16_sub_with_overflow,
-    intrinsics::u16_mul_with_overflow)
+    intrinsics::u16_mul_with_overflow }
 
-uint_impl!(u32 = u32, 32,
+uint_impl! { u32 = u32, 32,
     intrinsics::ctpop32,
     intrinsics::ctlz32,
     intrinsics::cttz32,
     intrinsics::bswap32,
     intrinsics::u32_add_with_overflow,
     intrinsics::u32_sub_with_overflow,
-    intrinsics::u32_mul_with_overflow)
+    intrinsics::u32_mul_with_overflow }
 
-uint_impl!(u64 = u64, 64,
+uint_impl! { u64 = u64, 64,
     intrinsics::ctpop64,
     intrinsics::ctlz64,
     intrinsics::cttz64,
     intrinsics::bswap64,
     intrinsics::u64_add_with_overflow,
     intrinsics::u64_sub_with_overflow,
-    intrinsics::u64_mul_with_overflow)
+    intrinsics::u64_mul_with_overflow }
 
 #[cfg(target_word_size = "32")]
-uint_impl!(uint = u32, 32,
+uint_impl! { uint = u32, 32,
     intrinsics::ctpop32,
     intrinsics::ctlz32,
     intrinsics::cttz32,
     intrinsics::bswap32,
     intrinsics::u32_add_with_overflow,
     intrinsics::u32_sub_with_overflow,
-    intrinsics::u32_mul_with_overflow)
+    intrinsics::u32_mul_with_overflow }
 
 #[cfg(target_word_size = "64")]
-uint_impl!(uint = u64, 64,
+uint_impl! { uint = u64, 64,
     intrinsics::ctpop64,
     intrinsics::ctlz64,
     intrinsics::cttz64,
     intrinsics::bswap64,
     intrinsics::u64_add_with_overflow,
     intrinsics::u64_sub_with_overflow,
-    intrinsics::u64_mul_with_overflow)
+    intrinsics::u64_mul_with_overflow }
 
 macro_rules! int_impl {
     ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr,
@@ -579,37 +579,37 @@ macro_rules! int_impl {
     }
 }
 
-int_impl!(i8 = i8, u8, 8,
+int_impl! { i8 = i8, u8, 8,
     intrinsics::i8_add_with_overflow,
     intrinsics::i8_sub_with_overflow,
-    intrinsics::i8_mul_with_overflow)
+    intrinsics::i8_mul_with_overflow }
 
-int_impl!(i16 = i16, u16, 16,
+int_impl! { i16 = i16, u16, 16,
     intrinsics::i16_add_with_overflow,
     intrinsics::i16_sub_with_overflow,
-    intrinsics::i16_mul_with_overflow)
+    intrinsics::i16_mul_with_overflow }
 
-int_impl!(i32 = i32, u32, 32,
+int_impl! { i32 = i32, u32, 32,
     intrinsics::i32_add_with_overflow,
     intrinsics::i32_sub_with_overflow,
-    intrinsics::i32_mul_with_overflow)
+    intrinsics::i32_mul_with_overflow }
 
-int_impl!(i64 = i64, u64, 64,
+int_impl! { i64 = i64, u64, 64,
     intrinsics::i64_add_with_overflow,
     intrinsics::i64_sub_with_overflow,
-    intrinsics::i64_mul_with_overflow)
+    intrinsics::i64_mul_with_overflow }
 
 #[cfg(target_word_size = "32")]
-int_impl!(int = i32, u32, 32,
+int_impl! { int = i32, u32, 32,
     intrinsics::i32_add_with_overflow,
     intrinsics::i32_sub_with_overflow,
-    intrinsics::i32_mul_with_overflow)
+    intrinsics::i32_mul_with_overflow }
 
 #[cfg(target_word_size = "64")]
-int_impl!(int = i64, u64, 64,
+int_impl! { int = i64, u64, 64,
     intrinsics::i64_add_with_overflow,
     intrinsics::i64_sub_with_overflow,
-    intrinsics::i64_mul_with_overflow)
+    intrinsics::i64_mul_with_overflow }
 
 /// A built-in two's complement integer.
 #[unstable = "recently settled as part of numerics reform"]
@@ -663,11 +663,11 @@ macro_rules! signed_int_impl {
     }
 }
 
-signed_int_impl!(i8)
-signed_int_impl!(i16)
-signed_int_impl!(i32)
-signed_int_impl!(i64)
-signed_int_impl!(int)
+signed_int_impl! { i8 }
+signed_int_impl! { i16 }
+signed_int_impl! { i32 }
+signed_int_impl! { i64 }
+signed_int_impl! { int }
 
 /// A built-in unsigned integer.
 #[unstable = "recently settled as part of numerics reform"]
@@ -791,7 +791,7 @@ pub trait ToPrimitive {
     }
 }
 
-macro_rules! impl_to_primitive_int_to_int(
+macro_rules! impl_to_primitive_int_to_int {
     ($SrcT:ty, $DstT:ty, $slf:expr) => (
         {
             if size_of::<$SrcT>() <= size_of::<$DstT>() {
@@ -808,9 +808,9 @@ macro_rules! impl_to_primitive_int_to_int(
             }
         }
     )
-)
+}
 
-macro_rules! impl_to_primitive_int_to_uint(
+macro_rules! impl_to_primitive_int_to_uint {
     ($SrcT:ty, $DstT:ty, $slf:expr) => (
         {
             let zero: $SrcT = Int::zero();
@@ -822,9 +822,9 @@ macro_rules! impl_to_primitive_int_to_uint(
             }
         }
     )
-)
+}
 
-macro_rules! impl_to_primitive_int(
+macro_rules! impl_to_primitive_int {
     ($T:ty) => (
         impl ToPrimitive for $T {
             #[inline]
@@ -855,15 +855,15 @@ macro_rules! impl_to_primitive_int(
             fn to_f64(&self) -> Option { Some(*self as f64) }
         }
     )
-)
+}
 
-impl_to_primitive_int!(int)
-impl_to_primitive_int!(i8)
-impl_to_primitive_int!(i16)
-impl_to_primitive_int!(i32)
-impl_to_primitive_int!(i64)
+impl_to_primitive_int! { int }
+impl_to_primitive_int! { i8 }
+impl_to_primitive_int! { i16 }
+impl_to_primitive_int! { i32 }
+impl_to_primitive_int! { i64 }
 
-macro_rules! impl_to_primitive_uint_to_int(
+macro_rules! impl_to_primitive_uint_to_int {
     ($DstT:ty, $slf:expr) => (
         {
             let max_value: $DstT = Int::max_value();
@@ -874,9 +874,9 @@ macro_rules! impl_to_primitive_uint_to_int(
             }
         }
     )
-)
+}
 
-macro_rules! impl_to_primitive_uint_to_uint(
+macro_rules! impl_to_primitive_uint_to_uint {
     ($SrcT:ty, $DstT:ty, $slf:expr) => (
         {
             if size_of::<$SrcT>() <= size_of::<$DstT>() {
@@ -892,9 +892,9 @@ macro_rules! impl_to_primitive_uint_to_uint(
             }
         }
     )
-)
+}
 
-macro_rules! impl_to_primitive_uint(
+macro_rules! impl_to_primitive_uint {
     ($T:ty) => (
         impl ToPrimitive for $T {
             #[inline]
@@ -925,15 +925,15 @@ macro_rules! impl_to_primitive_uint(
             fn to_f64(&self) -> Option { Some(*self as f64) }
         }
     )
-)
+}
 
-impl_to_primitive_uint!(uint)
-impl_to_primitive_uint!(u8)
-impl_to_primitive_uint!(u16)
-impl_to_primitive_uint!(u32)
-impl_to_primitive_uint!(u64)
+impl_to_primitive_uint! { uint }
+impl_to_primitive_uint! { u8 }
+impl_to_primitive_uint! { u16 }
+impl_to_primitive_uint! { u32 }
+impl_to_primitive_uint! { u64 }
 
-macro_rules! impl_to_primitive_float_to_float(
+macro_rules! impl_to_primitive_float_to_float {
     ($SrcT:ty, $DstT:ty, $slf:expr) => (
         if size_of::<$SrcT>() <= size_of::<$DstT>() {
             Some($slf as $DstT)
@@ -947,9 +947,9 @@ macro_rules! impl_to_primitive_float_to_float(
             }
         }
     )
-)
+}
 
-macro_rules! impl_to_primitive_float(
+macro_rules! impl_to_primitive_float {
     ($T:ty) => (
         impl ToPrimitive for $T {
             #[inline]
@@ -980,10 +980,10 @@ macro_rules! impl_to_primitive_float(
             fn to_f64(&self) -> Option { impl_to_primitive_float_to_float!($T, f64, *self) }
         }
     )
-)
+}
 
-impl_to_primitive_float!(f32)
-impl_to_primitive_float!(f64)
+impl_to_primitive_float! { f32 }
+impl_to_primitive_float! { f64 }
 
 /// A generic trait for converting a number to a value.
 #[experimental = "trait is likely to be removed"]
@@ -1139,7 +1139,7 @@ pub fn from_f64(n: f64) -> Option {
     FromPrimitive::from_f64(n)
 }
 
-macro_rules! impl_from_primitive(
+macro_rules! impl_from_primitive {
     ($T:ty, $to_ty:ident) => (
         impl FromPrimitive for $T {
             #[inline] fn from_int(n: int) -> Option<$T> { n.$to_ty() }
@@ -1158,20 +1158,20 @@ macro_rules! impl_from_primitive(
             #[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
         }
     )
-)
-
-impl_from_primitive!(int, to_int)
-impl_from_primitive!(i8, to_i8)
-impl_from_primitive!(i16, to_i16)
-impl_from_primitive!(i32, to_i32)
-impl_from_primitive!(i64, to_i64)
-impl_from_primitive!(uint, to_uint)
-impl_from_primitive!(u8, to_u8)
-impl_from_primitive!(u16, to_u16)
-impl_from_primitive!(u32, to_u32)
-impl_from_primitive!(u64, to_u64)
-impl_from_primitive!(f32, to_f32)
-impl_from_primitive!(f64, to_f64)
+}
+
+impl_from_primitive! { int, to_int }
+impl_from_primitive! { i8, to_i8 }
+impl_from_primitive! { i16, to_i16 }
+impl_from_primitive! { i32, to_i32 }
+impl_from_primitive! { i64, to_i64 }
+impl_from_primitive! { uint, to_uint }
+impl_from_primitive! { u8, to_u8 }
+impl_from_primitive! { u16, to_u16 }
+impl_from_primitive! { u32, to_u32 }
+impl_from_primitive! { u64, to_u64 }
+impl_from_primitive! { f32, to_f32 }
+impl_from_primitive! { f64, to_f64 }
 
 /// Cast from one machine scalar to another.
 ///
@@ -1198,7 +1198,7 @@ pub trait NumCast: ToPrimitive {
     fn from(n: T) -> Option;
 }
 
-macro_rules! impl_num_cast(
+macro_rules! impl_num_cast {
     ($T:ty, $conv:ident) => (
         impl NumCast for $T {
             #[inline]
@@ -1209,20 +1209,20 @@ macro_rules! impl_num_cast(
             }
         }
     )
-)
-
-impl_num_cast!(u8,    to_u8)
-impl_num_cast!(u16,   to_u16)
-impl_num_cast!(u32,   to_u32)
-impl_num_cast!(u64,   to_u64)
-impl_num_cast!(uint,  to_uint)
-impl_num_cast!(i8,    to_i8)
-impl_num_cast!(i16,   to_i16)
-impl_num_cast!(i32,   to_i32)
-impl_num_cast!(i64,   to_i64)
-impl_num_cast!(int,   to_int)
-impl_num_cast!(f32,   to_f32)
-impl_num_cast!(f64,   to_f64)
+}
+
+impl_num_cast! { u8,    to_u8 }
+impl_num_cast! { u16,   to_u16 }
+impl_num_cast! { u32,   to_u32 }
+impl_num_cast! { u64,   to_u64 }
+impl_num_cast! { uint,  to_uint }
+impl_num_cast! { i8,    to_i8 }
+impl_num_cast! { i16,   to_i16 }
+impl_num_cast! { i32,   to_i32 }
+impl_num_cast! { i64,   to_i64 }
+impl_num_cast! { int,   to_int }
+impl_num_cast! { f32,   to_f32 }
+impl_num_cast! { f64,   to_f64 }
 
 /// Used for representing the classification of floating point numbers
 #[deriving(PartialEq, Show)]
@@ -1638,8 +1638,8 @@ macro_rules! from_str_radix_float_impl {
         }
     }
 }
-from_str_radix_float_impl!(f32)
-from_str_radix_float_impl!(f64)
+from_str_radix_float_impl! { f32 }
+from_str_radix_float_impl! { f64 }
 
 macro_rules! from_str_radix_int_impl {
     ($T:ty) => {
@@ -1705,16 +1705,16 @@ macro_rules! from_str_radix_int_impl {
         }
     }
 }
-from_str_radix_int_impl!(int)
-from_str_radix_int_impl!(i8)
-from_str_radix_int_impl!(i16)
-from_str_radix_int_impl!(i32)
-from_str_radix_int_impl!(i64)
-from_str_radix_int_impl!(uint)
-from_str_radix_int_impl!(u8)
-from_str_radix_int_impl!(u16)
-from_str_radix_int_impl!(u32)
-from_str_radix_int_impl!(u64)
+from_str_radix_int_impl! { int }
+from_str_radix_int_impl! { i8 }
+from_str_radix_int_impl! { i16 }
+from_str_radix_int_impl! { i32 }
+from_str_radix_int_impl! { i64 }
+from_str_radix_int_impl! { uint }
+from_str_radix_int_impl! { u8 }
+from_str_radix_int_impl! { u16 }
+from_str_radix_int_impl! { u32 }
+from_str_radix_int_impl! { u64 }
 
 // DEPRECATED
 
@@ -1733,17 +1733,17 @@ pub trait Num: PartialEq + Zero + One
              + Mul
              + Div
              + Rem {}
-trait_impl!(Num for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+trait_impl! { Num for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 
 #[deprecated = "Generalised unsigned numbers are no longer supported"]
 #[allow(deprecated)]
 pub trait Unsigned: Num {}
-trait_impl!(Unsigned for uint u8 u16 u32 u64)
+trait_impl! { Unsigned for uint u8 u16 u32 u64 }
 
 #[deprecated = "Use `Float` or `Int`"]
 #[allow(deprecated)]
 pub trait Primitive: Copy + Clone + Num + NumCast + PartialOrd {}
-trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+trait_impl! { Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 
 #[deprecated = "The generic `Zero` trait will be removed soon."]
 pub trait Zero: Add {
@@ -1763,18 +1763,18 @@ macro_rules! zero_impl {
         }
     }
 }
-zero_impl!(uint, 0u)
-zero_impl!(u8,   0u8)
-zero_impl!(u16,  0u16)
-zero_impl!(u32,  0u32)
-zero_impl!(u64,  0u64)
-zero_impl!(int, 0i)
-zero_impl!(i8,  0i8)
-zero_impl!(i16, 0i16)
-zero_impl!(i32, 0i32)
-zero_impl!(i64, 0i64)
-zero_impl!(f32, 0.0f32)
-zero_impl!(f64, 0.0f64)
+zero_impl! { uint, 0u }
+zero_impl! { u8,   0u8 }
+zero_impl! { u16,  0u16 }
+zero_impl! { u32,  0u32 }
+zero_impl! { u64,  0u64 }
+zero_impl! { int, 0i }
+zero_impl! { i8,  0i8 }
+zero_impl! { i16, 0i16 }
+zero_impl! { i32, 0i32 }
+zero_impl! { i64, 0i64 }
+zero_impl! { f32, 0.0f32 }
+zero_impl! { f64, 0.0f64 }
 
 #[deprecated = "The generic `One` trait will be removed soon."]
 pub trait One: Mul {
@@ -1791,18 +1791,18 @@ macro_rules! one_impl {
         }
     }
 }
-one_impl!(uint, 1u)
-one_impl!(u8,  1u8)
-one_impl!(u16, 1u16)
-one_impl!(u32, 1u32)
-one_impl!(u64, 1u64)
-one_impl!(int, 1i)
-one_impl!(i8,  1i8)
-one_impl!(i16, 1i16)
-one_impl!(i32, 1i32)
-one_impl!(i64, 1i64)
-one_impl!(f32, 1.0f32)
-one_impl!(f64, 1.0f64)
+one_impl! { uint, 1u }
+one_impl! { u8,  1u8 }
+one_impl! { u16, 1u16 }
+one_impl! { u32, 1u32 }
+one_impl! { u64, 1u64 }
+one_impl! { int, 1i }
+one_impl! { i8,  1i8 }
+one_impl! { i16, 1i16 }
+one_impl! { i32, 1i32 }
+one_impl! { i64, 1i64 }
+one_impl! { f32, 1.0f32 }
+one_impl! { f64, 1.0f64 }
 
 #[deprecated = "Use `UnsignedInt::next_power_of_two`"]
 pub fn next_power_of_two(n: T) -> T {
@@ -1835,15 +1835,15 @@ macro_rules! bounded_impl {
         }
     };
 }
-bounded_impl!(uint, uint::MIN, uint::MAX)
-bounded_impl!(u8, u8::MIN, u8::MAX)
-bounded_impl!(u16, u16::MIN, u16::MAX)
-bounded_impl!(u32, u32::MIN, u32::MAX)
-bounded_impl!(u64, u64::MIN, u64::MAX)
-bounded_impl!(int, int::MIN, int::MAX)
-bounded_impl!(i8, i8::MIN, i8::MAX)
-bounded_impl!(i16, i16::MIN, i16::MAX)
-bounded_impl!(i32, i32::MIN, i32::MAX)
-bounded_impl!(i64, i64::MIN, i64::MAX)
-bounded_impl!(f32, f32::MIN_VALUE, f32::MAX_VALUE)
-bounded_impl!(f64, f64::MIN_VALUE, f64::MAX_VALUE)
+bounded_impl! { uint, uint::MIN, uint::MAX }
+bounded_impl! { u8, u8::MIN, u8::MAX }
+bounded_impl! { u16, u16::MIN, u16::MAX }
+bounded_impl! { u32, u32::MIN, u32::MAX }
+bounded_impl! { u64, u64::MIN, u64::MAX }
+bounded_impl! { int, int::MIN, int::MAX }
+bounded_impl! { i8, i8::MIN, i8::MAX }
+bounded_impl! { i16, i16::MIN, i16::MAX }
+bounded_impl! { i32, i32::MIN, i32::MAX }
+bounded_impl! { i64, i64::MIN, i64::MAX }
+bounded_impl! { f32, f32::MIN_VALUE, f32::MAX_VALUE }
+bounded_impl! { f64, f64::MIN_VALUE, f64::MAX_VALUE }
diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs
index 6971de279fa..730a24a963a 100644
--- a/src/libcore/num/u16.rs
+++ b/src/libcore/num/u16.rs
@@ -13,4 +13,4 @@
 #![stable]
 #![doc(primitive = "u16")]
 
-uint_module!(u16, i16, 16)
+uint_module! { u16, i16, 16 }
diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs
index 26affc3f790..f308122af43 100644
--- a/src/libcore/num/u32.rs
+++ b/src/libcore/num/u32.rs
@@ -13,4 +13,4 @@
 #![stable]
 #![doc(primitive = "u32")]
 
-uint_module!(u32, i32, 32)
+uint_module! { u32, i32, 32 }
diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs
index 3b50d033001..a55868eb746 100644
--- a/src/libcore/num/u64.rs
+++ b/src/libcore/num/u64.rs
@@ -13,4 +13,4 @@
 #![stable]
 #![doc(primitive = "u64")]
 
-uint_module!(u64, i64, 64)
+uint_module! { u64, i64, 64 }
diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs
index ce7d767aee4..8643f8ad650 100644
--- a/src/libcore/num/u8.rs
+++ b/src/libcore/num/u8.rs
@@ -13,4 +13,4 @@
 #![stable]
 #![doc(primitive = "u8")]
 
-uint_module!(u8, i8, 8)
+uint_module! { u8, i8, 8 }
diff --git a/src/libcore/num/uint.rs b/src/libcore/num/uint.rs
index 62d2f11e541..80d7b0b4ef3 100644
--- a/src/libcore/num/uint.rs
+++ b/src/libcore/num/uint.rs
@@ -13,5 +13,5 @@
 #![unstable]
 #![doc(primitive = "uint")]
 
-uint_module!(uint, int, ::int::BITS)
+uint_module! { uint, int, ::int::BITS }
 
diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs
index 2a94f851646..d79cf20fdfa 100644
--- a/src/libcore/num/uint_macros.rs
+++ b/src/libcore/num/uint_macros.rs
@@ -11,7 +11,7 @@
 #![macro_escape]
 #![doc(hidden)]
 
-macro_rules! uint_module (($T:ty, $T_SIGNED:ty, $bits:expr) => (
+macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
 
 #[unstable]
 pub const BITS : uint = $bits;
@@ -23,4 +23,5 @@ pub const MIN: $T = 0 as $T;
 #[unstable]
 pub const MAX: $T = 0 as $T - 1 as $T;
 
-))
+) }
+
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 7ff5026d0b9..bc29a2b4a58 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -113,14 +113,14 @@ pub trait Add for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! add_impl(
+macro_rules! add_impl {
     ($($t:ty)*) => ($(
         impl Add<$t, $t> for $t {
             #[inline]
             fn add(&self, other: &$t) -> $t { (*self) + (*other) }
         }
     )*)
-)
+}
 
 /// The `Add` trait is used to specify the functionality of `+`.
 ///
@@ -151,16 +151,16 @@ pub trait Add {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! add_impl(
+macro_rules! add_impl {
     ($($t:ty)*) => ($(
         impl Add<$t, $t> for $t {
             #[inline]
             fn add(self, other: $t) -> $t { self + other }
         }
     )*)
-)
+}
 
-add_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+add_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 
 /// The `Sub` trait is used to specify the functionality of `-`.
 ///
@@ -195,14 +195,14 @@ pub trait Sub for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! sub_impl(
+macro_rules! sub_impl {
     ($($t:ty)*) => ($(
         impl Sub<$t, $t> for $t {
             #[inline]
             fn sub(&self, other: &$t) -> $t { (*self) - (*other) }
         }
     )*)
-)
+}
 
 /// The `Sub` trait is used to specify the functionality of `-`.
 ///
@@ -233,16 +233,16 @@ pub trait Sub {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! sub_impl(
+macro_rules! sub_impl {
     ($($t:ty)*) => ($(
         impl Sub<$t, $t> for $t {
             #[inline]
             fn sub(self, other: $t) -> $t { self - other }
         }
     )*)
-)
+}
 
-sub_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+sub_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 
 /// The `Mul` trait is used to specify the functionality of `*`.
 ///
@@ -277,14 +277,14 @@ pub trait Mul  for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! mul_impl(
+macro_rules! mul_impl {
     ($($t:ty)*) => ($(
         impl Mul<$t, $t> for $t {
             #[inline]
             fn mul(&self, other: &$t) -> $t { (*self) * (*other) }
         }
     )*)
-)
+}
 
 /// The `Mul` trait is used to specify the functionality of `*`.
 ///
@@ -315,16 +315,16 @@ pub trait Mul {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! mul_impl(
+macro_rules! mul_impl {
     ($($t:ty)*) => ($(
         impl Mul<$t, $t> for $t {
             #[inline]
             fn mul(self, other: $t) -> $t { self * other }
         }
     )*)
-)
+}
 
-mul_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+mul_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 
 /// The `Div` trait is used to specify the functionality of `/`.
 ///
@@ -359,14 +359,14 @@ pub trait Div for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! div_impl(
+macro_rules! div_impl {
     ($($t:ty)*) => ($(
         impl Div<$t, $t> for $t {
             #[inline]
             fn div(&self, other: &$t) -> $t { (*self) / (*other) }
         }
     )*)
-)
+}
 
 /// The `Div` trait is used to specify the functionality of `/`.
 ///
@@ -397,16 +397,16 @@ pub trait Div {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! div_impl(
+macro_rules! div_impl {
     ($($t:ty)*) => ($(
         impl Div<$t, $t> for $t {
             #[inline]
             fn div(self, other: $t) -> $t { self / other }
         }
     )*)
-)
+}
 
-div_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+div_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
 
 /// The `Rem` trait is used to specify the functionality of `%`.
 ///
@@ -441,18 +441,18 @@ pub trait Rem  for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! rem_impl(
+macro_rules! rem_impl {
     ($($t:ty)*) => ($(
         impl Rem<$t, $t> for $t {
             #[inline]
             fn rem(&self, other: &$t) -> $t { (*self) % (*other) }
         }
     )*)
-)
+}
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! rem_float_impl(
+macro_rules! rem_float_impl {
     ($t:ty, $fmod:ident) => {
         impl Rem<$t, $t> for $t {
             #[inline]
@@ -462,7 +462,7 @@ macro_rules! rem_float_impl(
             }
         }
     }
-)
+}
 
 /// The `Rem` trait is used to specify the functionality of `%`.
 ///
@@ -493,17 +493,17 @@ pub trait Rem {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! rem_impl(
+macro_rules! rem_impl {
     ($($t:ty)*) => ($(
         impl Rem<$t, $t> for $t {
             #[inline]
             fn rem(self, other: $t) -> $t { self % other }
         }
     )*)
-)
+}
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! rem_float_impl(
+macro_rules! rem_float_impl {
     ($t:ty, $fmod:ident) => {
         impl Rem<$t, $t> for $t {
             #[inline]
@@ -513,11 +513,11 @@ macro_rules! rem_float_impl(
             }
         }
     }
-)
+}
 
-rem_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
-rem_float_impl!(f32, fmodf)
-rem_float_impl!(f64, fmod)
+rem_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
+rem_float_impl! { f32, fmodf }
+rem_float_impl! { f64, fmod }
 
 /// The `Neg` trait is used to specify the functionality of unary `-`.
 ///
@@ -548,31 +548,31 @@ pub trait Neg for Sized? {
     fn neg(&self) -> Result;
 }
 
-macro_rules! neg_impl(
+macro_rules! neg_impl {
     ($($t:ty)*) => ($(
         impl Neg<$t> for $t {
             #[inline]
             fn neg(&self) -> $t { -*self }
         }
     )*)
-)
+}
 
-macro_rules! neg_uint_impl(
+macro_rules! neg_uint_impl {
     ($t:ty, $t_signed:ty) => {
         impl Neg<$t> for $t {
             #[inline]
             fn neg(&self) -> $t { -(*self as $t_signed) as $t }
         }
     }
-)
+}
 
-neg_impl!(int i8 i16 i32 i64 f32 f64)
+neg_impl! { int i8 i16 i32 i64 f32 f64 }
 
-neg_uint_impl!(uint, int)
-neg_uint_impl!(u8, i8)
-neg_uint_impl!(u16, i16)
-neg_uint_impl!(u32, i32)
-neg_uint_impl!(u64, i64)
+neg_uint_impl! { uint, int }
+neg_uint_impl! { u8, i8 }
+neg_uint_impl! { u16, i16 }
+neg_uint_impl! { u32, i32 }
+neg_uint_impl! { u64, i64 }
 
 
 /// The `Not` trait is used to specify the functionality of unary `!`.
@@ -605,16 +605,16 @@ pub trait Not for Sized? {
 }
 
 
-macro_rules! not_impl(
+macro_rules! not_impl {
     ($($t:ty)*) => ($(
         impl Not<$t> for $t {
             #[inline]
             fn not(&self) -> $t { !*self }
         }
     )*)
-)
+}
 
-not_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
+not_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
 /// The `BitAnd` trait is used to specify the functionality of `&`.
 ///
@@ -649,14 +649,14 @@ pub trait BitAnd for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! bitand_impl(
+macro_rules! bitand_impl {
     ($($t:ty)*) => ($(
         impl BitAnd<$t, $t> for $t {
             #[inline]
             fn bitand(&self, rhs: &$t) -> $t { (*self) & (*rhs) }
         }
     )*)
-)
+}
 
 /// The `BitAnd` trait is used to specify the functionality of `&`.
 ///
@@ -687,16 +687,16 @@ pub trait BitAnd {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! bitand_impl(
+macro_rules! bitand_impl {
     ($($t:ty)*) => ($(
         impl BitAnd<$t, $t> for $t {
             #[inline]
             fn bitand(self, rhs: $t) -> $t { self & rhs }
         }
     )*)
-)
+}
 
-bitand_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
+bitand_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
 /// The `BitOr` trait is used to specify the functionality of `|`.
 ///
@@ -731,14 +731,14 @@ pub trait BitOr for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! bitor_impl(
+macro_rules! bitor_impl {
     ($($t:ty)*) => ($(
         impl BitOr<$t,$t> for $t {
             #[inline]
             fn bitor(&self, rhs: &$t) -> $t { (*self) | (*rhs) }
         }
     )*)
-)
+}
 
 /// The `BitOr` trait is used to specify the functionality of `|`.
 ///
@@ -769,16 +769,16 @@ pub trait BitOr {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! bitor_impl(
+macro_rules! bitor_impl {
     ($($t:ty)*) => ($(
         impl BitOr<$t,$t> for $t {
             #[inline]
             fn bitor(self, rhs: $t) -> $t { self | rhs }
         }
     )*)
-)
+}
 
-bitor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
+bitor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
 /// The `BitXor` trait is used to specify the functionality of `^`.
 ///
@@ -813,14 +813,14 @@ pub trait BitXor for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! bitxor_impl(
+macro_rules! bitxor_impl {
     ($($t:ty)*) => ($(
         impl BitXor<$t, $t> for $t {
             #[inline]
             fn bitxor(&self, other: &$t) -> $t { (*self) ^ (*other) }
         }
     )*)
-)
+}
 
 /// The `BitXor` trait is used to specify the functionality of `^`.
 ///
@@ -851,16 +851,16 @@ pub trait BitXor {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! bitxor_impl(
+macro_rules! bitxor_impl {
     ($($t:ty)*) => ($(
         impl BitXor<$t, $t> for $t {
             #[inline]
             fn bitxor(self, other: $t) -> $t { self ^ other }
         }
     )*)
-)
+}
 
-bitxor_impl!(bool uint u8 u16 u32 u64 int i8 i16 i32 i64)
+bitxor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
 /// The `Shl` trait is used to specify the functionality of `<<`.
 ///
@@ -895,7 +895,7 @@ pub trait Shl for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! shl_impl(
+macro_rules! shl_impl {
     ($($t:ty)*) => ($(
         impl Shl for $t {
             #[inline]
@@ -904,7 +904,7 @@ macro_rules! shl_impl(
             }
         }
     )*)
-)
+}
 
 /// The `Shl` trait is used to specify the functionality of `<<`.
 ///
@@ -935,7 +935,7 @@ pub trait Shl {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! shl_impl(
+macro_rules! shl_impl {
     ($($t:ty)*) => ($(
         impl Shl for $t {
             #[inline]
@@ -944,9 +944,9 @@ macro_rules! shl_impl(
             }
         }
     )*)
-)
+}
 
-shl_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
+shl_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
 /// The `Shr` trait is used to specify the functionality of `>>`.
 ///
@@ -981,14 +981,14 @@ pub trait Shr for Sized? {
 
 // NOTE(stage0): Remove macro after a snapshot
 #[cfg(stage0)]
-macro_rules! shr_impl(
+macro_rules! shr_impl {
     ($($t:ty)*) => ($(
         impl Shr for $t {
             #[inline]
             fn shr(&self, other: &uint) -> $t { (*self) >> (*other) }
         }
     )*)
-)
+}
 
 /// The `Shr` trait is used to specify the functionality of `>>`.
 ///
@@ -1019,16 +1019,16 @@ pub trait Shr {
 }
 
 #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
-macro_rules! shr_impl(
+macro_rules! shr_impl {
     ($($t:ty)*) => ($(
         impl Shr for $t {
             #[inline]
             fn shr(self, other: uint) -> $t { self >> other }
         }
     )*)
-)
+}
 
-shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
+shr_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
 
 /// The `Index` trait is used to specify the functionality of indexing operations
 /// like `arr[idx]` when used in an immutable context.
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index edd5f989797..36c6b9572ea 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -367,7 +367,7 @@ mod externfnpointers {
             self_ == other_
         }
     }
-    macro_rules! fnptreq(
+    macro_rules! fnptreq {
         ($($p:ident),*) => {
             impl<_R,$($p),*> PartialEq for extern "C" fn($($p),*) -> _R {
                 #[inline]
@@ -379,12 +379,12 @@ mod externfnpointers {
                 }
             }
         }
-    )
-    fnptreq!(A)
-    fnptreq!(A,B)
-    fnptreq!(A,B,C)
-    fnptreq!(A,B,C,D)
-    fnptreq!(A,B,C,D,E)
+    }
+    fnptreq! { A }
+    fnptreq! { A,B }
+    fnptreq! { A,B,C }
+    fnptreq! { A,B,C,D }
+    fnptreq! { A,B,C,D,E }
 }
 
 // Comparison for pointers
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 6dd23abf11f..e12666a2adf 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -222,7 +222,7 @@
 //! # #![feature(macro_rules)]
 //! macro_rules! try(
 //!     ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
-//! )
+//! );
 //! # fn main() { }
 //! ```
 //!
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 411a46ee1bd..2ee60955245 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -1540,16 +1540,16 @@ macro_rules! impl_mut_int_slice {
 
 macro_rules! impl_int_slice {
     ($u:ty, $s:ty) => {
-        impl_immut_int_slice!($u, $s, $u)
-        impl_immut_int_slice!($u, $s, $s)
-        impl_mut_int_slice!($u, $s, $u)
-        impl_mut_int_slice!($u, $s, $s)
+        impl_immut_int_slice! { $u, $s, $u }
+        impl_immut_int_slice! { $u, $s, $s }
+        impl_mut_int_slice! { $u, $s, $u }
+        impl_mut_int_slice! { $u, $s, $s }
     }
 }
 
-impl_int_slice!(u8,   i8)
-impl_int_slice!(u16,  i16)
-impl_int_slice!(u32,  i32)
-impl_int_slice!(u64,  i64)
-impl_int_slice!(uint, int)
+impl_int_slice! { u8,   i8 }
+impl_int_slice! { u16,  i16 }
+impl_int_slice! { u32,  i32 }
+impl_int_slice! { u64,  i64 }
+impl_int_slice! { uint, int }
 
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 1a7467555a5..28110cf7b1a 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -174,18 +174,18 @@ impl<'a> Copy for Chars<'a> {}
 // Return the initial codepoint accumulator for the first byte.
 // The first byte is special, only want bottom 5 bits for width 2, 4 bits
 // for width 3, and 3 bits for width 4
-macro_rules! utf8_first_byte(
+macro_rules! utf8_first_byte {
     ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
-)
+}
 
 // return the value of $ch updated with continuation byte $byte
-macro_rules! utf8_acc_cont_byte(
+macro_rules! utf8_acc_cont_byte {
     ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & CONT_MASK) as u32)
-)
+}
 
-macro_rules! utf8_is_cont_byte(
+macro_rules! utf8_is_cont_byte {
     ($byte:expr) => (($byte & !CONT_MASK) == TAG_CONT_U8)
-)
+}
 
 #[inline]
 fn unwrap_or_0(opt: Option<&u8>) -> u8 {
@@ -959,7 +959,7 @@ pub fn is_utf16(v: &[u16]) -> bool {
     macro_rules! next ( ($ret:expr) => {
             match it.next() { Some(u) => *u, None => return $ret }
         }
-    )
+    );
     loop {
         let u = next!(true);
 
@@ -1660,10 +1660,10 @@ pub trait StrPrelude for Sized? {
     /// # #![feature(unboxed_closures)]
     ///
     /// # fn main() {
-    /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar")
+    /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar");
     /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_chars(x), "foo1bar")
-    /// assert_eq!("123foo1bar123".trim_chars(|&: c: char| c.is_numeric()), "foo1bar")
+    /// assert_eq!("12foo1bar12".trim_chars(x), "foo1bar");
+    /// assert_eq!("123foo1bar123".trim_chars(|&: c: char| c.is_numeric()), "foo1bar");
     /// # }
     /// ```
     fn trim_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
@@ -1680,10 +1680,10 @@ pub trait StrPrelude for Sized? {
     /// # #![feature(unboxed_closures)]
     ///
     /// # fn main() {
-    /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11")
+    /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11");
     /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_left_chars(x), "foo1bar12")
-    /// assert_eq!("123foo1bar123".trim_left_chars(|&: c: char| c.is_numeric()), "foo1bar123")
+    /// assert_eq!("12foo1bar12".trim_left_chars(x), "foo1bar12");
+    /// assert_eq!("123foo1bar123".trim_left_chars(|&: c: char| c.is_numeric()), "foo1bar123");
     /// # }
     /// ```
     fn trim_left_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
@@ -1700,10 +1700,10 @@ pub trait StrPrelude for Sized? {
     /// # #![feature(unboxed_closures)]
     ///
     /// # fn main() {
-    /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar")
+    /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar");
     /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_right_chars(x), "12foo1bar")
-    /// assert_eq!("123foo1bar123".trim_right_chars(|&: c: char| c.is_numeric()), "123foo1bar")
+    /// assert_eq!("12foo1bar12".trim_right_chars(x), "12foo1bar");
+    /// assert_eq!("123foo1bar123".trim_right_chars(|&: c: char| c.is_numeric()), "123foo1bar");
     /// # }
     /// ```
     fn trim_right_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
@@ -2059,7 +2059,7 @@ impl StrPrelude for str {
 
     #[inline]
     fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a> {
-        assert!(!sep.is_empty())
+        assert!(!sep.is_empty());
         MatchIndices {
             haystack: self,
             needle: sep,
diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs
index 0bcebe073a3..dbbbaa5892c 100644
--- a/src/libcoretest/iter.rs
+++ b/src/libcoretest/iter.rs
@@ -522,15 +522,15 @@ fn test_double_ended_chain() {
     let xs = [1i, 2, 3, 4, 5];
     let ys = [7i, 9, 11];
     let mut it = xs.iter().chain(ys.iter()).rev();
-    assert_eq!(it.next().unwrap(), &11)
-    assert_eq!(it.next().unwrap(), &9)
-    assert_eq!(it.next_back().unwrap(), &1)
-    assert_eq!(it.next_back().unwrap(), &2)
-    assert_eq!(it.next_back().unwrap(), &3)
-    assert_eq!(it.next_back().unwrap(), &4)
-    assert_eq!(it.next_back().unwrap(), &5)
-    assert_eq!(it.next_back().unwrap(), &7)
-    assert_eq!(it.next_back(), None)
+    assert_eq!(it.next().unwrap(), &11);
+    assert_eq!(it.next().unwrap(), &9);
+    assert_eq!(it.next_back().unwrap(), &1);
+    assert_eq!(it.next_back().unwrap(), &2);
+    assert_eq!(it.next_back().unwrap(), &3);
+    assert_eq!(it.next_back().unwrap(), &4);
+    assert_eq!(it.next_back().unwrap(), &5);
+    assert_eq!(it.next_back().unwrap(), &7);
+    assert_eq!(it.next_back(), None);
 }
 
 #[test]
@@ -800,7 +800,7 @@ fn test_min_max() {
 #[test]
 fn test_min_max_result() {
     let r: MinMaxResult = NoElements;
-    assert_eq!(r.into_option(), None)
+    assert_eq!(r.into_option(), None);
 
     let r = OneElement(1i);
     assert_eq!(r.into_option(), Some((1,1)));
diff --git a/src/libcoretest/num/i16.rs b/src/libcoretest/num/i16.rs
index f3c2d67cdeb..7435831ac6d 100644
--- a/src/libcoretest/num/i16.rs
+++ b/src/libcoretest/num/i16.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-int_module!(i16, i16)
+int_module!(i16, i16);
diff --git a/src/libcoretest/num/i32.rs b/src/libcoretest/num/i32.rs
index 7232fc7505d..3b3407e1ada 100644
--- a/src/libcoretest/num/i32.rs
+++ b/src/libcoretest/num/i32.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-int_module!(i32, i32)
+int_module!(i32, i32);
diff --git a/src/libcoretest/num/i64.rs b/src/libcoretest/num/i64.rs
index 075b8448f35..9e1aec256ee 100644
--- a/src/libcoretest/num/i64.rs
+++ b/src/libcoretest/num/i64.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-int_module!(i64, i64)
+int_module!(i64, i64);
diff --git a/src/libcoretest/num/i8.rs b/src/libcoretest/num/i8.rs
index 9e0439f2818..f72244239b2 100644
--- a/src/libcoretest/num/i8.rs
+++ b/src/libcoretest/num/i8.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-int_module!(i8, i8)
+int_module!(i8, i8);
diff --git a/src/libcoretest/num/int.rs b/src/libcoretest/num/int.rs
index f01ec3f0310..be8dfd02ee1 100644
--- a/src/libcoretest/num/int.rs
+++ b/src/libcoretest/num/int.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-int_module!(int, int)
+int_module!(int, int);
diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs
index 87e2fe75299..55e0f10c865 100644
--- a/src/libcoretest/num/int_macros.rs
+++ b/src/libcoretest/num/int_macros.rs
@@ -202,4 +202,4 @@ mod tests {
     }
 }
 
-))
+));
diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs
index b7f8b81f996..acc593d7be9 100644
--- a/src/libcoretest/num/mod.rs
+++ b/src/libcoretest/num/mod.rs
@@ -62,9 +62,9 @@ mod test {
         let s : Option = from_str_radix("80000", 10);
         assert_eq!(s, None);
         let f : Option = from_str_radix("10000000000000000000000000000000000000000", 10);
-        assert_eq!(f, Some(Float::infinity()))
+        assert_eq!(f, Some(Float::infinity()));
         let fe : Option = from_str_radix("1e40", 10);
-        assert_eq!(fe, Some(Float::infinity()))
+        assert_eq!(fe, Some(Float::infinity()));
     }
 
     #[test]
diff --git a/src/libcoretest/num/u16.rs b/src/libcoretest/num/u16.rs
index d6aa6476678..8455207583c 100644
--- a/src/libcoretest/num/u16.rs
+++ b/src/libcoretest/num/u16.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-uint_module!(u16, u16)
+uint_module!(u16, u16);
diff --git a/src/libcoretest/num/u32.rs b/src/libcoretest/num/u32.rs
index 218e79df5ae..b44e60f6529 100644
--- a/src/libcoretest/num/u32.rs
+++ b/src/libcoretest/num/u32.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-uint_module!(u32, u32)
+uint_module!(u32, u32);
diff --git a/src/libcoretest/num/u64.rs b/src/libcoretest/num/u64.rs
index f78d4813503..ffcd1015d58 100644
--- a/src/libcoretest/num/u64.rs
+++ b/src/libcoretest/num/u64.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-uint_module!(u64, u64)
+uint_module!(u64, u64);
diff --git a/src/libcoretest/num/u8.rs b/src/libcoretest/num/u8.rs
index bb08072320b..4ee14e22f2d 100644
--- a/src/libcoretest/num/u8.rs
+++ b/src/libcoretest/num/u8.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-uint_module!(u8, u8)
+uint_module!(u8, u8);
diff --git a/src/libcoretest/num/uint.rs b/src/libcoretest/num/uint.rs
index 0db865f4cde..395e55cf255 100644
--- a/src/libcoretest/num/uint.rs
+++ b/src/libcoretest/num/uint.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-uint_module!(uint, uint)
+uint_module!(uint, uint);
diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs
index 5657a43de19..b21ac11e6a0 100644
--- a/src/libcoretest/num/uint_macros.rs
+++ b/src/libcoretest/num/uint_macros.rs
@@ -124,4 +124,4 @@ mod tests {
         assert!(5u.checked_div(0) == None);
     }
 }
-))
+));
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index 976b9bcf37e..257ce79b588 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -213,9 +213,11 @@ pub const WARN: u32 = 2;
 /// Error log level
 pub const ERROR: u32 = 1;
 
-thread_local!(static LOCAL_LOGGER: RefCell>> = {
-    RefCell::new(None)
-})
+thread_local! {
+    static LOCAL_LOGGER: RefCell>> = {
+        RefCell::new(None)
+    }
+}
 
 /// A trait used to represent an interface to a task-local logger. Each task
 /// can have its own custom logger which can respond to logging messages
diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs
index 4f8837083ae..8b2cfcd420a 100644
--- a/src/liblog/macros.rs
+++ b/src/liblog/macros.rs
@@ -51,7 +51,7 @@
 /// 6:main: this is a custom logging level: 6
 /// ```
 #[macro_export]
-macro_rules! log(
+macro_rules! log {
     ($lvl:expr, $($arg:tt)+) => ({
         static LOC: ::log::LogLocation = ::log::LogLocation {
             line: line!(),
@@ -63,7 +63,7 @@ macro_rules! log(
             format_args!(|args| { ::log::log(lvl, &LOC, args) }, $($arg)+)
         }
     })
-)
+}
 
 /// A convenience macro for logging at the error log level.
 ///
@@ -87,9 +87,9 @@ macro_rules! log(
 /// ```
 ///
 #[macro_export]
-macro_rules! error(
+macro_rules! error {
     ($($arg:tt)*) => (log!(::log::ERROR, $($arg)*))
-)
+}
 
 /// A convenience macro for logging at the warning log level.
 ///
@@ -112,9 +112,9 @@ macro_rules! error(
 /// WARN:main: you may like to know that a process exited with: 3
 /// ```
 #[macro_export]
-macro_rules! warn(
+macro_rules! warn {
     ($($arg:tt)*) => (log!(::log::WARN, $($arg)*))
-)
+}
 
 /// A convenience macro for logging at the info log level.
 ///
@@ -137,9 +137,9 @@ macro_rules! warn(
 /// INFO:main: this function is about to return: 3
 /// ```
 #[macro_export]
-macro_rules! info(
+macro_rules! info {
     ($($arg:tt)*) => (log!(::log::INFO, $($arg)*))
-)
+}
 
 /// A convenience macro for logging at the debug log level. This macro can also
 /// be omitted at compile time by passing `--cfg ndebug` to the compiler. If
@@ -163,9 +163,9 @@ macro_rules! info(
 /// DEBUG:main: x = 10, y = 20
 /// ```
 #[macro_export]
-macro_rules! debug(
+macro_rules! debug {
     ($($arg:tt)*) => (if cfg!(not(ndebug)) { log!(::log::DEBUG, $($arg)*) })
-)
+}
 
 /// A macro to test whether a log level is enabled for the current module.
 ///
@@ -197,11 +197,12 @@ macro_rules! debug(
 /// DEBUG:main: x.x = 1, x.y = 2
 /// ```
 #[macro_export]
-macro_rules! log_enabled(
+macro_rules! log_enabled {
     ($lvl:expr) => ({
         let lvl = $lvl;
         (lvl != ::log::DEBUG || cfg!(not(ndebug))) &&
         lvl <= ::log::log_level() &&
         ::log::mod_enabled(lvl, module_path!())
     })
-)
+}
+
diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs
index 2c1853b1951..2499d7f529f 100644
--- a/src/librand/isaac.rs
+++ b/src/librand/isaac.rs
@@ -434,7 +434,7 @@ impl Rng for Isaac64Rng {
 
         // See corresponding location in IsaacRng.next_u32 for
         // explanation.
-        debug_assert!(self.cnt < RAND_SIZE_64)
+        debug_assert!(self.cnt < RAND_SIZE_64);
         self.rsl[(self.cnt % RAND_SIZE_64) as uint]
     }
 }
diff --git a/src/librand/rand_impls.rs b/src/librand/rand_impls.rs
index 96f40bcc156..3b38fde3884 100644
--- a/src/librand/rand_impls.rs
+++ b/src/librand/rand_impls.rs
@@ -232,8 +232,8 @@ mod tests {
     #[test]
     fn floating_point_edge_cases() {
         // the test for exact equality is correct here.
-        assert!(ConstantRng(0xffff_ffff).gen::() != 1.0)
-        assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::() != 1.0)
+        assert!(ConstantRng(0xffff_ffff).gen::() != 1.0);
+        assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::() != 1.0);
     }
 
     #[test]
diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs
index bbedbc75395..bb7af92eb54 100644
--- a/src/librbml/lib.rs
+++ b/src/librbml/lib.rs
@@ -139,7 +139,7 @@ pub mod reader {
     pub type DecodeResult = Result;
     // rbml reading
 
-    macro_rules! try_or(
+    macro_rules! try_or {
         ($e:expr, $r:expr) => (
             match $e {
                 Ok(e) => e,
@@ -149,7 +149,7 @@ pub mod reader {
                 }
             }
         )
-    )
+    }
 
     pub struct Res {
         pub val: uint,
diff --git a/src/libregex/parse.rs b/src/libregex/parse.rs
index f9ae4d2591a..60cf45aeddc 100644
--- a/src/libregex/parse.rs
+++ b/src/libregex/parse.rs
@@ -224,7 +224,7 @@ impl<'a> Parser<'a> {
                 },
                 '(' => {
                     if self.peek_is(1, '?') {
-                        try!(self.expect('?'))
+                        try!(self.expect('?'));
                         try!(self.parse_group_opts())
                     } else {
                         self.caps += 1;
@@ -373,7 +373,7 @@ impl<'a> Parser<'a> {
     fn parse_class(&mut self) -> Result<(), Error> {
         let negated =
             if self.peek_is(1, '^') {
-                try!(self.expect('^'))
+                try!(self.expect('^'));
                 FLAG_NEGATED
             } else {
                 FLAG_EMPTY
@@ -597,7 +597,7 @@ impl<'a> Parser<'a> {
     // Parses all escape sequences.
     // Assumes that '\' is the current character.
     fn parse_escape(&mut self) -> Result {
-        try!(self.noteof("an escape sequence following a '\\'"))
+        try!(self.noteof("an escape sequence following a '\\'"));
 
         let c = self.cur();
         if is_punct(c) {
@@ -639,7 +639,7 @@ impl<'a> Parser<'a> {
         let negated = if self.cur() == 'P' { FLAG_NEGATED } else { FLAG_EMPTY };
         let mut name: String;
         if self.peek_is(1, '{') {
-            try!(self.expect('{'))
+            try!(self.expect('{'));
             let closer =
                 match self.pos('}') {
                     Some(i) => i,
@@ -677,10 +677,10 @@ impl<'a> Parser<'a> {
         let mut end = start + 1;
         let (d2, d3) = (self.peek(1), self.peek(2));
         if d2 >= Some('0') && d2 <= Some('7') {
-            try!(self.noteof("expected octal character in [0-7]"))
+            try!(self.noteof("expected octal character in [0-7]"));
             end += 1;
             if d3 >= Some('0') && d3 <= Some('7') {
-                try!(self.noteof("expected octal character in [0-7]"))
+                try!(self.noteof("expected octal character in [0-7]"));
                 end += 1;
             }
         }
@@ -698,7 +698,7 @@ impl<'a> Parser<'a> {
     // Assumes that \x has been read.
     fn parse_hex(&mut self) -> Result {
         if !self.peek_is(1, '{') {
-            try!(self.expect('{'))
+            try!(self.expect('{'));
             return self.parse_hex_two()
         }
         let start = self.chari + 2;
@@ -723,7 +723,7 @@ impl<'a> Parser<'a> {
         let (start, end) = (self.chari, self.chari + 2);
         let bad = self.slice(start - 2, self.chars.len());
         try!(self.noteof(format!("Invalid hex escape sequence '{}'",
-                                 bad).as_slice()))
+                                 bad).as_slice()));
         self.parse_hex_digits(self.slice(start, end).as_slice())
     }
 
@@ -743,7 +743,7 @@ impl<'a> Parser<'a> {
     // is '<'.
     // When done, parser will be at the closing '>' character.
     fn parse_named_capture(&mut self) -> Result<(), Error> {
-        try!(self.noteof("a capture name"))
+        try!(self.noteof("a capture name"));
         let closer =
             match self.pos('>') {
                 Some(i) => i,
@@ -773,7 +773,8 @@ impl<'a> Parser<'a> {
     // character.
     fn parse_group_opts(&mut self) -> Result<(), Error> {
         if self.peek_is(1, 'P') && self.peek_is(2, '<') {
-            try!(self.expect('P')) try!(self.expect('<'))
+            try!(self.expect('P'));
+            try!(self.expect('<'));
             return self.parse_named_capture()
         }
         let start = self.chari;
@@ -781,7 +782,8 @@ impl<'a> Parser<'a> {
         let mut sign = 1i;
         let mut saw_flag = false;
         loop {
-            try!(self.noteof("expected non-empty set of flags or closing ')'"))
+            try!(self.noteof(
+                    "expected non-empty set of flags or closing ')'"));
             match self.cur() {
                 'i' => { flags = flags | FLAG_NOCASE;     saw_flag = true},
                 'm' => { flags = flags | FLAG_MULTI;      saw_flag = true},
@@ -823,7 +825,7 @@ impl<'a> Parser<'a> {
     // If it is, then the next character is consumed.
     fn get_next_greedy(&mut self) -> Result {
         Ok(if self.peek_is(1, '?') {
-            try!(self.expect('?'))
+            try!(self.expect('?'));
             Ungreedy
         } else {
             Greedy
diff --git a/src/libregex/test/bench.rs b/src/libregex/test/bench.rs
index e1c24a902fa..0c204f759e6 100644
--- a/src/libregex/test/bench.rs
+++ b/src/libregex/test/bench.rs
@@ -137,7 +137,7 @@ fn one_pass_long_prefix_not(b: &mut Bencher) {
     b.iter(|| re.is_match(text));
 }
 
-macro_rules! throughput(
+macro_rules! throughput {
     ($name:ident, $regex:expr, $size:expr) => (
         #[bench]
         fn $name(b: &mut Bencher) {
@@ -146,7 +146,7 @@ macro_rules! throughput(
             b.iter(|| if $regex.is_match(text.as_slice()) { panic!("match") });
         }
     );
-)
+}
 
 fn easy0() -> Regex { regex!("ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
 fn easy1() -> Regex { regex!("A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$") }
@@ -165,18 +165,18 @@ fn gen_text(n: uint) -> String {
     String::from_utf8(bytes).unwrap()
 }
 
-throughput!(easy0_32, easy0(), 32)
-throughput!(easy0_1K, easy0(), 1<<10)
-throughput!(easy0_32K, easy0(), 32<<10)
+throughput!{easy0_32, easy0(), 32}
+throughput!{easy0_1K, easy0(), 1<<10}
+throughput!{easy0_32K, easy0(), 32<<10}
 
-throughput!(easy1_32, easy1(), 32)
-throughput!(easy1_1K, easy1(), 1<<10)
-throughput!(easy1_32K, easy1(), 32<<10)
+throughput!{easy1_32, easy1(), 32}
+throughput!{easy1_1K, easy1(), 1<<10}
+throughput!{easy1_32K, easy1(), 32<<10}
 
-throughput!(medium_32, medium(), 32)
-throughput!(medium_1K, medium(), 1<<10)
-throughput!(medium_32K,medium(), 32<<10)
+throughput!{medium_32, medium(), 32}
+throughput!{medium_1K, medium(), 1<<10}
+throughput!{medium_32K,medium(), 32<<10}
 
-throughput!(hard_32, hard(), 32)
-throughput!(hard_1K, hard(), 1<<10)
-throughput!(hard_32K,hard(), 32<<10)
+throughput!{hard_32, hard(), 32}
+throughput!{hard_1K, hard(), 1<<10}
+throughput!{hard_32K,hard(), 32<<10}
diff --git a/src/libregex/test/matches.rs b/src/libregex/test/matches.rs
index fb938513cb1..7508f4c50a2 100644
--- a/src/libregex/test/matches.rs
+++ b/src/libregex/test/matches.rs
@@ -14,360 +14,360 @@
 // on 2014-04-23 01:33:36.539280.
 
 // Tests from basic.dat
-mat!(match_basic_3, r"abracadabra$", r"abracadabracadabra", Some((7, 18)))
-mat!(match_basic_4, r"a...b", r"abababbb", Some((2, 7)))
-mat!(match_basic_5, r"XXXXXX", r"..XXXXXX", Some((2, 8)))
-mat!(match_basic_6, r"\)", r"()", Some((1, 2)))
-mat!(match_basic_7, r"a]", r"a]a", Some((0, 2)))
-mat!(match_basic_9, r"\}", r"}", Some((0, 1)))
-mat!(match_basic_10, r"\]", r"]", Some((0, 1)))
-mat!(match_basic_12, r"]", r"]", Some((0, 1)))
-mat!(match_basic_15, r"^a", r"ax", Some((0, 1)))
-mat!(match_basic_16, r"\^a", r"a^a", Some((1, 3)))
-mat!(match_basic_17, r"a\^", r"a^", Some((0, 2)))
-mat!(match_basic_18, r"a$", r"aa", Some((1, 2)))
-mat!(match_basic_19, r"a\$", r"a$", Some((0, 2)))
-mat!(match_basic_20, r"^$", r"", Some((0, 0)))
-mat!(match_basic_21, r"$^", r"", Some((0, 0)))
-mat!(match_basic_22, r"a($)", r"aa", Some((1, 2)), Some((2, 2)))
-mat!(match_basic_23, r"a*(^a)", r"aa", Some((0, 1)), Some((0, 1)))
-mat!(match_basic_24, r"(..)*(...)*", r"a", Some((0, 0)))
-mat!(match_basic_25, r"(..)*(...)*", r"abcd", Some((0, 4)), Some((2, 4)))
-mat!(match_basic_26, r"(ab|a)(bc|c)", r"abc", Some((0, 3)), Some((0, 2)), Some((2, 3)))
-mat!(match_basic_27, r"(ab)c|abc", r"abc", Some((0, 3)), Some((0, 2)))
-mat!(match_basic_28, r"a{0}b", r"ab", Some((1, 2)))
-mat!(match_basic_29, r"(a*)(b?)(b+)b{3}", r"aaabbbbbbb", Some((0, 10)), Some((0, 3)), Some((3, 4)), Some((4, 7)))
-mat!(match_basic_30, r"(a*)(b{0,1})(b{1,})b{3}", r"aaabbbbbbb", Some((0, 10)), Some((0, 3)), Some((3, 4)), Some((4, 7)))
-mat!(match_basic_32, r"((a|a)|a)", r"a", Some((0, 1)), Some((0, 1)), Some((0, 1)))
-mat!(match_basic_33, r"(a*)(a|aa)", r"aaaa", Some((0, 4)), Some((0, 3)), Some((3, 4)))
-mat!(match_basic_34, r"a*(a.|aa)", r"aaaa", Some((0, 4)), Some((2, 4)))
-mat!(match_basic_35, r"a(b)|c(d)|a(e)f", r"aef", Some((0, 3)), None, None, Some((1, 2)))
-mat!(match_basic_36, r"(a|b)?.*", r"b", Some((0, 1)), Some((0, 1)))
-mat!(match_basic_37, r"(a|b)c|a(b|c)", r"ac", Some((0, 2)), Some((0, 1)))
-mat!(match_basic_38, r"(a|b)c|a(b|c)", r"ab", Some((0, 2)), None, Some((1, 2)))
-mat!(match_basic_39, r"(a|b)*c|(a|ab)*c", r"abc", Some((0, 3)), Some((1, 2)))
-mat!(match_basic_40, r"(a|b)*c|(a|ab)*c", r"xc", Some((1, 2)))
-mat!(match_basic_41, r"(.a|.b).*|.*(.a|.b)", r"xa", Some((0, 2)), Some((0, 2)))
-mat!(match_basic_42, r"a?(ab|ba)ab", r"abab", Some((0, 4)), Some((0, 2)))
-mat!(match_basic_43, r"a?(ac{0}b|ba)ab", r"abab", Some((0, 4)), Some((0, 2)))
-mat!(match_basic_44, r"ab|abab", r"abbabab", Some((0, 2)))
-mat!(match_basic_45, r"aba|bab|bba", r"baaabbbaba", Some((5, 8)))
-mat!(match_basic_46, r"aba|bab", r"baaabbbaba", Some((6, 9)))
-mat!(match_basic_47, r"(aa|aaa)*|(a|aaaaa)", r"aa", Some((0, 2)), Some((0, 2)))
-mat!(match_basic_48, r"(a.|.a.)*|(a|.a...)", r"aa", Some((0, 2)), Some((0, 2)))
-mat!(match_basic_49, r"ab|a", r"xabc", Some((1, 3)))
-mat!(match_basic_50, r"ab|a", r"xxabc", Some((2, 4)))
-mat!(match_basic_51, r"(?i)(Ab|cD)*", r"aBcD", Some((0, 4)), Some((2, 4)))
-mat!(match_basic_52, r"[^-]", r"--a", Some((2, 3)))
-mat!(match_basic_53, r"[a-]*", r"--a", Some((0, 3)))
-mat!(match_basic_54, r"[a-m-]*", r"--amoma--", Some((0, 4)))
-mat!(match_basic_55, r":::1:::0:|:::1:1:0:", r":::0:::1:::1:::0:", Some((8, 17)))
-mat!(match_basic_56, r":::1:::0:|:::1:1:1:", r":::0:::1:::1:::0:", Some((8, 17)))
-mat!(match_basic_57, r"[[:upper:]]", r"A", Some((0, 1)))
-mat!(match_basic_58, r"[[:lower:]]+", r"`az{", Some((1, 3)))
-mat!(match_basic_59, r"[[:upper:]]+", r"@AZ[", Some((1, 3)))
-mat!(match_basic_65, r"
+mat!{match_basic_3, r"abracadabra$", r"abracadabracadabra", Some((7, 18))}
+mat!{match_basic_4, r"a...b", r"abababbb", Some((2, 7))}
+mat!{match_basic_5, r"XXXXXX", r"..XXXXXX", Some((2, 8))}
+mat!{match_basic_6, r"\)", r"()", Some((1, 2))}
+mat!{match_basic_7, r"a]", r"a]a", Some((0, 2))}
+mat!{match_basic_9, r"\}", r"}", Some((0, 1))}
+mat!{match_basic_10, r"\]", r"]", Some((0, 1))}
+mat!{match_basic_12, r"]", r"]", Some((0, 1))}
+mat!{match_basic_15, r"^a", r"ax", Some((0, 1))}
+mat!{match_basic_16, r"\^a", r"a^a", Some((1, 3))}
+mat!{match_basic_17, r"a\^", r"a^", Some((0, 2))}
+mat!{match_basic_18, r"a$", r"aa", Some((1, 2))}
+mat!{match_basic_19, r"a\$", r"a$", Some((0, 2))}
+mat!{match_basic_20, r"^$", r"", Some((0, 0))}
+mat!{match_basic_21, r"$^", r"", Some((0, 0))}
+mat!{match_basic_22, r"a($)", r"aa", Some((1, 2)), Some((2, 2))}
+mat!{match_basic_23, r"a*(^a)", r"aa", Some((0, 1)), Some((0, 1))}
+mat!{match_basic_24, r"(..)*(...)*", r"a", Some((0, 0))}
+mat!{match_basic_25, r"(..)*(...)*", r"abcd", Some((0, 4)), Some((2, 4))}
+mat!{match_basic_26, r"(ab|a)(bc|c)", r"abc", Some((0, 3)), Some((0, 2)), Some((2, 3))}
+mat!{match_basic_27, r"(ab)c|abc", r"abc", Some((0, 3)), Some((0, 2))}
+mat!{match_basic_28, r"a{0}b", r"ab", Some((1, 2))}
+mat!{match_basic_29, r"(a*)(b?)(b+)b{3}", r"aaabbbbbbb", Some((0, 10)), Some((0, 3)), Some((3, 4)), Some((4, 7))}
+mat!{match_basic_30, r"(a*)(b{0,1})(b{1,})b{3}", r"aaabbbbbbb", Some((0, 10)), Some((0, 3)), Some((3, 4)), Some((4, 7))}
+mat!{match_basic_32, r"((a|a)|a)", r"a", Some((0, 1)), Some((0, 1)), Some((0, 1))}
+mat!{match_basic_33, r"(a*)(a|aa)", r"aaaa", Some((0, 4)), Some((0, 3)), Some((3, 4))}
+mat!{match_basic_34, r"a*(a.|aa)", r"aaaa", Some((0, 4)), Some((2, 4))}
+mat!{match_basic_35, r"a(b)|c(d)|a(e)f", r"aef", Some((0, 3)), None, None, Some((1, 2))}
+mat!{match_basic_36, r"(a|b)?.*", r"b", Some((0, 1)), Some((0, 1))}
+mat!{match_basic_37, r"(a|b)c|a(b|c)", r"ac", Some((0, 2)), Some((0, 1))}
+mat!{match_basic_38, r"(a|b)c|a(b|c)", r"ab", Some((0, 2)), None, Some((1, 2))}
+mat!{match_basic_39, r"(a|b)*c|(a|ab)*c", r"abc", Some((0, 3)), Some((1, 2))}
+mat!{match_basic_40, r"(a|b)*c|(a|ab)*c", r"xc", Some((1, 2))}
+mat!{match_basic_41, r"(.a|.b).*|.*(.a|.b)", r"xa", Some((0, 2)), Some((0, 2))}
+mat!{match_basic_42, r"a?(ab|ba)ab", r"abab", Some((0, 4)), Some((0, 2))}
+mat!{match_basic_43, r"a?(ac{0}b|ba)ab", r"abab", Some((0, 4)), Some((0, 2))}
+mat!{match_basic_44, r"ab|abab", r"abbabab", Some((0, 2))}
+mat!{match_basic_45, r"aba|bab|bba", r"baaabbbaba", Some((5, 8))}
+mat!{match_basic_46, r"aba|bab", r"baaabbbaba", Some((6, 9))}
+mat!{match_basic_47, r"(aa|aaa)*|(a|aaaaa)", r"aa", Some((0, 2)), Some((0, 2))}
+mat!{match_basic_48, r"(a.|.a.)*|(a|.a...)", r"aa", Some((0, 2)), Some((0, 2))}
+mat!{match_basic_49, r"ab|a", r"xabc", Some((1, 3))}
+mat!{match_basic_50, r"ab|a", r"xxabc", Some((2, 4))}
+mat!{match_basic_51, r"(?i)(Ab|cD)*", r"aBcD", Some((0, 4)), Some((2, 4))}
+mat!{match_basic_52, r"[^-]", r"--a", Some((2, 3))}
+mat!{match_basic_53, r"[a-]*", r"--a", Some((0, 3))}
+mat!{match_basic_54, r"[a-m-]*", r"--amoma--", Some((0, 4))}
+mat!{match_basic_55, r":::1:::0:|:::1:1:0:", r":::0:::1:::1:::0:", Some((8, 17))}
+mat!{match_basic_56, r":::1:::0:|:::1:1:1:", r":::0:::1:::1:::0:", Some((8, 17))}
+mat!{match_basic_57, r"[[:upper:]]", r"A", Some((0, 1))}
+mat!{match_basic_58, r"[[:lower:]]+", r"`az{", Some((1, 3))}
+mat!{match_basic_59, r"[[:upper:]]+", r"@AZ[", Some((1, 3))}
+mat!{match_basic_65, r"
 ", r"
-", Some((0, 1)))
-mat!(match_basic_66, r"
+", Some((0, 1))}
+mat!{match_basic_66, r"
 ", r"
-", Some((0, 1)))
-mat!(match_basic_67, r"[^a]", r"
-", Some((0, 1)))
-mat!(match_basic_68, r"
+", Some((0, 1))}
+mat!{match_basic_67, r"[^a]", r"
+", Some((0, 1))}
+mat!{match_basic_68, r"
 a", r"
-a", Some((0, 2)))
-mat!(match_basic_69, r"(a)(b)(c)", r"abc", Some((0, 3)), Some((0, 1)), Some((1, 2)), Some((2, 3)))
-mat!(match_basic_70, r"xxx", r"xxx", Some((0, 3)))
-mat!(match_basic_71, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"feb 6,", Some((0, 6)))
-mat!(match_basic_72, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"2/7", Some((0, 3)))
-mat!(match_basic_73, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"feb 1,Feb 6", Some((5, 11)))
-mat!(match_basic_74, r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))", r"x", Some((0, 1)), Some((0, 1)), Some((0, 1)))
-mat!(match_basic_75, r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*", r"xx", Some((0, 2)), Some((1, 2)), Some((1, 2)))
-mat!(match_basic_76, r"a?(ab|ba)*", r"ababababababababababababababababababababababababababababababababababababababababa", Some((0, 81)), Some((79, 81)))
-mat!(match_basic_77, r"abaa|abbaa|abbbaa|abbbbaa", r"ababbabbbabbbabbbbabbbbaa", Some((18, 25)))
-mat!(match_basic_78, r"abaa|abbaa|abbbaa|abbbbaa", r"ababbabbbabbbabbbbabaa", Some((18, 22)))
-mat!(match_basic_79, r"aaac|aabc|abac|abbc|baac|babc|bbac|bbbc", r"baaabbbabac", Some((7, 11)))
-mat!(match_basic_80, r".*", r"", Some((0, 2)))
-mat!(match_basic_81, r"aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll", r"XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa", Some((53, 57)))
-mat!(match_basic_83, r"a*a*a*a*a*b", r"aaaaaaaaab", Some((0, 10)))
-mat!(match_basic_84, r"^", r"", Some((0, 0)))
-mat!(match_basic_85, r"$", r"", Some((0, 0)))
-mat!(match_basic_86, r"^$", r"", Some((0, 0)))
-mat!(match_basic_87, r"^a$", r"a", Some((0, 1)))
-mat!(match_basic_88, r"abc", r"abc", Some((0, 3)))
-mat!(match_basic_89, r"abc", r"xabcy", Some((1, 4)))
-mat!(match_basic_90, r"abc", r"ababc", Some((2, 5)))
-mat!(match_basic_91, r"ab*c", r"abc", Some((0, 3)))
-mat!(match_basic_92, r"ab*bc", r"abc", Some((0, 3)))
-mat!(match_basic_93, r"ab*bc", r"abbc", Some((0, 4)))
-mat!(match_basic_94, r"ab*bc", r"abbbbc", Some((0, 6)))
-mat!(match_basic_95, r"ab+bc", r"abbc", Some((0, 4)))
-mat!(match_basic_96, r"ab+bc", r"abbbbc", Some((0, 6)))
-mat!(match_basic_97, r"ab?bc", r"abbc", Some((0, 4)))
-mat!(match_basic_98, r"ab?bc", r"abc", Some((0, 3)))
-mat!(match_basic_99, r"ab?c", r"abc", Some((0, 3)))
-mat!(match_basic_100, r"^abc$", r"abc", Some((0, 3)))
-mat!(match_basic_101, r"^abc", r"abcc", Some((0, 3)))
-mat!(match_basic_102, r"abc$", r"aabc", Some((1, 4)))
-mat!(match_basic_103, r"^", r"abc", Some((0, 0)))
-mat!(match_basic_104, r"$", r"abc", Some((3, 3)))
-mat!(match_basic_105, r"a.c", r"abc", Some((0, 3)))
-mat!(match_basic_106, r"a.c", r"axc", Some((0, 3)))
-mat!(match_basic_107, r"a.*c", r"axyzc", Some((0, 5)))
-mat!(match_basic_108, r"a[bc]d", r"abd", Some((0, 3)))
-mat!(match_basic_109, r"a[b-d]e", r"ace", Some((0, 3)))
-mat!(match_basic_110, r"a[b-d]", r"aac", Some((1, 3)))
-mat!(match_basic_111, r"a[-b]", r"a-", Some((0, 2)))
-mat!(match_basic_112, r"a[b-]", r"a-", Some((0, 2)))
-mat!(match_basic_113, r"a]", r"a]", Some((0, 2)))
-mat!(match_basic_114, r"a[]]b", r"a]b", Some((0, 3)))
-mat!(match_basic_115, r"a[^bc]d", r"aed", Some((0, 3)))
-mat!(match_basic_116, r"a[^-b]c", r"adc", Some((0, 3)))
-mat!(match_basic_117, r"a[^]b]c", r"adc", Some((0, 3)))
-mat!(match_basic_118, r"ab|cd", r"abc", Some((0, 2)))
-mat!(match_basic_119, r"ab|cd", r"abcd", Some((0, 2)))
-mat!(match_basic_120, r"a\(b", r"a(b", Some((0, 3)))
-mat!(match_basic_121, r"a\(*b", r"ab", Some((0, 2)))
-mat!(match_basic_122, r"a\(*b", r"a((b", Some((0, 4)))
-mat!(match_basic_123, r"((a))", r"abc", Some((0, 1)), Some((0, 1)), Some((0, 1)))
-mat!(match_basic_124, r"(a)b(c)", r"abc", Some((0, 3)), Some((0, 1)), Some((2, 3)))
-mat!(match_basic_125, r"a+b+c", r"aabbabc", Some((4, 7)))
-mat!(match_basic_126, r"a*", r"aaa", Some((0, 3)))
-mat!(match_basic_128, r"(a*)*", r"-", Some((0, 0)), None)
-mat!(match_basic_129, r"(a*)+", r"-", Some((0, 0)), Some((0, 0)))
-mat!(match_basic_131, r"(a*|b)*", r"-", Some((0, 0)), None)
-mat!(match_basic_132, r"(a+|b)*", r"ab", Some((0, 2)), Some((1, 2)))
-mat!(match_basic_133, r"(a+|b)+", r"ab", Some((0, 2)), Some((1, 2)))
-mat!(match_basic_134, r"(a+|b)?", r"ab", Some((0, 1)), Some((0, 1)))
-mat!(match_basic_135, r"[^ab]*", r"cde", Some((0, 3)))
-mat!(match_basic_137, r"(^)*", r"-", Some((0, 0)), None)
-mat!(match_basic_138, r"a*", r"", Some((0, 0)))
-mat!(match_basic_139, r"([abc])*d", r"abbbcd", Some((0, 6)), Some((4, 5)))
-mat!(match_basic_140, r"([abc])*bcd", r"abcd", Some((0, 4)), Some((0, 1)))
-mat!(match_basic_141, r"a|b|c|d|e", r"e", Some((0, 1)))
-mat!(match_basic_142, r"(a|b|c|d|e)f", r"ef", Some((0, 2)), Some((0, 1)))
-mat!(match_basic_144, r"((a*|b))*", r"-", Some((0, 0)), None, None)
-mat!(match_basic_145, r"abcd*efg", r"abcdefg", Some((0, 7)))
-mat!(match_basic_146, r"ab*", r"xabyabbbz", Some((1, 3)))
-mat!(match_basic_147, r"ab*", r"xayabbbz", Some((1, 2)))
-mat!(match_basic_148, r"(ab|cd)e", r"abcde", Some((2, 5)), Some((2, 4)))
-mat!(match_basic_149, r"[abhgefdc]ij", r"hij", Some((0, 3)))
-mat!(match_basic_150, r"(a|b)c*d", r"abcd", Some((1, 4)), Some((1, 2)))
-mat!(match_basic_151, r"(ab|ab*)bc", r"abc", Some((0, 3)), Some((0, 1)))
-mat!(match_basic_152, r"a([bc]*)c*", r"abc", Some((0, 3)), Some((1, 3)))
-mat!(match_basic_153, r"a([bc]*)(c*d)", r"abcd", Some((0, 4)), Some((1, 3)), Some((3, 4)))
-mat!(match_basic_154, r"a([bc]+)(c*d)", r"abcd", Some((0, 4)), Some((1, 3)), Some((3, 4)))
-mat!(match_basic_155, r"a([bc]*)(c+d)", r"abcd", Some((0, 4)), Some((1, 2)), Some((2, 4)))
-mat!(match_basic_156, r"a[bcd]*dcdcde", r"adcdcde", Some((0, 7)))
-mat!(match_basic_157, r"(ab|a)b*c", r"abc", Some((0, 3)), Some((0, 2)))
-mat!(match_basic_158, r"((a)(b)c)(d)", r"abcd", Some((0, 4)), Some((0, 3)), Some((0, 1)), Some((1, 2)), Some((3, 4)))
-mat!(match_basic_159, r"[A-Za-z_][A-Za-z0-9_]*", r"alpha", Some((0, 5)))
-mat!(match_basic_160, r"^a(bc+|b[eh])g|.h$", r"abh", Some((1, 3)))
-mat!(match_basic_161, r"(bc+d$|ef*g.|h?i(j|k))", r"effgz", Some((0, 5)), Some((0, 5)))
-mat!(match_basic_162, r"(bc+d$|ef*g.|h?i(j|k))", r"ij", Some((0, 2)), Some((0, 2)), Some((1, 2)))
-mat!(match_basic_163, r"(bc+d$|ef*g.|h?i(j|k))", r"reffgz", Some((1, 6)), Some((1, 6)))
-mat!(match_basic_164, r"(((((((((a)))))))))", r"a", Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)))
-mat!(match_basic_165, r"multiple words", r"multiple words yeah", Some((0, 14)))
-mat!(match_basic_166, r"(.*)c(.*)", r"abcde", Some((0, 5)), Some((0, 2)), Some((3, 5)))
-mat!(match_basic_167, r"abcd", r"abcd", Some((0, 4)))
-mat!(match_basic_168, r"a(bc)d", r"abcd", Some((0, 4)), Some((1, 3)))
-mat!(match_basic_169, r"a[-]?c", r"ac", Some((0, 3)))
-mat!(match_basic_170, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Qaddafi", Some((0, 15)), None, Some((10, 12)))
-mat!(match_basic_171, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mo'ammar Gadhafi", Some((0, 16)), None, Some((11, 13)))
-mat!(match_basic_172, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Kaddafi", Some((0, 15)), None, Some((10, 12)))
-mat!(match_basic_173, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Qadhafi", Some((0, 15)), None, Some((10, 12)))
-mat!(match_basic_174, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Gadafi", Some((0, 14)), None, Some((10, 11)))
-mat!(match_basic_175, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mu'ammar Qadafi", Some((0, 15)), None, Some((11, 12)))
-mat!(match_basic_176, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moamar Gaddafi", Some((0, 14)), None, Some((9, 11)))
-mat!(match_basic_177, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mu'ammar Qadhdhafi", Some((0, 18)), None, Some((13, 15)))
-mat!(match_basic_178, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Khaddafi", Some((0, 16)), None, Some((11, 13)))
-mat!(match_basic_179, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghaddafy", Some((0, 16)), None, Some((11, 13)))
-mat!(match_basic_180, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghadafi", Some((0, 15)), None, Some((11, 12)))
-mat!(match_basic_181, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghaddafi", Some((0, 16)), None, Some((11, 13)))
-mat!(match_basic_182, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muamar Kaddafi", Some((0, 14)), None, Some((9, 11)))
-mat!(match_basic_183, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Quathafi", Some((0, 16)), None, Some((11, 13)))
-mat!(match_basic_184, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Gheddafi", Some((0, 16)), None, Some((11, 13)))
-mat!(match_basic_185, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moammar Khadafy", Some((0, 15)), None, Some((11, 12)))
-mat!(match_basic_186, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moammar Qudhafi", Some((0, 15)), None, Some((10, 12)))
-mat!(match_basic_187, r"a+(b|c)*d+", r"aabcdd", Some((0, 6)), Some((3, 4)))
-mat!(match_basic_188, r"^.+$", r"vivi", Some((0, 4)))
-mat!(match_basic_189, r"^(.+)$", r"vivi", Some((0, 4)), Some((0, 4)))
-mat!(match_basic_190, r"^([^!.]+).att.com!(.+)$", r"gryphon.att.com!eby", Some((0, 19)), Some((0, 7)), Some((16, 19)))
-mat!(match_basic_191, r"^([^!]+!)?([^!]+)$", r"bas", Some((0, 3)), None, Some((0, 3)))
-mat!(match_basic_192, r"^([^!]+!)?([^!]+)$", r"bar!bas", Some((0, 7)), Some((0, 4)), Some((4, 7)))
-mat!(match_basic_193, r"^([^!]+!)?([^!]+)$", r"foo!bas", Some((0, 7)), Some((0, 4)), Some((4, 7)))
-mat!(match_basic_194, r"^.+!([^!]+!)([^!]+)$", r"foo!bar!bas", Some((0, 11)), Some((4, 8)), Some((8, 11)))
-mat!(match_basic_195, r"((foo)|(bar))!bas", r"bar!bas", Some((0, 7)), Some((0, 3)), None, Some((0, 3)))
-mat!(match_basic_196, r"((foo)|(bar))!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)), None, Some((4, 7)))
-mat!(match_basic_197, r"((foo)|(bar))!bas", r"foo!bas", Some((0, 7)), Some((0, 3)), Some((0, 3)))
-mat!(match_basic_198, r"((foo)|bar)!bas", r"bar!bas", Some((0, 7)), Some((0, 3)))
-mat!(match_basic_199, r"((foo)|bar)!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)))
-mat!(match_basic_200, r"((foo)|bar)!bas", r"foo!bas", Some((0, 7)), Some((0, 3)), Some((0, 3)))
-mat!(match_basic_201, r"(foo|(bar))!bas", r"bar!bas", Some((0, 7)), Some((0, 3)), Some((0, 3)))
-mat!(match_basic_202, r"(foo|(bar))!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)), Some((4, 7)))
-mat!(match_basic_203, r"(foo|(bar))!bas", r"foo!bas", Some((0, 7)), Some((0, 3)))
-mat!(match_basic_204, r"(foo|bar)!bas", r"bar!bas", Some((0, 7)), Some((0, 3)))
-mat!(match_basic_205, r"(foo|bar)!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)))
-mat!(match_basic_206, r"(foo|bar)!bas", r"foo!bas", Some((0, 7)), Some((0, 3)))
-mat!(match_basic_207, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bar!bas", Some((0, 11)), Some((0, 11)), None, None, Some((4, 8)), Some((8, 11)))
-mat!(match_basic_208, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"bas", Some((0, 3)), None, Some((0, 3)))
-mat!(match_basic_209, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"bar!bas", Some((0, 7)), Some((0, 4)), Some((4, 7)))
-mat!(match_basic_210, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"foo!bar!bas", Some((0, 11)), None, None, Some((4, 8)), Some((8, 11)))
-mat!(match_basic_211, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"foo!bas", Some((0, 7)), Some((0, 4)), Some((4, 7)))
-mat!(match_basic_212, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"bas", Some((0, 3)), Some((0, 3)), None, Some((0, 3)))
-mat!(match_basic_213, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"bar!bas", Some((0, 7)), Some((0, 7)), Some((0, 4)), Some((4, 7)))
-mat!(match_basic_214, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bar!bas", Some((0, 11)), Some((0, 11)), None, None, Some((4, 8)), Some((8, 11)))
-mat!(match_basic_215, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bas", Some((0, 7)), Some((0, 7)), Some((0, 4)), Some((4, 7)))
-mat!(match_basic_216, r".*(/XXX).*", r"/XXX", Some((0, 4)), Some((0, 4)))
-mat!(match_basic_217, r".*(\\XXX).*", r"\XXX", Some((0, 4)), Some((0, 4)))
-mat!(match_basic_218, r"\\XXX", r"\XXX", Some((0, 4)))
-mat!(match_basic_219, r".*(/000).*", r"/000", Some((0, 4)), Some((0, 4)))
-mat!(match_basic_220, r".*(\\000).*", r"\000", Some((0, 4)), Some((0, 4)))
-mat!(match_basic_221, r"\\000", r"\000", Some((0, 4)))
+a", Some((0, 2))}
+mat!{match_basic_69, r"(a)(b)(c)", r"abc", Some((0, 3)), Some((0, 1)), Some((1, 2)), Some((2, 3))}
+mat!{match_basic_70, r"xxx", r"xxx", Some((0, 3))}
+mat!{match_basic_71, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"feb 6,", Some((0, 6))}
+mat!{match_basic_72, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"2/7", Some((0, 3))}
+mat!{match_basic_73, r"(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)", r"feb 1,Feb 6", Some((5, 11))}
+mat!{match_basic_74, r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))", r"x", Some((0, 1)), Some((0, 1)), Some((0, 1))}
+mat!{match_basic_75, r"((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*", r"xx", Some((0, 2)), Some((1, 2)), Some((1, 2))}
+mat!{match_basic_76, r"a?(ab|ba)*", r"ababababababababababababababababababababababababababababababababababababababababa", Some((0, 81)), Some((79, 81))}
+mat!{match_basic_77, r"abaa|abbaa|abbbaa|abbbbaa", r"ababbabbbabbbabbbbabbbbaa", Some((18, 25))}
+mat!{match_basic_78, r"abaa|abbaa|abbbaa|abbbbaa", r"ababbabbbabbbabbbbabaa", Some((18, 22))}
+mat!{match_basic_79, r"aaac|aabc|abac|abbc|baac|babc|bbac|bbbc", r"baaabbbabac", Some((7, 11))}
+mat!{match_basic_80, r".*", r"", Some((0, 2))}
+mat!{match_basic_81, r"aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll", r"XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa", Some((53, 57))}
+mat!{match_basic_83, r"a*a*a*a*a*b", r"aaaaaaaaab", Some((0, 10))}
+mat!{match_basic_84, r"^", r"", Some((0, 0))}
+mat!{match_basic_85, r"$", r"", Some((0, 0))}
+mat!{match_basic_86, r"^$", r"", Some((0, 0))}
+mat!{match_basic_87, r"^a$", r"a", Some((0, 1))}
+mat!{match_basic_88, r"abc", r"abc", Some((0, 3))}
+mat!{match_basic_89, r"abc", r"xabcy", Some((1, 4))}
+mat!{match_basic_90, r"abc", r"ababc", Some((2, 5))}
+mat!{match_basic_91, r"ab*c", r"abc", Some((0, 3))}
+mat!{match_basic_92, r"ab*bc", r"abc", Some((0, 3))}
+mat!{match_basic_93, r"ab*bc", r"abbc", Some((0, 4))}
+mat!{match_basic_94, r"ab*bc", r"abbbbc", Some((0, 6))}
+mat!{match_basic_95, r"ab+bc", r"abbc", Some((0, 4))}
+mat!{match_basic_96, r"ab+bc", r"abbbbc", Some((0, 6))}
+mat!{match_basic_97, r"ab?bc", r"abbc", Some((0, 4))}
+mat!{match_basic_98, r"ab?bc", r"abc", Some((0, 3))}
+mat!{match_basic_99, r"ab?c", r"abc", Some((0, 3))}
+mat!{match_basic_100, r"^abc$", r"abc", Some((0, 3))}
+mat!{match_basic_101, r"^abc", r"abcc", Some((0, 3))}
+mat!{match_basic_102, r"abc$", r"aabc", Some((1, 4))}
+mat!{match_basic_103, r"^", r"abc", Some((0, 0))}
+mat!{match_basic_104, r"$", r"abc", Some((3, 3))}
+mat!{match_basic_105, r"a.c", r"abc", Some((0, 3))}
+mat!{match_basic_106, r"a.c", r"axc", Some((0, 3))}
+mat!{match_basic_107, r"a.*c", r"axyzc", Some((0, 5))}
+mat!{match_basic_108, r"a[bc]d", r"abd", Some((0, 3))}
+mat!{match_basic_109, r"a[b-d]e", r"ace", Some((0, 3))}
+mat!{match_basic_110, r"a[b-d]", r"aac", Some((1, 3))}
+mat!{match_basic_111, r"a[-b]", r"a-", Some((0, 2))}
+mat!{match_basic_112, r"a[b-]", r"a-", Some((0, 2))}
+mat!{match_basic_113, r"a]", r"a]", Some((0, 2))}
+mat!{match_basic_114, r"a[]]b", r"a]b", Some((0, 3))}
+mat!{match_basic_115, r"a[^bc]d", r"aed", Some((0, 3))}
+mat!{match_basic_116, r"a[^-b]c", r"adc", Some((0, 3))}
+mat!{match_basic_117, r"a[^]b]c", r"adc", Some((0, 3))}
+mat!{match_basic_118, r"ab|cd", r"abc", Some((0, 2))}
+mat!{match_basic_119, r"ab|cd", r"abcd", Some((0, 2))}
+mat!{match_basic_120, r"a\(b", r"a(b", Some((0, 3))}
+mat!{match_basic_121, r"a\(*b", r"ab", Some((0, 2))}
+mat!{match_basic_122, r"a\(*b", r"a((b", Some((0, 4))}
+mat!{match_basic_123, r"((a))", r"abc", Some((0, 1)), Some((0, 1)), Some((0, 1))}
+mat!{match_basic_124, r"(a)b(c)", r"abc", Some((0, 3)), Some((0, 1)), Some((2, 3))}
+mat!{match_basic_125, r"a+b+c", r"aabbabc", Some((4, 7))}
+mat!{match_basic_126, r"a*", r"aaa", Some((0, 3))}
+mat!{match_basic_128, r"(a*)*", r"-", Some((0, 0)), None}
+mat!{match_basic_129, r"(a*)+", r"-", Some((0, 0)), Some((0, 0))}
+mat!{match_basic_131, r"(a*|b)*", r"-", Some((0, 0)), None}
+mat!{match_basic_132, r"(a+|b)*", r"ab", Some((0, 2)), Some((1, 2))}
+mat!{match_basic_133, r"(a+|b)+", r"ab", Some((0, 2)), Some((1, 2))}
+mat!{match_basic_134, r"(a+|b)?", r"ab", Some((0, 1)), Some((0, 1))}
+mat!{match_basic_135, r"[^ab]*", r"cde", Some((0, 3))}
+mat!{match_basic_137, r"(^)*", r"-", Some((0, 0)), None}
+mat!{match_basic_138, r"a*", r"", Some((0, 0))}
+mat!{match_basic_139, r"([abc])*d", r"abbbcd", Some((0, 6)), Some((4, 5))}
+mat!{match_basic_140, r"([abc])*bcd", r"abcd", Some((0, 4)), Some((0, 1))}
+mat!{match_basic_141, r"a|b|c|d|e", r"e", Some((0, 1))}
+mat!{match_basic_142, r"(a|b|c|d|e)f", r"ef", Some((0, 2)), Some((0, 1))}
+mat!{match_basic_144, r"((a*|b))*", r"-", Some((0, 0)), None, None}
+mat!{match_basic_145, r"abcd*efg", r"abcdefg", Some((0, 7))}
+mat!{match_basic_146, r"ab*", r"xabyabbbz", Some((1, 3))}
+mat!{match_basic_147, r"ab*", r"xayabbbz", Some((1, 2))}
+mat!{match_basic_148, r"(ab|cd)e", r"abcde", Some((2, 5)), Some((2, 4))}
+mat!{match_basic_149, r"[abhgefdc]ij", r"hij", Some((0, 3))}
+mat!{match_basic_150, r"(a|b)c*d", r"abcd", Some((1, 4)), Some((1, 2))}
+mat!{match_basic_151, r"(ab|ab*)bc", r"abc", Some((0, 3)), Some((0, 1))}
+mat!{match_basic_152, r"a([bc]*)c*", r"abc", Some((0, 3)), Some((1, 3))}
+mat!{match_basic_153, r"a([bc]*)(c*d)", r"abcd", Some((0, 4)), Some((1, 3)), Some((3, 4))}
+mat!{match_basic_154, r"a([bc]+)(c*d)", r"abcd", Some((0, 4)), Some((1, 3)), Some((3, 4))}
+mat!{match_basic_155, r"a([bc]*)(c+d)", r"abcd", Some((0, 4)), Some((1, 2)), Some((2, 4))}
+mat!{match_basic_156, r"a[bcd]*dcdcde", r"adcdcde", Some((0, 7))}
+mat!{match_basic_157, r"(ab|a)b*c", r"abc", Some((0, 3)), Some((0, 2))}
+mat!{match_basic_158, r"((a)(b)c)(d)", r"abcd", Some((0, 4)), Some((0, 3)), Some((0, 1)), Some((1, 2)), Some((3, 4))}
+mat!{match_basic_159, r"[A-Za-z_][A-Za-z0-9_]*", r"alpha", Some((0, 5))}
+mat!{match_basic_160, r"^a(bc+|b[eh])g|.h$", r"abh", Some((1, 3))}
+mat!{match_basic_161, r"(bc+d$|ef*g.|h?i(j|k))", r"effgz", Some((0, 5)), Some((0, 5))}
+mat!{match_basic_162, r"(bc+d$|ef*g.|h?i(j|k))", r"ij", Some((0, 2)), Some((0, 2)), Some((1, 2))}
+mat!{match_basic_163, r"(bc+d$|ef*g.|h?i(j|k))", r"reffgz", Some((1, 6)), Some((1, 6))}
+mat!{match_basic_164, r"(((((((((a)))))))))", r"a", Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1)), Some((0, 1))}
+mat!{match_basic_165, r"multiple words", r"multiple words yeah", Some((0, 14))}
+mat!{match_basic_166, r"(.*)c(.*)", r"abcde", Some((0, 5)), Some((0, 2)), Some((3, 5))}
+mat!{match_basic_167, r"abcd", r"abcd", Some((0, 4))}
+mat!{match_basic_168, r"a(bc)d", r"abcd", Some((0, 4)), Some((1, 3))}
+mat!{match_basic_169, r"a[-]?c", r"ac", Some((0, 3))}
+mat!{match_basic_170, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Qaddafi", Some((0, 15)), None, Some((10, 12))}
+mat!{match_basic_171, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mo'ammar Gadhafi", Some((0, 16)), None, Some((11, 13))}
+mat!{match_basic_172, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Kaddafi", Some((0, 15)), None, Some((10, 12))}
+mat!{match_basic_173, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Qadhafi", Some((0, 15)), None, Some((10, 12))}
+mat!{match_basic_174, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Gadafi", Some((0, 14)), None, Some((10, 11))}
+mat!{match_basic_175, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mu'ammar Qadafi", Some((0, 15)), None, Some((11, 12))}
+mat!{match_basic_176, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moamar Gaddafi", Some((0, 14)), None, Some((9, 11))}
+mat!{match_basic_177, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Mu'ammar Qadhdhafi", Some((0, 18)), None, Some((13, 15))}
+mat!{match_basic_178, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Khaddafi", Some((0, 16)), None, Some((11, 13))}
+mat!{match_basic_179, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghaddafy", Some((0, 16)), None, Some((11, 13))}
+mat!{match_basic_180, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghadafi", Some((0, 15)), None, Some((11, 12))}
+mat!{match_basic_181, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Ghaddafi", Some((0, 16)), None, Some((11, 13))}
+mat!{match_basic_182, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muamar Kaddafi", Some((0, 14)), None, Some((9, 11))}
+mat!{match_basic_183, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Quathafi", Some((0, 16)), None, Some((11, 13))}
+mat!{match_basic_184, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Muammar Gheddafi", Some((0, 16)), None, Some((11, 13))}
+mat!{match_basic_185, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moammar Khadafy", Some((0, 15)), None, Some((11, 12))}
+mat!{match_basic_186, r"M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]", r"Moammar Qudhafi", Some((0, 15)), None, Some((10, 12))}
+mat!{match_basic_187, r"a+(b|c)*d+", r"aabcdd", Some((0, 6)), Some((3, 4))}
+mat!{match_basic_188, r"^.+$", r"vivi", Some((0, 4))}
+mat!{match_basic_189, r"^(.+)$", r"vivi", Some((0, 4)), Some((0, 4))}
+mat!{match_basic_190, r"^([^!.]+).att.com!(.+)$", r"gryphon.att.com!eby", Some((0, 19)), Some((0, 7)), Some((16, 19))}
+mat!{match_basic_191, r"^([^!]+!)?([^!]+)$", r"bas", Some((0, 3)), None, Some((0, 3))}
+mat!{match_basic_192, r"^([^!]+!)?([^!]+)$", r"bar!bas", Some((0, 7)), Some((0, 4)), Some((4, 7))}
+mat!{match_basic_193, r"^([^!]+!)?([^!]+)$", r"foo!bas", Some((0, 7)), Some((0, 4)), Some((4, 7))}
+mat!{match_basic_194, r"^.+!([^!]+!)([^!]+)$", r"foo!bar!bas", Some((0, 11)), Some((4, 8)), Some((8, 11))}
+mat!{match_basic_195, r"((foo)|(bar))!bas", r"bar!bas", Some((0, 7)), Some((0, 3)), None, Some((0, 3))}
+mat!{match_basic_196, r"((foo)|(bar))!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)), None, Some((4, 7))}
+mat!{match_basic_197, r"((foo)|(bar))!bas", r"foo!bas", Some((0, 7)), Some((0, 3)), Some((0, 3))}
+mat!{match_basic_198, r"((foo)|bar)!bas", r"bar!bas", Some((0, 7)), Some((0, 3))}
+mat!{match_basic_199, r"((foo)|bar)!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7))}
+mat!{match_basic_200, r"((foo)|bar)!bas", r"foo!bas", Some((0, 7)), Some((0, 3)), Some((0, 3))}
+mat!{match_basic_201, r"(foo|(bar))!bas", r"bar!bas", Some((0, 7)), Some((0, 3)), Some((0, 3))}
+mat!{match_basic_202, r"(foo|(bar))!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7)), Some((4, 7))}
+mat!{match_basic_203, r"(foo|(bar))!bas", r"foo!bas", Some((0, 7)), Some((0, 3))}
+mat!{match_basic_204, r"(foo|bar)!bas", r"bar!bas", Some((0, 7)), Some((0, 3))}
+mat!{match_basic_205, r"(foo|bar)!bas", r"foo!bar!bas", Some((4, 11)), Some((4, 7))}
+mat!{match_basic_206, r"(foo|bar)!bas", r"foo!bas", Some((0, 7)), Some((0, 3))}
+mat!{match_basic_207, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bar!bas", Some((0, 11)), Some((0, 11)), None, None, Some((4, 8)), Some((8, 11))}
+mat!{match_basic_208, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"bas", Some((0, 3)), None, Some((0, 3))}
+mat!{match_basic_209, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"bar!bas", Some((0, 7)), Some((0, 4)), Some((4, 7))}
+mat!{match_basic_210, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"foo!bar!bas", Some((0, 11)), None, None, Some((4, 8)), Some((8, 11))}
+mat!{match_basic_211, r"^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$", r"foo!bas", Some((0, 7)), Some((0, 4)), Some((4, 7))}
+mat!{match_basic_212, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"bas", Some((0, 3)), Some((0, 3)), None, Some((0, 3))}
+mat!{match_basic_213, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"bar!bas", Some((0, 7)), Some((0, 7)), Some((0, 4)), Some((4, 7))}
+mat!{match_basic_214, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bar!bas", Some((0, 11)), Some((0, 11)), None, None, Some((4, 8)), Some((8, 11))}
+mat!{match_basic_215, r"^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$", r"foo!bas", Some((0, 7)), Some((0, 7)), Some((0, 4)), Some((4, 7))}
+mat!{match_basic_216, r".*(/XXX).*", r"/XXX", Some((0, 4)), Some((0, 4))}
+mat!{match_basic_217, r".*(\\XXX).*", r"\XXX", Some((0, 4)), Some((0, 4))}
+mat!{match_basic_218, r"\\XXX", r"\XXX", Some((0, 4))}
+mat!{match_basic_219, r".*(/000).*", r"/000", Some((0, 4)), Some((0, 4))}
+mat!{match_basic_220, r".*(\\000).*", r"\000", Some((0, 4)), Some((0, 4))}
+mat!{match_basic_221, r"\\000", r"\000", Some((0, 4))}
 
 // Tests from nullsubexpr.dat
-mat!(match_nullsubexpr_3, r"(a*)*", r"a", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_5, r"(a*)*", r"x", Some((0, 0)), None)
-mat!(match_nullsubexpr_6, r"(a*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_7, r"(a*)*", r"aaaaaax", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_8, r"(a*)+", r"a", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_9, r"(a*)+", r"x", Some((0, 0)), Some((0, 0)))
-mat!(match_nullsubexpr_10, r"(a*)+", r"aaaaaa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_11, r"(a*)+", r"aaaaaax", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_12, r"(a+)*", r"a", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_13, r"(a+)*", r"x", Some((0, 0)))
-mat!(match_nullsubexpr_14, r"(a+)*", r"aaaaaa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_15, r"(a+)*", r"aaaaaax", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_16, r"(a+)+", r"a", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_17, r"(a+)+", r"x", None)
-mat!(match_nullsubexpr_18, r"(a+)+", r"aaaaaa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_19, r"(a+)+", r"aaaaaax", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_21, r"([a]*)*", r"a", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_23, r"([a]*)*", r"x", Some((0, 0)), None)
-mat!(match_nullsubexpr_24, r"([a]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_25, r"([a]*)*", r"aaaaaax", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_26, r"([a]*)+", r"a", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_27, r"([a]*)+", r"x", Some((0, 0)), Some((0, 0)))
-mat!(match_nullsubexpr_28, r"([a]*)+", r"aaaaaa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_29, r"([a]*)+", r"aaaaaax", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_30, r"([^b]*)*", r"a", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_32, r"([^b]*)*", r"b", Some((0, 0)), None)
-mat!(match_nullsubexpr_33, r"([^b]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_34, r"([^b]*)*", r"aaaaaab", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_35, r"([ab]*)*", r"a", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_36, r"([ab]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_37, r"([ab]*)*", r"ababab", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_38, r"([ab]*)*", r"bababa", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_39, r"([ab]*)*", r"b", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_40, r"([ab]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_41, r"([ab]*)*", r"aaaabcde", Some((0, 5)), Some((0, 5)))
-mat!(match_nullsubexpr_42, r"([^a]*)*", r"b", Some((0, 1)), Some((0, 1)))
-mat!(match_nullsubexpr_43, r"([^a]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_45, r"([^a]*)*", r"aaaaaa", Some((0, 0)), None)
-mat!(match_nullsubexpr_46, r"([^ab]*)*", r"ccccxx", Some((0, 6)), Some((0, 6)))
-mat!(match_nullsubexpr_48, r"([^ab]*)*", r"ababab", Some((0, 0)), None)
-mat!(match_nullsubexpr_50, r"((z)+|a)*", r"zabcde", Some((0, 2)), Some((1, 2)))
-mat!(match_nullsubexpr_69, r"(a*)*(x)", r"x", Some((0, 1)), None, Some((0, 1)))
-mat!(match_nullsubexpr_70, r"(a*)*(x)", r"ax", Some((0, 2)), Some((0, 1)), Some((1, 2)))
-mat!(match_nullsubexpr_71, r"(a*)*(x)", r"axa", Some((0, 2)), Some((0, 1)), Some((1, 2)))
-mat!(match_nullsubexpr_73, r"(a*)+(x)", r"x", Some((0, 1)), Some((0, 0)), Some((0, 1)))
-mat!(match_nullsubexpr_74, r"(a*)+(x)", r"ax", Some((0, 2)), Some((0, 1)), Some((1, 2)))
-mat!(match_nullsubexpr_75, r"(a*)+(x)", r"axa", Some((0, 2)), Some((0, 1)), Some((1, 2)))
-mat!(match_nullsubexpr_77, r"(a*){2}(x)", r"x", Some((0, 1)), Some((0, 0)), Some((0, 1)))
-mat!(match_nullsubexpr_78, r"(a*){2}(x)", r"ax", Some((0, 2)), Some((1, 1)), Some((1, 2)))
-mat!(match_nullsubexpr_79, r"(a*){2}(x)", r"axa", Some((0, 2)), Some((1, 1)), Some((1, 2)))
+mat!{match_nullsubexpr_3, r"(a*)*", r"a", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_5, r"(a*)*", r"x", Some((0, 0)), None}
+mat!{match_nullsubexpr_6, r"(a*)*", r"aaaaaa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_7, r"(a*)*", r"aaaaaax", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_8, r"(a*)+", r"a", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_9, r"(a*)+", r"x", Some((0, 0)), Some((0, 0))}
+mat!{match_nullsubexpr_10, r"(a*)+", r"aaaaaa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_11, r"(a*)+", r"aaaaaax", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_12, r"(a+)*", r"a", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_13, r"(a+)*", r"x", Some((0, 0))}
+mat!{match_nullsubexpr_14, r"(a+)*", r"aaaaaa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_15, r"(a+)*", r"aaaaaax", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_16, r"(a+)+", r"a", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_17, r"(a+)+", r"x", None}
+mat!{match_nullsubexpr_18, r"(a+)+", r"aaaaaa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_19, r"(a+)+", r"aaaaaax", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_21, r"([a]*)*", r"a", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_23, r"([a]*)*", r"x", Some((0, 0)), None}
+mat!{match_nullsubexpr_24, r"([a]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_25, r"([a]*)*", r"aaaaaax", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_26, r"([a]*)+", r"a", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_27, r"([a]*)+", r"x", Some((0, 0)), Some((0, 0))}
+mat!{match_nullsubexpr_28, r"([a]*)+", r"aaaaaa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_29, r"([a]*)+", r"aaaaaax", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_30, r"([^b]*)*", r"a", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_32, r"([^b]*)*", r"b", Some((0, 0)), None}
+mat!{match_nullsubexpr_33, r"([^b]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_34, r"([^b]*)*", r"aaaaaab", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_35, r"([ab]*)*", r"a", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_36, r"([ab]*)*", r"aaaaaa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_37, r"([ab]*)*", r"ababab", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_38, r"([ab]*)*", r"bababa", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_39, r"([ab]*)*", r"b", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_40, r"([ab]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_41, r"([ab]*)*", r"aaaabcde", Some((0, 5)), Some((0, 5))}
+mat!{match_nullsubexpr_42, r"([^a]*)*", r"b", Some((0, 1)), Some((0, 1))}
+mat!{match_nullsubexpr_43, r"([^a]*)*", r"bbbbbb", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_45, r"([^a]*)*", r"aaaaaa", Some((0, 0)), None}
+mat!{match_nullsubexpr_46, r"([^ab]*)*", r"ccccxx", Some((0, 6)), Some((0, 6))}
+mat!{match_nullsubexpr_48, r"([^ab]*)*", r"ababab", Some((0, 0)), None}
+mat!{match_nullsubexpr_50, r"((z)+|a)*", r"zabcde", Some((0, 2)), Some((1, 2))}
+mat!{match_nullsubexpr_69, r"(a*)*(x)", r"x", Some((0, 1)), None, Some((0, 1))}
+mat!{match_nullsubexpr_70, r"(a*)*(x)", r"ax", Some((0, 2)), Some((0, 1)), Some((1, 2))}
+mat!{match_nullsubexpr_71, r"(a*)*(x)", r"axa", Some((0, 2)), Some((0, 1)), Some((1, 2))}
+mat!{match_nullsubexpr_73, r"(a*)+(x)", r"x", Some((0, 1)), Some((0, 0)), Some((0, 1))}
+mat!{match_nullsubexpr_74, r"(a*)+(x)", r"ax", Some((0, 2)), Some((0, 1)), Some((1, 2))}
+mat!{match_nullsubexpr_75, r"(a*)+(x)", r"axa", Some((0, 2)), Some((0, 1)), Some((1, 2))}
+mat!{match_nullsubexpr_77, r"(a*){2}(x)", r"x", Some((0, 1)), Some((0, 0)), Some((0, 1))}
+mat!{match_nullsubexpr_78, r"(a*){2}(x)", r"ax", Some((0, 2)), Some((1, 1)), Some((1, 2))}
+mat!{match_nullsubexpr_79, r"(a*){2}(x)", r"axa", Some((0, 2)), Some((1, 1)), Some((1, 2))}
 
 // Tests from repetition.dat
-mat!(match_repetition_10, r"((..)|(.))", r"", None)
-mat!(match_repetition_11, r"((..)|(.))((..)|(.))", r"", None)
-mat!(match_repetition_12, r"((..)|(.))((..)|(.))((..)|(.))", r"", None)
-mat!(match_repetition_14, r"((..)|(.)){1}", r"", None)
-mat!(match_repetition_15, r"((..)|(.)){2}", r"", None)
-mat!(match_repetition_16, r"((..)|(.)){3}", r"", None)
-mat!(match_repetition_18, r"((..)|(.))*", r"", Some((0, 0)))
-mat!(match_repetition_20, r"((..)|(.))", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1)))
-mat!(match_repetition_21, r"((..)|(.))((..)|(.))", r"a", None)
-mat!(match_repetition_22, r"((..)|(.))((..)|(.))((..)|(.))", r"a", None)
-mat!(match_repetition_24, r"((..)|(.)){1}", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1)))
-mat!(match_repetition_25, r"((..)|(.)){2}", r"a", None)
-mat!(match_repetition_26, r"((..)|(.)){3}", r"a", None)
-mat!(match_repetition_28, r"((..)|(.))*", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1)))
-mat!(match_repetition_30, r"((..)|(.))", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_31, r"((..)|(.))((..)|(.))", r"aa", Some((0, 2)), Some((0, 1)), None, Some((0, 1)), Some((1, 2)), None, Some((1, 2)))
-mat!(match_repetition_32, r"((..)|(.))((..)|(.))((..)|(.))", r"aa", None)
-mat!(match_repetition_34, r"((..)|(.)){1}", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_35, r"((..)|(.)){2}", r"aa", Some((0, 2)), Some((1, 2)), None, Some((1, 2)))
-mat!(match_repetition_36, r"((..)|(.)){3}", r"aa", None)
-mat!(match_repetition_38, r"((..)|(.))*", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_40, r"((..)|(.))", r"aaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_41, r"((..)|(.))((..)|(.))", r"aaa", Some((0, 3)), Some((0, 2)), Some((0, 2)), None, Some((2, 3)), None, Some((2, 3)))
-mat!(match_repetition_42, r"((..)|(.))((..)|(.))((..)|(.))", r"aaa", Some((0, 3)), Some((0, 1)), None, Some((0, 1)), Some((1, 2)), None, Some((1, 2)), Some((2, 3)), None, Some((2, 3)))
-mat!(match_repetition_44, r"((..)|(.)){1}", r"aaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_46, r"((..)|(.)){2}", r"aaa", Some((0, 3)), Some((2, 3)), Some((0, 2)), Some((2, 3)))
-mat!(match_repetition_47, r"((..)|(.)){3}", r"aaa", Some((0, 3)), Some((2, 3)), None, Some((2, 3)))
-mat!(match_repetition_50, r"((..)|(.))*", r"aaa", Some((0, 3)), Some((2, 3)), Some((0, 2)), Some((2, 3)))
-mat!(match_repetition_52, r"((..)|(.))", r"aaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_53, r"((..)|(.))((..)|(.))", r"aaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None)
-mat!(match_repetition_54, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 3)), None, Some((2, 3)), Some((3, 4)), None, Some((3, 4)))
-mat!(match_repetition_56, r"((..)|(.)){1}", r"aaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_57, r"((..)|(.)){2}", r"aaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None)
-mat!(match_repetition_59, r"((..)|(.)){3}", r"aaaa", Some((0, 4)), Some((3, 4)), Some((0, 2)), Some((3, 4)))
-mat!(match_repetition_61, r"((..)|(.))*", r"aaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None)
-mat!(match_repetition_63, r"((..)|(.))", r"aaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_64, r"((..)|(.))((..)|(.))", r"aaaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None)
-mat!(match_repetition_65, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaaa", Some((0, 5)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None, Some((4, 5)), None, Some((4, 5)))
-mat!(match_repetition_67, r"((..)|(.)){1}", r"aaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_68, r"((..)|(.)){2}", r"aaaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None)
-mat!(match_repetition_70, r"((..)|(.)){3}", r"aaaaa", Some((0, 5)), Some((4, 5)), Some((2, 4)), Some((4, 5)))
-mat!(match_repetition_73, r"((..)|(.))*", r"aaaaa", Some((0, 5)), Some((4, 5)), Some((2, 4)), Some((4, 5)))
-mat!(match_repetition_75, r"((..)|(.))", r"aaaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_76, r"((..)|(.))((..)|(.))", r"aaaaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None)
-mat!(match_repetition_77, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaaaa", Some((0, 6)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None, Some((4, 6)), Some((4, 6)), None)
-mat!(match_repetition_79, r"((..)|(.)){1}", r"aaaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None)
-mat!(match_repetition_80, r"((..)|(.)){2}", r"aaaaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None)
-mat!(match_repetition_81, r"((..)|(.)){3}", r"aaaaaa", Some((0, 6)), Some((4, 6)), Some((4, 6)), None)
-mat!(match_repetition_83, r"((..)|(.))*", r"aaaaaa", Some((0, 6)), Some((4, 6)), Some((4, 6)), None)
-mat!(match_repetition_90, r"X(.?){0,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)))
-mat!(match_repetition_91, r"X(.?){1,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)))
-mat!(match_repetition_92, r"X(.?){2,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)))
-mat!(match_repetition_93, r"X(.?){3,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)))
-mat!(match_repetition_94, r"X(.?){4,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)))
-mat!(match_repetition_95, r"X(.?){5,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)))
-mat!(match_repetition_96, r"X(.?){6,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)))
-mat!(match_repetition_97, r"X(.?){7,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8)))
-mat!(match_repetition_98, r"X(.?){8,}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_100, r"X(.?){0,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_102, r"X(.?){1,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_104, r"X(.?){2,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_106, r"X(.?){3,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_108, r"X(.?){4,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_110, r"X(.?){5,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_112, r"X(.?){6,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_114, r"X(.?){7,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_115, r"X(.?){8,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8)))
-mat!(match_repetition_126, r"(a|ab|c|bcd){0,}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)))
-mat!(match_repetition_127, r"(a|ab|c|bcd){1,}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)))
-mat!(match_repetition_128, r"(a|ab|c|bcd){2,}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6)))
-mat!(match_repetition_129, r"(a|ab|c|bcd){3,}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6)))
-mat!(match_repetition_130, r"(a|ab|c|bcd){4,}(d*)", r"ababcd", None)
-mat!(match_repetition_131, r"(a|ab|c|bcd){0,10}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)))
-mat!(match_repetition_132, r"(a|ab|c|bcd){1,10}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)))
-mat!(match_repetition_133, r"(a|ab|c|bcd){2,10}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6)))
-mat!(match_repetition_134, r"(a|ab|c|bcd){3,10}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6)))
-mat!(match_repetition_135, r"(a|ab|c|bcd){4,10}(d*)", r"ababcd", None)
-mat!(match_repetition_136, r"(a|ab|c|bcd)*(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)))
-mat!(match_repetition_137, r"(a|ab|c|bcd)+(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1)))
-mat!(match_repetition_143, r"(ab|a|c|bcd){0,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_145, r"(ab|a|c|bcd){1,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_147, r"(ab|a|c|bcd){2,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_149, r"(ab|a|c|bcd){3,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_150, r"(ab|a|c|bcd){4,}(d*)", r"ababcd", None)
-mat!(match_repetition_152, r"(ab|a|c|bcd){0,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_154, r"(ab|a|c|bcd){1,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_156, r"(ab|a|c|bcd){2,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_158, r"(ab|a|c|bcd){3,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_159, r"(ab|a|c|bcd){4,10}(d*)", r"ababcd", None)
-mat!(match_repetition_161, r"(ab|a|c|bcd)*(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
-mat!(match_repetition_163, r"(ab|a|c|bcd)+(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6)))
+mat!{match_repetition_10, r"((..)|(.))", r"", None}
+mat!{match_repetition_11, r"((..)|(.))((..)|(.))", r"", None}
+mat!{match_repetition_12, r"((..)|(.))((..)|(.))((..)|(.))", r"", None}
+mat!{match_repetition_14, r"((..)|(.)){1}", r"", None}
+mat!{match_repetition_15, r"((..)|(.)){2}", r"", None}
+mat!{match_repetition_16, r"((..)|(.)){3}", r"", None}
+mat!{match_repetition_18, r"((..)|(.))*", r"", Some((0, 0))}
+mat!{match_repetition_20, r"((..)|(.))", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1))}
+mat!{match_repetition_21, r"((..)|(.))((..)|(.))", r"a", None}
+mat!{match_repetition_22, r"((..)|(.))((..)|(.))((..)|(.))", r"a", None}
+mat!{match_repetition_24, r"((..)|(.)){1}", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1))}
+mat!{match_repetition_25, r"((..)|(.)){2}", r"a", None}
+mat!{match_repetition_26, r"((..)|(.)){3}", r"a", None}
+mat!{match_repetition_28, r"((..)|(.))*", r"a", Some((0, 1)), Some((0, 1)), None, Some((0, 1))}
+mat!{match_repetition_30, r"((..)|(.))", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_31, r"((..)|(.))((..)|(.))", r"aa", Some((0, 2)), Some((0, 1)), None, Some((0, 1)), Some((1, 2)), None, Some((1, 2))}
+mat!{match_repetition_32, r"((..)|(.))((..)|(.))((..)|(.))", r"aa", None}
+mat!{match_repetition_34, r"((..)|(.)){1}", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_35, r"((..)|(.)){2}", r"aa", Some((0, 2)), Some((1, 2)), None, Some((1, 2))}
+mat!{match_repetition_36, r"((..)|(.)){3}", r"aa", None}
+mat!{match_repetition_38, r"((..)|(.))*", r"aa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_40, r"((..)|(.))", r"aaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_41, r"((..)|(.))((..)|(.))", r"aaa", Some((0, 3)), Some((0, 2)), Some((0, 2)), None, Some((2, 3)), None, Some((2, 3))}
+mat!{match_repetition_42, r"((..)|(.))((..)|(.))((..)|(.))", r"aaa", Some((0, 3)), Some((0, 1)), None, Some((0, 1)), Some((1, 2)), None, Some((1, 2)), Some((2, 3)), None, Some((2, 3))}
+mat!{match_repetition_44, r"((..)|(.)){1}", r"aaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_46, r"((..)|(.)){2}", r"aaa", Some((0, 3)), Some((2, 3)), Some((0, 2)), Some((2, 3))}
+mat!{match_repetition_47, r"((..)|(.)){3}", r"aaa", Some((0, 3)), Some((2, 3)), None, Some((2, 3))}
+mat!{match_repetition_50, r"((..)|(.))*", r"aaa", Some((0, 3)), Some((2, 3)), Some((0, 2)), Some((2, 3))}
+mat!{match_repetition_52, r"((..)|(.))", r"aaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_53, r"((..)|(.))((..)|(.))", r"aaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None}
+mat!{match_repetition_54, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 3)), None, Some((2, 3)), Some((3, 4)), None, Some((3, 4))}
+mat!{match_repetition_56, r"((..)|(.)){1}", r"aaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_57, r"((..)|(.)){2}", r"aaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None}
+mat!{match_repetition_59, r"((..)|(.)){3}", r"aaaa", Some((0, 4)), Some((3, 4)), Some((0, 2)), Some((3, 4))}
+mat!{match_repetition_61, r"((..)|(.))*", r"aaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None}
+mat!{match_repetition_63, r"((..)|(.))", r"aaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_64, r"((..)|(.))((..)|(.))", r"aaaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None}
+mat!{match_repetition_65, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaaa", Some((0, 5)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None, Some((4, 5)), None, Some((4, 5))}
+mat!{match_repetition_67, r"((..)|(.)){1}", r"aaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_68, r"((..)|(.)){2}", r"aaaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None}
+mat!{match_repetition_70, r"((..)|(.)){3}", r"aaaaa", Some((0, 5)), Some((4, 5)), Some((2, 4)), Some((4, 5))}
+mat!{match_repetition_73, r"((..)|(.))*", r"aaaaa", Some((0, 5)), Some((4, 5)), Some((2, 4)), Some((4, 5))}
+mat!{match_repetition_75, r"((..)|(.))", r"aaaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_76, r"((..)|(.))((..)|(.))", r"aaaaaa", Some((0, 4)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None}
+mat!{match_repetition_77, r"((..)|(.))((..)|(.))((..)|(.))", r"aaaaaa", Some((0, 6)), Some((0, 2)), Some((0, 2)), None, Some((2, 4)), Some((2, 4)), None, Some((4, 6)), Some((4, 6)), None}
+mat!{match_repetition_79, r"((..)|(.)){1}", r"aaaaaa", Some((0, 2)), Some((0, 2)), Some((0, 2)), None}
+mat!{match_repetition_80, r"((..)|(.)){2}", r"aaaaaa", Some((0, 4)), Some((2, 4)), Some((2, 4)), None}
+mat!{match_repetition_81, r"((..)|(.)){3}", r"aaaaaa", Some((0, 6)), Some((4, 6)), Some((4, 6)), None}
+mat!{match_repetition_83, r"((..)|(.))*", r"aaaaaa", Some((0, 6)), Some((4, 6)), Some((4, 6)), None}
+mat!{match_repetition_90, r"X(.?){0,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))}
+mat!{match_repetition_91, r"X(.?){1,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))}
+mat!{match_repetition_92, r"X(.?){2,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))}
+mat!{match_repetition_93, r"X(.?){3,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))}
+mat!{match_repetition_94, r"X(.?){4,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))}
+mat!{match_repetition_95, r"X(.?){5,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))}
+mat!{match_repetition_96, r"X(.?){6,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))}
+mat!{match_repetition_97, r"X(.?){7,}Y", r"X1234567Y", Some((0, 9)), Some((7, 8))}
+mat!{match_repetition_98, r"X(.?){8,}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_100, r"X(.?){0,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_102, r"X(.?){1,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_104, r"X(.?){2,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_106, r"X(.?){3,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_108, r"X(.?){4,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_110, r"X(.?){5,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_112, r"X(.?){6,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_114, r"X(.?){7,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_115, r"X(.?){8,8}Y", r"X1234567Y", Some((0, 9)), Some((8, 8))}
+mat!{match_repetition_126, r"(a|ab|c|bcd){0,}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))}
+mat!{match_repetition_127, r"(a|ab|c|bcd){1,}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))}
+mat!{match_repetition_128, r"(a|ab|c|bcd){2,}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6))}
+mat!{match_repetition_129, r"(a|ab|c|bcd){3,}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6))}
+mat!{match_repetition_130, r"(a|ab|c|bcd){4,}(d*)", r"ababcd", None}
+mat!{match_repetition_131, r"(a|ab|c|bcd){0,10}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))}
+mat!{match_repetition_132, r"(a|ab|c|bcd){1,10}(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))}
+mat!{match_repetition_133, r"(a|ab|c|bcd){2,10}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6))}
+mat!{match_repetition_134, r"(a|ab|c|bcd){3,10}(d*)", r"ababcd", Some((0, 6)), Some((3, 6)), Some((6, 6))}
+mat!{match_repetition_135, r"(a|ab|c|bcd){4,10}(d*)", r"ababcd", None}
+mat!{match_repetition_136, r"(a|ab|c|bcd)*(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))}
+mat!{match_repetition_137, r"(a|ab|c|bcd)+(d*)", r"ababcd", Some((0, 1)), Some((0, 1)), Some((1, 1))}
+mat!{match_repetition_143, r"(ab|a|c|bcd){0,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_145, r"(ab|a|c|bcd){1,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_147, r"(ab|a|c|bcd){2,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_149, r"(ab|a|c|bcd){3,}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_150, r"(ab|a|c|bcd){4,}(d*)", r"ababcd", None}
+mat!{match_repetition_152, r"(ab|a|c|bcd){0,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_154, r"(ab|a|c|bcd){1,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_156, r"(ab|a|c|bcd){2,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_158, r"(ab|a|c|bcd){3,10}(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_159, r"(ab|a|c|bcd){4,10}(d*)", r"ababcd", None}
+mat!{match_repetition_161, r"(ab|a|c|bcd)*(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
+mat!{match_repetition_163, r"(ab|a|c|bcd)+(d*)", r"ababcd", Some((0, 6)), Some((4, 5)), Some((5, 6))}
 
diff --git a/src/libregex/test/mod.rs b/src/libregex/test/mod.rs
index 7f014b4eb68..14156647191 100644
--- a/src/libregex/test/mod.rs
+++ b/src/libregex/test/mod.rs
@@ -26,14 +26,14 @@ mod native_static;
 // Due to macro scoping rules, this definition only applies for the modules
 // defined below. Effectively, it allows us to use the same tests for both
 // native and dynamic regexes.
-macro_rules! regex(
+macro_rules! regex {
     ($re:expr) => (
         match ::regex::Regex::new($re) {
             Ok(re) => re,
             Err(err) => panic!("{}", err),
         }
     );
-)
+}
 
 #[path = "bench.rs"]
 mod dynamic_bench;
diff --git a/src/libregex/test/tests.rs b/src/libregex/test/tests.rs
index 27091b6ef4b..2f66d483d80 100644
--- a/src/libregex/test/tests.rs
+++ b/src/libregex/test/tests.rs
@@ -67,7 +67,7 @@ fn range_ends_with_escape() {
     assert_eq!(ms, vec![(0, 1), (1, 2)]);
 }
 
-macro_rules! replace(
+macro_rules! replace {
     ($name:ident, $which:ident, $re:expr,
      $search:expr, $replace:expr, $result:expr) => (
         #[test]
@@ -76,23 +76,23 @@ macro_rules! replace(
             assert_eq!(re.$which($search, $replace), String::from_str($result));
         }
     );
-)
-
-replace!(rep_first, replace, r"\d", "age: 26", "Z", "age: Z6")
-replace!(rep_plus, replace, r"\d+", "age: 26", "Z", "age: Z")
-replace!(rep_all, replace_all, r"\d", "age: 26", "Z", "age: ZZ")
-replace!(rep_groups, replace, r"(\S+)\s+(\S+)", "w1 w2", "$2 $1", "w2 w1")
-replace!(rep_double_dollar, replace,
-         r"(\S+)\s+(\S+)", "w1 w2", "$2 $$1", "w2 $1")
-replace!(rep_no_expand, replace,
-         r"(\S+)\s+(\S+)", "w1 w2", NoExpand("$2 $1"), "$2 $1")
-replace!(rep_named, replace_all,
+}
+
+replace!{rep_first, replace, r"\d", "age: 26", "Z", "age: Z6"}
+replace!{rep_plus, replace, r"\d+", "age: 26", "Z", "age: Z"}
+replace!{rep_all, replace_all, r"\d", "age: 26", "Z", "age: ZZ"}
+replace!{rep_groups, replace, r"(\S+)\s+(\S+)", "w1 w2", "$2 $1", "w2 w1"}
+replace!{rep_double_dollar, replace,
+         r"(\S+)\s+(\S+)", "w1 w2", "$2 $$1", "w2 $1"}
+replace!{rep_no_expand, replace,
+         r"(\S+)\s+(\S+)", "w1 w2", NoExpand("$2 $1"), "$2 $1"}
+replace!{rep_named, replace_all,
          r"(?P\S+)\s+(?P\S+)(?P\s*)",
-         "w1 w2 w3 w4", "$last $first$space", "w2 w1 w4 w3")
-replace!(rep_trim, replace_all, "^[ \t]+|[ \t]+$", " \t  trim me\t   \t",
-         "", "trim me")
+         "w1 w2 w3 w4", "$last $first$space", "w2 w1 w4 w3"}
+replace!{rep_trim, replace_all, "^[ \t]+|[ \t]+$", " \t  trim me\t   \t",
+         "", "trim me"}
 
-macro_rules! noparse(
+macro_rules! noparse {
     ($name:ident, $re:expr) => (
         #[test]
         fn $name() {
@@ -103,47 +103,47 @@ macro_rules! noparse(
             }
         }
     );
-)
-
-noparse!(fail_double_repeat, "a**")
-noparse!(fail_no_repeat_arg, "*")
-noparse!(fail_no_repeat_arg_begin, "^*")
-noparse!(fail_incomplete_escape, "\\")
-noparse!(fail_class_incomplete, "[A-")
-noparse!(fail_class_not_closed, "[A")
-noparse!(fail_class_no_begin, r"[\A]")
-noparse!(fail_class_no_end, r"[\z]")
-noparse!(fail_class_no_boundary, r"[\b]")
-noparse!(fail_open_paren, "(")
-noparse!(fail_close_paren, ")")
-noparse!(fail_invalid_range, "[a-Z]")
-noparse!(fail_empty_capture_name, "(?P<>a)")
-noparse!(fail_empty_capture_exp, "(?P)")
-noparse!(fail_bad_capture_name, "(?P)")
-noparse!(fail_bad_flag, "(?a)a")
-noparse!(fail_empty_alt_before, "|a")
-noparse!(fail_empty_alt_after, "a|")
-noparse!(fail_counted_big_exact, "a{1001}")
-noparse!(fail_counted_big_min, "a{1001,}")
-noparse!(fail_counted_no_close, "a{1001")
-noparse!(fail_unfinished_cap, "(?")
-noparse!(fail_unfinished_escape, "\\")
-noparse!(fail_octal_digit, r"\8")
-noparse!(fail_hex_digit, r"\xG0")
-noparse!(fail_hex_short, r"\xF")
-noparse!(fail_hex_long_digits, r"\x{fffg}")
-noparse!(fail_flag_bad, "(?a)")
-noparse!(fail_flag_empty, "(?)")
-noparse!(fail_double_neg, "(?-i-i)")
-noparse!(fail_neg_empty, "(?i-)")
-noparse!(fail_empty_group, "()")
-noparse!(fail_dupe_named, "(?P.)(?P.)")
-noparse!(fail_range_end_no_class, "[a-[:lower:]]")
-noparse!(fail_range_end_no_begin, r"[a-\A]")
-noparse!(fail_range_end_no_end, r"[a-\z]")
-noparse!(fail_range_end_no_boundary, r"[a-\b]")
-
-macro_rules! mat(
+}
+
+noparse!{fail_double_repeat, "a**"}
+noparse!{fail_no_repeat_arg, "*"}
+noparse!{fail_no_repeat_arg_begin, "^*"}
+noparse!{fail_incomplete_escape, "\\"}
+noparse!{fail_class_incomplete, "[A-"}
+noparse!{fail_class_not_closed, "[A"}
+noparse!{fail_class_no_begin, r"[\A]"}
+noparse!{fail_class_no_end, r"[\z]"}
+noparse!{fail_class_no_boundary, r"[\b]"}
+noparse!{fail_open_paren, "("}
+noparse!{fail_close_paren, ")"}
+noparse!{fail_invalid_range, "[a-Z]"}
+noparse!{fail_empty_capture_name, "(?P<>a)"}
+noparse!{fail_empty_capture_exp, "(?P)"}
+noparse!{fail_bad_capture_name, "(?P)"}
+noparse!{fail_bad_flag, "(?a)a"}
+noparse!{fail_empty_alt_before, "|a"}
+noparse!{fail_empty_alt_after, "a|"}
+noparse!{fail_counted_big_exact, "a{1001}"}
+noparse!{fail_counted_big_min, "a{1001,}"}
+noparse!{fail_counted_no_close, "a{1001"}
+noparse!{fail_unfinished_cap, "(?"}
+noparse!{fail_unfinished_escape, "\\"}
+noparse!{fail_octal_digit, r"\8"}
+noparse!{fail_hex_digit, r"\xG0"}
+noparse!{fail_hex_short, r"\xF"}
+noparse!{fail_hex_long_digits, r"\x{fffg}"}
+noparse!{fail_flag_bad, "(?a)"}
+noparse!{fail_flag_empty, "(?)"}
+noparse!{fail_double_neg, "(?-i-i)"}
+noparse!{fail_neg_empty, "(?i-)"}
+noparse!{fail_empty_group, "()"}
+noparse!{fail_dupe_named, "(?P.)(?P.)"}
+noparse!{fail_range_end_no_class, "[a-[:lower:]]"}
+noparse!{fail_range_end_no_begin, r"[a-\A]"}
+noparse!{fail_range_end_no_end, r"[a-\z]"}
+noparse!{fail_range_end_no_boundary, r"[a-\b]"}
+
+macro_rules! mat {
     ($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
         #[test]
         fn $name() {
@@ -166,78 +166,78 @@ macro_rules! mat(
             }
         }
     );
-)
+}
 
 // Some crazy expressions from regular-expressions.info.
-mat!(match_ranges,
+mat!{match_ranges,
      r"\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b",
-     "num: 255", Some((5, 8)))
-mat!(match_ranges_not,
+     "num: 255", Some((5, 8))}
+mat!{match_ranges_not,
      r"\b(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b",
-     "num: 256", None)
-mat!(match_float1, r"[-+]?[0-9]*\.?[0-9]+", "0.1", Some((0, 3)))
-mat!(match_float2, r"[-+]?[0-9]*\.?[0-9]+", "0.1.2", Some((0, 3)))
-mat!(match_float3, r"[-+]?[0-9]*\.?[0-9]+", "a1.2", Some((1, 4)))
-mat!(match_float4, r"^[-+]?[0-9]*\.?[0-9]+$", "1.a", None)
-mat!(match_email, r"(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
-     "mine is jam.slam@gmail.com ", Some((8, 26)))
-mat!(match_email_not, r"(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
-     "mine is jam.slam@gmail ", None)
-mat!(match_email_big, r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
-     "mine is jam.slam@gmail.com ", Some((8, 26)))
-mat!(match_date1,
+     "num: 256", None}
+mat!{match_float1, r"[-+]?[0-9]*\.?[0-9]+", "0.1", Some((0, 3))}
+mat!{match_float2, r"[-+]?[0-9]*\.?[0-9]+", "0.1.2", Some((0, 3))}
+mat!{match_float3, r"[-+]?[0-9]*\.?[0-9]+", "a1.2", Some((1, 4))}
+mat!{match_float4, r"^[-+]?[0-9]*\.?[0-9]+$", "1.a", None}
+mat!{match_email, r"(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
+     "mine is jam.slam@gmail.com ", Some((8, 26))}
+mat!{match_email_not, r"(?i)\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
+     "mine is jam.slam@gmail ", None}
+mat!{match_email_big, r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
+     "mine is jam.slam@gmail.com ", Some((8, 26))}
+mat!{match_date1,
      r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
-     "1900-01-01", Some((0, 10)))
-mat!(match_date2,
+     "1900-01-01", Some((0, 10))}
+mat!{match_date2,
      r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
-     "1900-00-01", None)
-mat!(match_date3,
+     "1900-00-01", None}
+mat!{match_date3,
      r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$",
-     "1900-13-01", None)
+     "1900-13-01", None}
 
 // Exercise the flags.
-mat!(match_flag_case, "(?i)abc", "ABC", Some((0, 3)))
-mat!(match_flag_weird_case, "(?i)a(?-i)bc", "Abc", Some((0, 3)))
-mat!(match_flag_weird_case_not, "(?i)a(?-i)bc", "ABC", None)
-mat!(match_flag_case_dotnl, "(?is)a.", "A\n", Some((0, 2)))
-mat!(match_flag_case_dotnl_toggle, "(?is)a.(?-is)a.", "A\nab", Some((0, 4)))
-mat!(match_flag_case_dotnl_toggle_not, "(?is)a.(?-is)a.", "A\na\n", None)
-mat!(match_flag_case_dotnl_toggle_ok, "(?is)a.(?-is:a.)?", "A\na\n", Some((0, 2)))
-mat!(match_flag_multi, "(?m)(?:^\\d+$\n?)+", "123\n456\n789", Some((0, 11)))
-mat!(match_flag_ungreedy, "(?U)a+", "aa", Some((0, 1)))
-mat!(match_flag_ungreedy_greedy, "(?U)a+?", "aa", Some((0, 2)))
-mat!(match_flag_ungreedy_noop, "(?U)(?-U)a+", "aa", Some((0, 2)))
+mat!{match_flag_case, "(?i)abc", "ABC", Some((0, 3))}
+mat!{match_flag_weird_case, "(?i)a(?-i)bc", "Abc", Some((0, 3))}
+mat!{match_flag_weird_case_not, "(?i)a(?-i)bc", "ABC", None}
+mat!{match_flag_case_dotnl, "(?is)a.", "A\n", Some((0, 2))}
+mat!{match_flag_case_dotnl_toggle, "(?is)a.(?-is)a.", "A\nab", Some((0, 4))}
+mat!{match_flag_case_dotnl_toggle_not, "(?is)a.(?-is)a.", "A\na\n", None}
+mat!{match_flag_case_dotnl_toggle_ok, "(?is)a.(?-is:a.)?", "A\na\n", Some((0, 2))}
+mat!{match_flag_multi, "(?m)(?:^\\d+$\n?)+", "123\n456\n789", Some((0, 11))}
+mat!{match_flag_ungreedy, "(?U)a+", "aa", Some((0, 1))}
+mat!{match_flag_ungreedy_greedy, "(?U)a+?", "aa", Some((0, 2))}
+mat!{match_flag_ungreedy_noop, "(?U)(?-U)a+", "aa", Some((0, 2))}
 
 // Some Unicode tests.
 // A couple of these are commented out because something in the guts of macro expansion is creating
 // invalid byte strings.
-//mat!(uni_literal, r"Ⅰ", "Ⅰ", Some((0, 3)))
-mat!(uni_one, r"\pN", "Ⅰ", Some((0, 3)))
-mat!(uni_mixed, r"\pN+", "Ⅰ1Ⅱ2", Some((0, 8)))
-mat!(uni_not, r"\PN+", "abⅠ", Some((0, 2)))
-mat!(uni_not_class, r"[\PN]+", "abⅠ", Some((0, 2)))
-mat!(uni_not_class_neg, r"[^\PN]+", "abⅠ", Some((2, 5)))
-mat!(uni_case, r"(?i)Δ", "δ", Some((0, 2)))
-//mat!(uni_case_not, r"Δ", "δ", None)
-mat!(uni_case_upper, r"\p{Lu}+", "ΛΘΓΔα", Some((0, 8)))
-mat!(uni_case_upper_nocase_flag, r"(?i)\p{Lu}+", "ΛΘΓΔα", Some((0, 10)))
-mat!(uni_case_upper_nocase, r"\p{L}+", "ΛΘΓΔα", Some((0, 10)))
-mat!(uni_case_lower, r"\p{Ll}+", "ΛΘΓΔα", Some((8, 10)))
+//mat!{uni_literal, r"Ⅰ", "Ⅰ", Some((0, 3))}
+mat!{uni_one, r"\pN", "Ⅰ", Some((0, 3))}
+mat!{uni_mixed, r"\pN+", "Ⅰ1Ⅱ2", Some((0, 8))}
+mat!{uni_not, r"\PN+", "abⅠ", Some((0, 2))}
+mat!{uni_not_class, r"[\PN]+", "abⅠ", Some((0, 2))}
+mat!{uni_not_class_neg, r"[^\PN]+", "abⅠ", Some((2, 5))}
+mat!{uni_case, r"(?i)Δ", "δ", Some((0, 2))}
+//mat!{uni_case_not, r"Δ", "δ", None}
+mat!{uni_case_upper, r"\p{Lu}+", "ΛΘΓΔα", Some((0, 8))}
+mat!{uni_case_upper_nocase_flag, r"(?i)\p{Lu}+", "ΛΘΓΔα", Some((0, 10))}
+mat!{uni_case_upper_nocase, r"\p{L}+", "ΛΘΓΔα", Some((0, 10))}
+mat!{uni_case_lower, r"\p{Ll}+", "ΛΘΓΔα", Some((8, 10))}
 
 // Test the Unicode friendliness of Perl character classes.
-mat!(uni_perl_w, r"\w+", "dδd", Some((0, 4)))
-mat!(uni_perl_w_not, r"\w+", "⥡", None)
-mat!(uni_perl_w_neg, r"\W+", "⥡", Some((0, 3)))
-mat!(uni_perl_d, r"\d+", "1२३9", Some((0, 8)))
-mat!(uni_perl_d_not, r"\d+", "Ⅱ", None)
-mat!(uni_perl_d_neg, r"\D+", "Ⅱ", Some((0, 3)))
-mat!(uni_perl_s, r"\s+", " ", Some((0, 3)))
-mat!(uni_perl_s_not, r"\s+", "☃", None)
-mat!(uni_perl_s_neg, r"\S+", "☃", Some((0, 3)))
+mat!{uni_perl_w, r"\w+", "dδd", Some((0, 4))}
+mat!{uni_perl_w_not, r"\w+", "⥡", None}
+mat!{uni_perl_w_neg, r"\W+", "⥡", Some((0, 3))}
+mat!{uni_perl_d, r"\d+", "1२३9", Some((0, 8))}
+mat!{uni_perl_d_not, r"\d+", "Ⅱ", None}
+mat!{uni_perl_d_neg, r"\D+", "Ⅱ", Some((0, 3))}
+mat!{uni_perl_s, r"\s+", " ", Some((0, 3))}
+mat!{uni_perl_s_not, r"\s+", "☃", None}
+mat!{uni_perl_s_neg, r"\S+", "☃", Some((0, 3))}
 
 // And do the same for word boundaries.
-mat!(uni_boundary_none, r"\d\b", "6δ", None)
-mat!(uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1)))
+mat!{uni_boundary_none, r"\d\b", "6δ", None}
+mat!{uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1))}
 
 // A whole mess of tests from Glenn Fowler's regex test suite.
 // Generated by the 'src/etc/regex-match-tests' program.
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index fcac718b370..4c3cb99f64d 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -10,16 +10,16 @@
 
 #![allow(non_snake_case)]
 
-register_diagnostic!(E0001, r##"
+register_diagnostic! { E0001, r##"
     This error suggests that the expression arm corresponding to the noted pattern
     will never be reached as for all possible values of the expression being matched,
     one of the preceeding patterns will match.
 
     This means that perhaps some of the preceeding patterns are too general, this
     one is too specific or the ordering is incorrect.
-"##)
+"## }
 
-register_diagnostics!(
+register_diagnostics! {
     E0002,
     E0003,
     E0004,
@@ -68,4 +68,4 @@ register_diagnostics!(
     E0174,
     E0177,
     E0178
-)
+}
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 404c7edeb88..d87fbb01620 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -121,7 +121,7 @@ pub mod lib {
     pub use llvm;
 }
 
-__build_diagnostic_array!(DIAGNOSTICS)
+__build_diagnostic_array! { DIAGNOSTICS }
 
 // A private module so that macro-expanded idents like
 // `::rustc::lint::Lint` will also work in `rustc` itself.
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 3040125d97e..8c25bc702b3 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -50,8 +50,11 @@ use syntax::ast_util;
 use syntax::ptr::P;
 use syntax::visit::{mod, Visitor};
 
-declare_lint!(WHILE_TRUE, Warn,
-              "suggest using `loop { }` instead of `while true { }`")
+declare_lint! {
+    WHILE_TRUE,
+    Warn,
+    "suggest using `loop { }` instead of `while true { }`"
+}
 
 pub struct WhileTrue;
 
@@ -74,8 +77,11 @@ impl LintPass for WhileTrue {
     }
 }
 
-declare_lint!(UNUSED_TYPECASTS, Allow,
-              "detects unnecessary type casts, that can be removed")
+declare_lint! {
+    UNUSED_TYPECASTS,
+    Allow,
+    "detects unnecessary type casts that can be removed"
+}
 
 pub struct UnusedCasts;
 
@@ -96,17 +102,29 @@ impl LintPass for UnusedCasts {
     }
 }
 
-declare_lint!(UNSIGNED_NEGATION, Warn,
-              "using an unary minus operator on unsigned type")
+declare_lint! {
+    UNSIGNED_NEGATION,
+    Warn,
+    "using an unary minus operator on unsigned type"
+}
 
-declare_lint!(UNUSED_COMPARISONS, Warn,
-              "comparisons made useless by limits of the types involved")
+declare_lint! {
+    UNUSED_COMPARISONS,
+    Warn,
+    "comparisons made useless by limits of the types involved"
+}
 
-declare_lint!(OVERFLOWING_LITERALS, Warn,
-              "literal out of range for its type")
+declare_lint! {
+    OVERFLOWING_LITERALS,
+    Warn,
+    "literal out of range for its type"
+}
 
-declare_lint!(EXCEEDING_BITSHIFTS, Deny,
-              "shift exceeds the type's number of bits")
+declare_lint! {
+    EXCEEDING_BITSHIFTS,
+    Deny,
+    "shift exceeds the type's number of bits"
+}
 
 pub struct TypeLimits {
     /// Id of the last visited negated expression
@@ -373,8 +391,11 @@ impl LintPass for TypeLimits {
     }
 }
 
-declare_lint!(IMPROPER_CTYPES, Warn,
-              "proper use of libc types in foreign modules")
+declare_lint! {
+    IMPROPER_CTYPES,
+    Warn,
+    "proper use of libc types in foreign modules"
+}
 
 struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
     cx: &'a Context<'a, 'tcx>
@@ -459,8 +480,11 @@ impl LintPass for ImproperCTypes {
     }
 }
 
-declare_lint!(BOX_POINTERS, Allow,
-              "use of owned (Box type) heap memory")
+declare_lint! {
+    BOX_POINTERS,
+    Allow,
+    "use of owned (Box type) heap memory"
+}
 
 pub struct BoxPointers;
 
@@ -527,8 +551,11 @@ impl LintPass for BoxPointers {
     }
 }
 
-declare_lint!(RAW_POINTER_DERIVING, Warn,
-              "uses of #[deriving] with raw pointers are rarely correct")
+declare_lint! {
+    RAW_POINTER_DERIVING,
+    Warn,
+    "uses of #[deriving] with raw pointers are rarely correct"
+}
 
 struct RawPtrDerivingVisitor<'a, 'tcx: 'a> {
     cx: &'a Context<'a, 'tcx>
@@ -594,8 +621,11 @@ impl LintPass for RawPointerDeriving {
     }
 }
 
-declare_lint!(UNUSED_ATTRIBUTES, Warn,
-              "detects attributes that were not used by the compiler")
+declare_lint! {
+    UNUSED_ATTRIBUTES,
+    Warn,
+    "detects attributes that were not used by the compiler"
+}
 
 pub struct UnusedAttributes;
 
@@ -675,8 +705,11 @@ impl LintPass for UnusedAttributes {
     }
 }
 
-declare_lint!(pub PATH_STATEMENTS, Warn,
-              "path statements with no effect")
+declare_lint! {
+    pub PATH_STATEMENTS,
+    Warn,
+    "path statements with no effect"
+}
 
 pub struct PathStatements;
 
@@ -701,11 +734,17 @@ impl LintPass for PathStatements {
     }
 }
 
-declare_lint!(pub UNUSED_MUST_USE, Warn,
-              "unused result of a type flagged as #[must_use]")
+declare_lint! {
+    pub UNUSED_MUST_USE,
+    Warn,
+    "unused result of a type flagged as #[must_use]"
+}
 
-declare_lint!(pub UNUSED_RESULTS, Allow,
-              "unused result of an expression in a statement")
+declare_lint! {
+    pub UNUSED_RESULTS,
+    Allow,
+    "unused result of an expression in a statement"
+}
 
 pub struct UnusedResults;
 
@@ -770,8 +809,11 @@ impl LintPass for UnusedResults {
     }
 }
 
-declare_lint!(pub NON_CAMEL_CASE_TYPES, Warn,
-              "types, variants, traits and type parameters should have camel case names")
+declare_lint! {
+    pub NON_CAMEL_CASE_TYPES,
+    Warn,
+    "types, variants, traits and type parameters should have camel case names"
+}
 
 pub struct NonCamelCaseTypes;
 
@@ -891,8 +933,11 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
     }
 }
 
-declare_lint!(pub NON_SNAKE_CASE, Warn,
-              "methods, functions, lifetime parameters and modules should have snake case names")
+declare_lint! {
+    pub NON_SNAKE_CASE,
+    Warn,
+    "methods, functions, lifetime parameters and modules should have snake case names"
+}
 
 pub struct NonSnakeCase;
 
@@ -1002,8 +1047,11 @@ impl LintPass for NonSnakeCase {
     }
 }
 
-declare_lint!(pub NON_UPPER_CASE_GLOBALS, Warn,
-              "static constants should have uppercase identifiers")
+declare_lint! {
+    pub NON_UPPER_CASE_GLOBALS,
+    Warn,
+    "static constants should have uppercase identifiers"
+}
 
 pub struct NonUpperCaseGlobals;
 
@@ -1053,8 +1101,11 @@ impl LintPass for NonUpperCaseGlobals {
     }
 }
 
-declare_lint!(UNUSED_PARENS, Warn,
-              "`if`, `match`, `while` and `return` do not need parentheses")
+declare_lint! {
+    UNUSED_PARENS,
+    Warn,
+    "`if`, `match`, `while` and `return` do not need parentheses"
+}
 
 pub struct UnusedParens;
 
@@ -1145,8 +1196,11 @@ impl LintPass for UnusedParens {
     }
 }
 
-declare_lint!(UNUSED_IMPORT_BRACES, Allow,
-              "unnecessary braces around an imported item")
+declare_lint! {
+    UNUSED_IMPORT_BRACES,
+    Allow,
+    "unnecessary braces around an imported item"
+}
 
 pub struct UnusedImportBraces;
 
@@ -1182,8 +1236,11 @@ impl LintPass for UnusedImportBraces {
     }
 }
 
-declare_lint!(NON_SHORTHAND_FIELD_PATTERNS, Warn,
-              "using `Struct { x: x }` instead of `Struct { x }`")
+declare_lint! {
+    NON_SHORTHAND_FIELD_PATTERNS,
+    Warn,
+    "using `Struct { x: x }` instead of `Struct { x }`"
+}
 
 pub struct NonShorthandFieldPatterns;
 
@@ -1213,8 +1270,11 @@ impl LintPass for NonShorthandFieldPatterns {
     }
 }
 
-declare_lint!(pub UNUSED_UNSAFE, Warn,
-              "unnecessary use of an `unsafe` block")
+declare_lint! {
+    pub UNUSED_UNSAFE,
+    Warn,
+    "unnecessary use of an `unsafe` block"
+}
 
 pub struct UnusedUnsafe;
 
@@ -1236,8 +1296,11 @@ impl LintPass for UnusedUnsafe {
     }
 }
 
-declare_lint!(UNSAFE_BLOCKS, Allow,
-              "usage of an `unsafe` block")
+declare_lint! {
+    UNSAFE_BLOCKS,
+    Allow,
+    "usage of an `unsafe` block"
+}
 
 pub struct UnsafeBlocks;
 
@@ -1258,8 +1321,11 @@ impl LintPass for UnsafeBlocks {
     }
 }
 
-declare_lint!(pub UNUSED_MUT, Warn,
-              "detect mut variables which don't need to be mutable")
+declare_lint! {
+    pub UNUSED_MUT,
+    Warn,
+    "detect mut variables which don't need to be mutable"
+}
 
 pub struct UnusedMut;
 
@@ -1325,8 +1391,11 @@ impl LintPass for UnusedMut {
     }
 }
 
-declare_lint!(UNUSED_ALLOCATION, Warn,
-              "detects unnecessary allocations that can be eliminated")
+declare_lint! {
+    UNUSED_ALLOCATION,
+    Warn,
+    "detects unnecessary allocations that can be eliminated"
+}
 
 pub struct UnusedAllocation;
 
@@ -1361,8 +1430,11 @@ impl LintPass for UnusedAllocation {
     }
 }
 
-declare_lint!(MISSING_DOCS, Allow,
-              "detects missing documentation for public members")
+declare_lint! {
+    MISSING_DOCS,
+    Allow,
+    "detects missing documentation for public members"
+}
 
 pub struct MissingDoc {
     /// Stack of IDs of struct definitions.
@@ -1572,15 +1644,24 @@ impl LintPass for MissingCopyImplementations {
     }
 }
 
-declare_lint!(DEPRECATED, Warn,
-              "detects use of #[deprecated] items")
+declare_lint! {
+    DEPRECATED,
+    Warn,
+    "detects use of #[deprecated] items"
+}
 
 // FIXME #6875: Change to Warn after std library stabilization is complete
-declare_lint!(EXPERIMENTAL, Allow,
-              "detects use of #[experimental] items")
+declare_lint! {
+    EXPERIMENTAL,
+    Allow,
+    "detects use of #[experimental] items"
+}
 
-declare_lint!(UNSTABLE, Allow,
-              "detects use of #[unstable] items (incl. items with no stability attribute)")
+declare_lint! {
+    UNSTABLE,
+    Allow,
+    "detects use of #[unstable] items (incl. items with no stability attribute)"
+}
 
 /// Checks for use of items with `#[deprecated]`, `#[experimental]` and
 /// `#[unstable]` attributes, or no stability attribute.
@@ -1738,47 +1819,89 @@ impl LintPass for Stability {
     }
 }
 
-declare_lint!(pub UNUSED_IMPORTS, Warn,
-              "imports that are never used")
+declare_lint! {
+    pub UNUSED_IMPORTS,
+    Warn,
+    "imports that are never used"
+}
 
-declare_lint!(pub UNUSED_EXTERN_CRATES, Allow,
-              "extern crates that are never used")
+declare_lint! {
+    pub UNUSED_EXTERN_CRATES,
+    Allow,
+    "extern crates that are never used"
+}
 
-declare_lint!(pub UNUSED_QUALIFICATIONS, Allow,
-              "detects unnecessarily qualified names")
+declare_lint! {
+    pub UNUSED_QUALIFICATIONS,
+    Allow,
+    "detects unnecessarily qualified names"
+}
 
-declare_lint!(pub UNKNOWN_LINTS, Warn,
-              "unrecognized lint attribute")
+declare_lint! {
+    pub UNKNOWN_LINTS,
+    Warn,
+    "unrecognized lint attribute"
+}
 
-declare_lint!(pub UNUSED_VARIABLES, Warn,
-              "detect variables which are not used in any way")
+declare_lint! {
+    pub UNUSED_VARIABLES,
+    Warn,
+    "detect variables which are not used in any way"
+}
 
-declare_lint!(pub UNUSED_ASSIGNMENTS, Warn,
-              "detect assignments that will never be read")
+declare_lint! {
+    pub UNUSED_ASSIGNMENTS,
+    Warn,
+    "detect assignments that will never be read"
+}
 
-declare_lint!(pub DEAD_CODE, Warn,
-              "detect unused, unexported items")
+declare_lint! {
+    pub DEAD_CODE,
+    Warn,
+    "detect unused, unexported items"
+}
 
-declare_lint!(pub UNREACHABLE_CODE, Warn,
-              "detects unreachable code paths")
+declare_lint! {
+    pub UNREACHABLE_CODE,
+    Warn,
+    "detects unreachable code paths"
+}
 
-declare_lint!(pub WARNINGS, Warn,
-              "mass-change the level for lints which produce warnings")
+declare_lint! {
+    pub WARNINGS,
+    Warn,
+    "mass-change the level for lints which produce warnings"
+}
 
-declare_lint!(pub UNKNOWN_FEATURES, Deny,
-              "unknown features found in crate-level #[feature] directives")
+declare_lint! {
+    pub UNKNOWN_FEATURES,
+    Deny,
+    "unknown features found in crate-level #[feature] directives"
+}
 
-declare_lint!(pub UNKNOWN_CRATE_TYPES, Deny,
-              "unknown crate type found in #[crate_type] directive")
+declare_lint! {
+    pub UNKNOWN_CRATE_TYPES,
+    Deny,
+    "unknown crate type found in #[crate_type] directive"
+}
 
-declare_lint!(pub VARIANT_SIZE_DIFFERENCES, Allow,
-              "detects enums with widely varying variant sizes")
+declare_lint! {
+    pub VARIANT_SIZE_DIFFERENCES,
+    Allow,
+    "detects enums with widely varying variant sizes"
+}
 
-declare_lint!(pub FAT_PTR_TRANSMUTES, Allow,
-              "detects transmutes of fat pointers")
+declare_lint! {
+    pub FAT_PTR_TRANSMUTES,
+    Allow,
+    "detects transmutes of fat pointers"
+}
 
-declare_lint!(pub MISSING_COPY_IMPLEMENTATIONS, Warn,
-              "detects potentially-forgotten implementations of `Copy`")
+declare_lint!{
+    pub MISSING_COPY_IMPLEMENTATIONS,
+    Warn,
+    "detects potentially-forgotten implementations of `Copy`"
+}
 
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 75f2fc81900..d8d9d653e62 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -171,17 +171,17 @@ impl LintStore {
             {$(
                 self.register_pass($sess, false, box builtin::$name as LintPassObject);
             )*}
-        ))
+        ));
 
         macro_rules! add_builtin_with_new ( ( $sess:ident, $($name:ident),*, ) => (
             {$(
                 self.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
             )*}
-        ))
+        ));
 
         macro_rules! add_lint_group ( ( $sess:ident, $name:expr, $($lint:ident),* ) => (
             self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
-        ))
+        ));
 
         add_builtin!(sess,
                      HardwiredLints,
@@ -204,21 +204,21 @@ impl LintStore {
                      UnusedAllocation,
                      Stability,
                      MissingCopyImplementations,
-        )
+        );
 
         add_builtin_with_new!(sess,
                               TypeLimits,
                               RawPointerDeriving,
                               MissingDoc,
-        )
+        );
 
         add_lint_group!(sess, "bad_style",
-                        NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS)
+                        NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS);
 
         add_lint_group!(sess, "unused",
                         UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE,
                         UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
-                        UNUSED_UNSAFE, PATH_STATEMENTS)
+                        UNUSED_UNSAFE, PATH_STATEMENTS);
 
         // We have one lint pass defined in this module.
         self.register_pass(sess, false, box GatherNodeLevels as LintPassObject);
@@ -318,7 +318,7 @@ pub struct Context<'a, 'tcx: 'a> {
 }
 
 /// Convenience macro for calling a `LintPass` method on every pass in the context.
-macro_rules! run_lints ( ($cx:expr, $f:ident, $($args:expr),*) => ({
+macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({
     // Move the vector of passes out of `$cx` so that we can
     // iterate over it mutably while passing `$cx` to the methods.
     let mut passes = $cx.lints.passes.take().unwrap();
@@ -326,7 +326,7 @@ macro_rules! run_lints ( ($cx:expr, $f:ident, $($args:expr),*) => ({
         obj.$f($cx, $($args),*);
     }
     $cx.lints.passes = Some(passes);
-}))
+}) }
 
 /// Parse the lint attributes into a vector, with `Err`s for malformed lint
 /// attributes. Writing this as an iterator is an enormous mess.
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 4b4ba2ab94c..79d57305f96 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -75,7 +75,7 @@ impl Lint {
 
 /// Build a `Lint` initializer.
 #[macro_export]
-macro_rules! lint_initializer (
+macro_rules! lint_initializer {
     ($name:ident, $level:ident, $desc:expr) => (
         ::rustc::lint::Lint {
             name: stringify!($name),
@@ -83,11 +83,11 @@ macro_rules! lint_initializer (
             desc: $desc,
         }
     )
-)
+}
 
 /// Declare a static item of type `&'static Lint`.
 #[macro_export]
-macro_rules! declare_lint (
+macro_rules! declare_lint {
     // FIXME(#14660): deduplicate
     (pub $name:ident, $level:ident, $desc:expr) => (
         pub static $name: &'static ::rustc::lint::Lint
@@ -97,17 +97,17 @@ macro_rules! declare_lint (
         static $name: &'static ::rustc::lint::Lint
             = &lint_initializer!($name, $level, $desc);
     );
-)
+}
 
 /// Declare a static `LintArray` and return it as an expression.
 #[macro_export]
-macro_rules! lint_array ( ($( $lint:expr ),*) => (
+macro_rules! lint_array { ($( $lint:expr ),*) => (
     {
         #[allow(non_upper_case_globals)]
         static array: LintArray = &[ $( &$lint ),* ];
         array
     }
-))
+) }
 
 pub type LintArray = &'static [&'static &'static Lint];
 
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 9b9d2ab42df..2a057da7db3 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -29,7 +29,7 @@ use syntax::parse::token;
 
 use rbml::io::SeekableMemWriter;
 
-macro_rules! mywrite( ($($arg:tt)*) => ({ write!($($arg)*); }) )
+macro_rules! mywrite { ($($arg:tt)*) => ({ write!($($arg)*); }) }
 
 pub struct ctxt<'a, 'tcx: 'a> {
     pub diag: &'a SpanHandler,
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 150bcbdd688..f0d52d1ac23 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -525,7 +525,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result Err("can't cast this type".to_string())
             })
-        )
+        );
 
         eval_const_expr_partial(tcx, &**base)
             .and_then(|val| define_casts!(val, {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 2cb78beff4c..aacb994e5a4 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -320,14 +320,14 @@ pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> {
 //
 // Note that this macro appears similar to try!(), but, unlike try!(),
 // it does not propagate the error.
-macro_rules! return_if_err(
+macro_rules! return_if_err {
     ($inp: expr) => (
         match $inp {
             Ok(v) => v,
             Err(()) => return
         }
     )
-)
+}
 
 /// Whether the elements of an overloaded operation are passed by value or by reference
 enum PassArgs {
diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index 5c2944f898e..ab685dd5dbc 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -224,7 +224,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
         for error in errors.iter() {
             match error.clone() {
                 ConcreteFailure(origin, sub, sup) => {
-                    debug!("processing ConcreteFailure")
+                    debug!("processing ConcreteFailure");
                     let trace = match origin {
                         infer::Subtype(trace) => Some(trace),
                         _ => None,
@@ -241,7 +241,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     }
                 }
                 SubSupConflict(var_origin, _, sub_r, _, sup_r) => {
-                    debug!("processing SubSupConflict")
+                    debug!("processing SubSupConflict");
                     match free_regions_from_same_fn(self.tcx, sub_r, sup_r) {
                         Some(ref same_frs) => {
                             var_origins.push(var_origin);
@@ -324,7 +324,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     _ => None
                 },
                 None => {
-                    debug!("no parent node of scope_id {}", scope_id)
+                    debug!("no parent node of scope_id {}", scope_id);
                     None
                 }
             }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 86b912a579f..0e05eb4dcdd 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -389,14 +389,14 @@ impl MutabilityCategory {
     }
 }
 
-macro_rules! if_ok(
+macro_rules! if_ok {
     ($inp: expr) => (
         match $inp {
             Ok(v) => { v }
             Err(e) => { return Err(e); }
         }
     )
-)
+}
 
 impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
     pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 84b69eb8471..b349b5ca0bf 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -1223,7 +1223,7 @@ pub fn mk_prim_t<'tcx>(primitive: &'tcx TyS<'static>) -> Ty<'tcx> {
 
 // Do not change these from static to const, interning types requires
 // the primitives to have a significant address.
-macro_rules! def_prim_tys(
+macro_rules! def_prim_tys {
     ($($name:ident -> $sty:expr;)*) => (
         $(#[inline] pub fn $name<'tcx>() -> Ty<'tcx> {
             static PRIM_TY: TyS<'static> = TyS {
@@ -1234,7 +1234,7 @@ macro_rules! def_prim_tys(
             mk_prim_t(&PRIM_TY)
         })*
     )
-)
+}
 
 def_prim_tys!{
     mk_bool ->  ty_bool;
@@ -2739,7 +2739,7 @@ pub struct TypeContents {
 
 impl Copy for TypeContents {}
 
-macro_rules! def_type_content_sets(
+macro_rules! def_type_content_sets {
     (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
         #[allow(non_snake_case)]
         mod $mname {
@@ -2750,9 +2750,9 @@ macro_rules! def_type_content_sets(
              )+
         }
     }
-)
+}
 
-def_type_content_sets!(
+def_type_content_sets! {
     mod TC {
         None                                = 0b0000_0000__0000_0000__0000,
 
@@ -2790,7 +2790,7 @@ def_type_content_sets!(
         // All bits
         All                                 = 0b1111_1111__1111_1111__1111
     }
-)
+}
 
 impl TypeContents {
     pub fn when(&self, cond: bool) -> TypeContents {
@@ -3113,7 +3113,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
 
             ty_open(ty) => {
                 let result = tc_ty(cx, ty, cache);
-                assert!(!result.is_sized(cx))
+                assert!(!result.is_sized(cx));
                 result.unsafe_pointer() | TC::Nonsized
             }
 
@@ -3644,7 +3644,7 @@ pub fn unsized_part_of_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
             let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
                 .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
             // Exactly one of the fields must be unsized.
-            assert!(unsized_fields.len() == 1)
+            assert!(unsized_fields.len() == 1);
 
             unsized_part_of_type(cx, unsized_fields[0])
         }
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index e0fe87d6d06..892a8004fec 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -23,7 +23,8 @@ use syntax::visit;
 
 use std::collections::HashSet;
 
-macro_rules! weak_lang_items( ($($name:ident, $item:ident, $sym:ident;)*) => (
+macro_rules! weak_lang_items {
+    ($($name:ident, $item:ident, $sym:ident;)*) => (
 
 struct Context<'a> {
     sess: &'a Session,
@@ -115,10 +116,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
     }
 }
 
-) )
+) }
 
-weak_lang_items!(
+weak_lang_items! {
     panic_fmt,          PanicFmtLangItem,            rust_begin_unwind;
     stack_exhausted,    StackExhaustedLangItem,     rust_stack_exhausted;
     eh_personality,     EhPersonalityLangItem,      rust_eh_personality;
-)
+}
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index b3b44b60b6e..59da0af417c 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -239,17 +239,17 @@ pub enum CrateType {
 
 impl Copy for CrateType {}
 
-macro_rules! debugging_opts(
+macro_rules! debugging_opts {
     ([ $opt:ident ] $cnt:expr ) => (
         pub const $opt: u64 = 1 << $cnt;
     );
     ([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
         pub const $opt: u64 = 1 << $cnt;
-        debugging_opts!([ $($rest),* ] $cnt + 1)
+        debugging_opts! { [ $($rest),* ] $cnt + 1 }
     )
-)
+}
 
-debugging_opts!(
+debugging_opts! {
     [
         VERBOSE,
         TIME_PASSES,
@@ -280,7 +280,7 @@ debugging_opts!(
         PRINT_REGION_GRAPH
     ]
     0
-)
+}
 
 pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
     vec![("verbose", "in general, enable more debug printouts", VERBOSE),
@@ -354,7 +354,7 @@ impl Passes {
 /// cgsetters module which is a bunch of generated code to parse an option into
 /// its respective field in the struct. There are a few hand-written parsers for
 /// parsing specific types of values in this module.
-macro_rules! cgoptions(
+macro_rules! cgoptions {
     ($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
 (
     #[deriving(Clone)]
@@ -469,9 +469,9 @@ macro_rules! cgoptions(
             }
         }
     }
-) )
+) }
 
-cgoptions!(
+cgoptions! {
     ar: Option = (None, parse_opt_string,
         "tool to assemble archives with"),
     linker: Option = (None, parse_opt_string,
@@ -520,7 +520,7 @@ cgoptions!(
         "print remarks for these optimization passes (space separated, or \"all\")"),
     no_stack_check: bool = (false, parse_bool,
         "disable checks for stack exhaustion (a memory-safety hazard!)"),
-)
+}
 
 pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
 {
diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs
index 1587104ca49..074341ccff4 100644
--- a/src/librustc_back/sha2.rs
+++ b/src/librustc_back/sha2.rs
@@ -349,7 +349,7 @@ impl Engine256State {
         macro_rules! schedule_round( ($t:expr) => (
                 w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16];
                 )
-        )
+        );
 
         macro_rules! sha2_round(
             ($A:ident, $B:ident, $C:ident, $D:ident,
@@ -360,7 +360,7 @@ impl Engine256State {
                     $H += sum0($A) + maj($A, $B, $C);
                 }
              )
-        )
+        );
 
         read_u32v_be(w[mut 0..16], data);
 
@@ -454,7 +454,7 @@ impl Engine256 {
     }
 
     fn input(&mut self, input: &[u8]) {
-        assert!(!self.finished)
+        assert!(!self.finished);
         // Assumes that input.len() can be converted to u64 without overflow
         self.length_bits = add_bytes_to_bits(self.length_bits, input.len() as u64);
         let self_state = &mut self.state;
diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs
index 116cff49153..98fa659ba55 100644
--- a/src/librustc_back/svh.rs
+++ b/src/librustc_back/svh.rs
@@ -340,14 +340,17 @@ mod svh_visitor {
                 // expensive; a direct content-based hash on token
                 // trees might be faster. Implementing this is far
                 // easier in short term.
-                let macro_defn_as_string =
-                    pprust::to_string(|pp_state| pp_state.print_mac(macro));
+                let macro_defn_as_string = pprust::to_string(|pp_state| {
+                    pp_state.print_mac(macro, token::Paren)
+                });
                 macro_defn_as_string.hash(self.st);
             } else {
                 // It is not possible to observe any kind of macro
                 // invocation at this stage except `macro_rules!`.
                 panic!("reached macro somehow: {}",
-                      pprust::to_string(|pp_state| pp_state.print_mac(macro)));
+                      pprust::to_string(|pp_state| {
+                          pp_state.print_mac(macro, token::Paren)
+                      }));
             }
 
             visit::walk_mac(self, macro);
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 76adc4e472f..d12cb356e3f 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -256,7 +256,7 @@ impl Target {
                         )
                     );
             } );
-        )
+        );
 
         key!(cpu);
         key!(linker);
@@ -325,7 +325,7 @@ impl Target {
                     }
                 }
             )
-        )
+        );
 
         load_specific!(
             x86_64_unknown_linux_gnu,
@@ -348,7 +348,7 @@ impl Target {
 
             x86_64_pc_windows_gnu,
             i686_pc_windows_gnu
-        )
+        );
 
 
         let path = Path::new(target);
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index a3fb91aced0..7f469db3186 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -39,14 +39,14 @@ use syntax::visit;
 use syntax::visit::{Visitor, FnKind};
 use syntax::ast::{FnDecl, Block, NodeId};
 
-macro_rules! if_ok(
+macro_rules! if_ok {
     ($inp: expr) => (
         match $inp {
             Ok(v) => { v }
             Err(e) => { return Err(e); }
         }
     )
-)
+}
 
 pub mod doc;
 
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index b052c8755cb..8b036b25015 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -2290,5 +2290,5 @@ pub unsafe fn static_link_hack_this_sucks() {
 // Works to the above fix for #15460 to ensure LLVM dependencies that
 // are only used by rustllvm don't get stripped by the linker.
 mod llvmdeps {
-    include!(env!("CFG_LLVM_LINKAGE_FILE"))
+    include! { env!("CFG_LLVM_LINKAGE_FILE") }
 }
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index b0512925719..bf17043f0e4 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -676,7 +676,7 @@ fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 // pattern.  Note that, because the macro is well-typed, either ALL of the
 // matches should fit that sort of pattern or NONE (however, some of the
 // matches may be wildcards like _ or identifiers).
-macro_rules! any_pat (
+macro_rules! any_pat {
     ($m:expr, $col:expr, $pattern:pat) => (
         ($m).iter().any(|br| {
             match br.pats[$col].node {
@@ -685,7 +685,7 @@ macro_rules! any_pat (
             }
         })
     )
-)
+}
 
 fn any_uniq_pat(m: &[Match], col: uint) -> bool {
     any_pat!(m, col, ast::PatBox(_))
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index 991333d8f07..0c2c86fc32d 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -147,7 +147,7 @@ pub fn represent_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     }
 
     let repr = Rc::new(represent_type_uncached(cx, t));
-    debug!("Represented as: {}", repr)
+    debug!("Represented as: {}", repr);
     cx.adt_reprs().borrow_mut().insert(t, repr.clone());
     repr
 }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 83779ffbe16..f1d839e916d 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -103,9 +103,11 @@ use syntax::visit::Visitor;
 use syntax::visit;
 use syntax::{ast, ast_util, ast_map};
 
-thread_local!(static TASK_LOCAL_INSN_KEY: RefCell>> = {
-    RefCell::new(None)
-})
+thread_local! {
+    static TASK_LOCAL_INSN_KEY: RefCell>> = {
+        RefCell::new(None)
+    }
+}
 
 pub fn with_insn_ctxt(blk: F) where
     F: FnOnce(&[&'static str]),
diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs
index 3b5197594a1..89fa6a72e88 100644
--- a/src/librustc_trans/trans/context.rs
+++ b/src/librustc_trans/trans/context.rs
@@ -749,10 +749,10 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option (Type::struct_(ccx, &[$($field_ty),*], false))
-    )
+    );
 
     let i8p = Type::i8p(ccx);
     let void = Type::void(ccx);
@@ -886,7 +886,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option t_f32);
     compatible_ifn!("llvm.copysign.f64", copysign(t_f64, t_f64) -> t_f64);
diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs
index 531b22c8fb5..e32b5792e5d 100644
--- a/src/librustc_trans/trans/datum.rs
+++ b/src/librustc_trans/trans/datum.rs
@@ -583,7 +583,7 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> {
     }
 
     pub fn to_llbool<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef {
-        assert!(ty::type_is_bool(self.ty))
+        assert!(ty::type_is_bool(self.ty));
         self.to_llscalarish(bcx)
     }
 }
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index c97e6a09529..e9730f7af0e 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -634,7 +634,7 @@ impl<'tcx> TypeMap<'tcx> {
 
 // Returns from the enclosing function if the type metadata with the given
 // unique id can be found in the type map
-macro_rules! return_if_metadata_created_in_meantime(
+macro_rules! return_if_metadata_created_in_meantime {
     ($cx: expr, $unique_type_id: expr) => (
         match debug_context($cx).type_map
                                 .borrow()
@@ -643,7 +643,7 @@ macro_rules! return_if_metadata_created_in_meantime(
             None => { /* proceed normally */ }
         };
     )
-)
+}
 
 
 /// A context object for maintaining all state needed by the debuginfo module.
diff --git a/src/librustc_trans/trans/macros.rs b/src/librustc_trans/trans/macros.rs
index 313280cb7a8..ab202975bfc 100644
--- a/src/librustc_trans/trans/macros.rs
+++ b/src/librustc_trans/trans/macros.rs
@@ -10,7 +10,7 @@
 
 #![macro_escape]
 
-macro_rules! unpack_datum(
+macro_rules! unpack_datum {
     ($bcx: ident, $inp: expr) => (
         {
             let db = $inp;
@@ -18,9 +18,9 @@ macro_rules! unpack_datum(
             db.datum
         }
     )
-)
+}
 
-macro_rules! unpack_result(
+macro_rules! unpack_result {
     ($bcx: ident, $inp: expr) => (
         {
             let db = $inp;
@@ -28,4 +28,4 @@ macro_rules! unpack_result(
             db.val
         }
     )
-)
+}
diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs
index 387af7390b2..70b1e99ce8e 100644
--- a/src/librustc_trans/trans/type_.rs
+++ b/src/librustc_trans/trans/type_.rs
@@ -33,9 +33,9 @@ pub struct Type {
 
 impl Copy for Type {}
 
-macro_rules! ty (
+macro_rules! ty {
     ($e:expr) => ( Type::from_ref(unsafe { $e }))
-)
+}
 
 /// Wrapper for LLVM TypeRef
 impl Type {
diff --git a/src/librustc_trans/trans/value.rs b/src/librustc_trans/trans/value.rs
index 81488b99b67..c7cf86fb184 100644
--- a/src/librustc_trans/trans/value.rs
+++ b/src/librustc_trans/trans/value.rs
@@ -18,14 +18,14 @@ pub struct Value(pub ValueRef);
 
 impl Copy for Value {}
 
-macro_rules! opt_val ( ($e:expr) => (
+macro_rules! opt_val { ($e:expr) => (
     unsafe {
         match $e {
             p if p.is_not_null() => Some(Value(p)),
             _ => None
         }
     }
-))
+) }
 
 /// Wrapper for LLVM ValueRef
 impl Value {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 6cfe24342e2..2ec7e2c3883 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -199,14 +199,14 @@ pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 // check failed (or will fail, when the error is uncovered and
 // reported during writeback). In this case, we just ignore this part
 // of the code and don't try to add any more region constraints.
-macro_rules! ignore_err(
+macro_rules! ignore_err {
     ($inp: expr) => (
         match $inp {
             Ok(v) => v,
             Err(()) => return
         }
     )
-)
+}
 
 // Stores parameters for a potential call to link_region()
 // to perform if an upvar reference is marked unique/mutable after
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index ecd3cafd91f..9657bf82a8b 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -10,16 +10,18 @@
 
 #![allow(non_snake_case)]
 
-register_diagnostic!(E0001, r##"
+register_diagnostic! {
+    E0001,
+r##"
     This error suggests that the expression arm corresponding to the noted pattern
     will never be reached as for all possible values of the expression being matched,
     one of the preceeding patterns will match.
 
     This means that perhaps some of the preceeding patterns are too general, this
     one is too specific or the ordering is incorrect.
-"##)
+"## }
 
-register_diagnostics!(
+register_diagnostics! {
     E0002,
     E0003,
     E0004,
@@ -156,4 +158,4 @@ register_diagnostics!(
     E0181,
     E0182,
     E0183
-)
+}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 6a2929beca2..1e243906b23 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -779,7 +779,7 @@ The counts do not include methods or trait
 implementations that are visible only through a re-exported type.",
 stable, unstable, experimental, deprecated, unmarked,
 name=self.name));
-        try!(write!(f, ""))
+        try!(write!(f, "
")); try!(fmt_inner(f, &mut context, self)); write!(f, "
") } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index cba58db7c7f..8b2f644dfe3 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -149,12 +149,12 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> { thread_local!(static USED_HEADER_MAP: RefCell> = { RefCell::new(HashMap::new()) -}) -thread_local!(static TEST_IDX: Cell = Cell::new(0)) +}); +thread_local!(static TEST_IDX: Cell = Cell::new(0)); thread_local!(pub static PLAYGROUND_KRATE: RefCell>> = { RefCell::new(None) -}) +}); pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1977b6320d0..3e6cffa1304 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -246,9 +246,9 @@ struct IndexItem { // TLS keys used to carry information around during rendering. -thread_local!(static CACHE_KEY: RefCell> = Default::default()) +thread_local!(static CACHE_KEY: RefCell> = Default::default()); thread_local!(pub static CURRENT_LOCATION_KEY: RefCell> = - RefCell::new(Vec::new())) + RefCell::new(Vec::new())); /// Generates the documentation for `crate` into the directory `dst` pub fn run(mut krate: clean::Crate, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 78117c9cb06..5a91298acdf 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -93,7 +93,7 @@ static DEFAULT_PASSES: &'static [&'static str] = &[ thread_local!(pub static ANALYSISKEY: Rc>> = { Rc::new(RefCell::new(None)) -}) +}); struct Output { krate: clean::Crate, diff --git a/src/librustrt/macros.rs b/src/librustrt/macros.rs index d4e92736a9d..45144308535 100644 --- a/src/librustrt/macros.rs +++ b/src/librustrt/macros.rs @@ -15,22 +15,22 @@ #![macro_escape] -macro_rules! rterrln ( +macro_rules! rterrln { ($fmt:expr $($arg:tt)*) => ( { format_args!(::util::dumb_print, concat!($fmt, "\n") $($arg)*) } ) -) +} // Some basic logging. Enabled by passing `--cfg rtdebug` to the libstd build. -macro_rules! rtdebug ( +macro_rules! rtdebug { ($($arg:tt)*) => ( { if cfg!(rtdebug) { rterrln!($($arg)*) } }) -) +} -macro_rules! rtassert ( +macro_rules! rtassert { ( $arg:expr ) => ( { if ::util::ENFORCE_SANITY { if !$arg { @@ -38,9 +38,9 @@ macro_rules! rtassert ( } } } ) -) +} -macro_rules! rtabort ( +macro_rules! rtabort { ($($arg:tt)*) => (format_args!(::util::abort, $($arg)*)) -) +} diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 59faf75c0c3..8ded963b928 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -385,7 +385,7 @@ mod tests { #[test] fn test_from_base64_invalid_char() { - assert!("Zm$=".from_base64().is_err()) + assert!("Zm$=".from_base64().is_err()); assert!("Zg==$".from_base64().is_err()); } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index c811a16e2b1..e7b2d0c8eba 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -1970,7 +1970,7 @@ impl Decoder { } } -macro_rules! expect( +macro_rules! expect { ($e:expr, Null) => ({ match $e { Json::Null => Ok(()), @@ -1987,7 +1987,7 @@ macro_rules! expect( } } }) -) +} macro_rules! read_primitive { ($name:ident, $ty:ty) => { @@ -2020,16 +2020,16 @@ impl ::Decoder for Decoder { expect!(self.pop(), Null) } - read_primitive!(read_uint, uint) - read_primitive!(read_u8, u8) - read_primitive!(read_u16, u16) - read_primitive!(read_u32, u32) - read_primitive!(read_u64, u64) - read_primitive!(read_int, int) - read_primitive!(read_i8, i8) - read_primitive!(read_i16, i16) - read_primitive!(read_i32, i32) - read_primitive!(read_i64, i64) + read_primitive! { read_uint, uint } + read_primitive! { read_u8, u8 } + read_primitive! { read_u16, u16 } + read_primitive! { read_u32, u32 } + read_primitive! { read_u64, u64 } + read_primitive! { read_int, int } + read_primitive! { read_i8, i8 } + read_primitive! { read_i16, i16 } + read_primitive! { read_i32, i32 } + read_primitive! { read_i64, i64 } fn read_f32(&mut self) -> DecodeResult { self.read_f64().map(|x| x as f32) } @@ -2298,25 +2298,25 @@ pub trait ToJson for Sized? { fn to_json(&self) -> Json; } -macro_rules! to_json_impl_i64( +macro_rules! to_json_impl_i64 { ($($t:ty), +) => ( $(impl ToJson for $t { fn to_json(&self) -> Json { Json::I64(*self as i64) } })+ ) -) +} -to_json_impl_i64!(int, i8, i16, i32, i64) +to_json_impl_i64! { int, i8, i16, i32, i64 } -macro_rules! to_json_impl_u64( +macro_rules! to_json_impl_u64 { ($($t:ty), +) => ( $(impl ToJson for $t { fn to_json(&self) -> Json { Json::U64(*self as u64) } })+ ) -) +} -to_json_impl_u64!(uint, u8, u16, u32, u64) +to_json_impl_u64! { uint, u8, u16, u32, u64 } impl ToJson for Json { fn to_json(&self) -> Json { self.clone() } @@ -2730,7 +2730,7 @@ mod tests { ); } - macro_rules! check_encoder_for_simple( + macro_rules! check_encoder_for_simple { ($value:expr, $expected:expr) => ({ let s = with_str_writer(|writer| { let mut encoder = Encoder::new(writer); @@ -2744,7 +2744,7 @@ mod tests { }); assert_eq!(s, $expected); }) - ) + } #[test] fn test_write_some() { @@ -2948,7 +2948,7 @@ mod tests { #[test] fn test_decode_tuple() { let t: (uint, uint, uint) = super::decode("[1, 2, 3]").unwrap(); - assert_eq!(t, (1u, 2, 3)) + assert_eq!(t, (1u, 2, 3)); let t: (uint, string::String) = super::decode("[1, \"two\"]").unwrap(); assert_eq!(t, (1u, "two".into_string())); diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 0e0d3b4115b..00c5158309e 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -474,7 +474,9 @@ impl,T:Decodable> Decodable for Option { } } -macro_rules! peel(($name:ident, $($other:ident,)*) => (tuple!($($other,)*))) +macro_rules! peel { + ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) +} /// Evaluates to the number of identifiers passed to it, for example: `count_idents!(a, b, c) == 3 macro_rules! count_idents { @@ -482,7 +484,7 @@ macro_rules! count_idents { ($_i:ident $(, $rest:ident)*) => { 1 + count_idents!($($rest),*) } } -macro_rules! tuple ( +macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( impl,$($name:Decodable),*> Decodable for ($($name,)*) { @@ -511,9 +513,9 @@ macro_rules! tuple ( }) } } - peel!($($name,)*) + peel! { $($name,)* } ) -) +} tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index edf88a84893..c436de0d193 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -638,14 +638,14 @@ mod tests { use char::from_u32; use str::StrPrelude; - macro_rules! v2ascii ( + macro_rules! v2ascii { ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]); (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]); - ) + } - macro_rules! vec2ascii ( + macro_rules! vec2ascii { ($($e:expr),*) => ([$(Ascii{chr:$e}),*].to_vec()); - ) + } #[test] fn test_ascii() { @@ -788,7 +788,7 @@ mod tests { let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_upper(), - (from_u32(upper).unwrap()).to_string()) + (from_u32(upper).unwrap()).to_string()); i += 1; } } @@ -804,7 +804,7 @@ mod tests { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lower(), - (from_u32(lower).unwrap()).to_string()) + (from_u32(lower).unwrap()).to_string()); i += 1; } } @@ -820,7 +820,7 @@ mod tests { let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_upper(), - (from_u32(upper).unwrap()).to_string()) + (from_u32(upper).unwrap()).to_string()); i += 1; } } @@ -837,7 +837,7 @@ mod tests { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lower(), - (from_u32(lower).unwrap()).to_string()) + (from_u32(lower).unwrap()).to_string()); i += 1; } } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 0ff29a94f2f..04dd5afdfa2 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1471,7 +1471,7 @@ mod test_map { assert_eq!(*m.get(&2).unwrap(), 4); } - thread_local!(static DROP_VECTOR: RefCell> = RefCell::new(Vec::new())) + thread_local! { static DROP_VECTOR: RefCell> = RefCell::new(Vec::new()) } #[deriving(Hash, PartialEq, Eq)] struct Dropable { diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index 72ddbe19f54..29a7b0dd0cc 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -136,7 +136,7 @@ //! select! { //! val = rx.recv() => println!("Received {}", val), //! () = timeout.recv() => { -//! println!("timed out, total time was more than 10 seconds") +//! println!("timed out, total time was more than 10 seconds"); //! break; //! } //! } @@ -160,7 +160,7 @@ //! select! { //! val = rx.recv() => println!("Received {}", val), //! () = timeout.recv() => { -//! println!("timed out, no message received in 5 seconds") +//! println!("timed out, no message received in 5 seconds"); //! break; //! } //! } @@ -331,7 +331,7 @@ use rustrt::task::BlockedTask; pub use comm::select::{Select, Handle}; -macro_rules! test ( +macro_rules! test { { fn $name:ident() $b:block $(#[$a:meta])*} => ( mod $name { #![allow(unused_imports)] @@ -347,7 +347,7 @@ macro_rules! test ( $(#[$a])* #[test] fn f() { $b } } ) -) +} mod oneshot; mod select; @@ -1036,70 +1036,70 @@ mod test { } } - test!(fn smoke() { + test! { fn smoke() { let (tx, rx) = channel::(); tx.send(1); assert_eq!(rx.recv(), 1); - }) + } } - test!(fn drop_full() { + test! { fn drop_full() { let (tx, _rx) = channel(); tx.send(box 1i); - }) + } } - test!(fn drop_full_shared() { + test! { fn drop_full_shared() { let (tx, _rx) = channel(); drop(tx.clone()); drop(tx.clone()); tx.send(box 1i); - }) + } } - test!(fn smoke_shared() { + test! { fn smoke_shared() { let (tx, rx) = channel::(); tx.send(1); assert_eq!(rx.recv(), 1); let tx = tx.clone(); tx.send(1); assert_eq!(rx.recv(), 1); - }) + } } - test!(fn smoke_threads() { + test! { fn smoke_threads() { let (tx, rx) = channel::(); spawn(move|| { tx.send(1); }); assert_eq!(rx.recv(), 1); - }) + } } - test!(fn smoke_port_gone() { + test! { fn smoke_port_gone() { let (tx, rx) = channel::(); drop(rx); tx.send(1); - } #[should_fail]) + } #[should_fail] } - test!(fn smoke_shared_port_gone() { + test! { fn smoke_shared_port_gone() { let (tx, rx) = channel::(); drop(rx); tx.send(1); - } #[should_fail]) + } #[should_fail] } - test!(fn smoke_shared_port_gone2() { + test! { fn smoke_shared_port_gone2() { let (tx, rx) = channel::(); drop(rx); let tx2 = tx.clone(); drop(tx); tx2.send(1); - } #[should_fail]) + } #[should_fail] } - test!(fn port_gone_concurrent() { + test! { fn port_gone_concurrent() { let (tx, rx) = channel::(); spawn(move|| { rx.recv(); }); loop { tx.send(1) } - } #[should_fail]) + } #[should_fail] } - test!(fn port_gone_concurrent_shared() { + test! { fn port_gone_concurrent_shared() { let (tx, rx) = channel::(); let tx2 = tx.clone(); spawn(move|| { @@ -1109,32 +1109,32 @@ mod test { tx.send(1); tx2.send(1); } - } #[should_fail]) + } #[should_fail] } - test!(fn smoke_chan_gone() { + test! { fn smoke_chan_gone() { let (tx, rx) = channel::(); drop(tx); rx.recv(); - } #[should_fail]) + } #[should_fail] } - test!(fn smoke_chan_gone_shared() { + test! { fn smoke_chan_gone_shared() { let (tx, rx) = channel::<()>(); let tx2 = tx.clone(); drop(tx); drop(tx2); rx.recv(); - } #[should_fail]) + } #[should_fail] } - test!(fn chan_gone_concurrent() { + test! { fn chan_gone_concurrent() { let (tx, rx) = channel::(); spawn(move|| { tx.send(1); tx.send(1); }); loop { rx.recv(); } - } #[should_fail]) + } #[should_fail] } - test!(fn stress() { + test! { fn stress() { let (tx, rx) = channel::(); spawn(move|| { for _ in range(0u, 10000) { tx.send(1i); } @@ -1142,9 +1142,9 @@ mod test { for _ in range(0u, 10000) { assert_eq!(rx.recv(), 1); } - }) + } } - test!(fn stress_shared() { + test! { fn stress_shared() { static AMT: uint = 10000; static NTHREADS: uint = 8; let (tx, rx) = channel::(); @@ -1169,7 +1169,7 @@ mod test { } drop(tx); drx.recv(); - }) + } } #[test] fn send_from_outside_runtime() { @@ -1231,26 +1231,26 @@ mod test { rx3.recv(); } - test!(fn oneshot_single_thread_close_port_first() { + test! { fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending let (_tx, rx) = channel::(); drop(rx); - }) + } } - test!(fn oneshot_single_thread_close_chan_first() { + test! { fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending let (tx, _rx) = channel::(); drop(tx); - }) + } } - test!(fn oneshot_single_thread_send_port_close() { + test! { fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed let (tx, rx) = channel::>(); drop(rx); tx.send(box 0); - } #[should_fail]) + } #[should_fail] } - test!(fn oneshot_single_thread_recv_chan_close() { + test! { fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = task::try(move|| { let (tx, rx) = channel::(); @@ -1259,67 +1259,67 @@ mod test { }); // What is our res? assert!(res.is_err()); - }) + } } - test!(fn oneshot_single_thread_send_then_recv() { + test! { fn oneshot_single_thread_send_then_recv() { let (tx, rx) = channel::>(); tx.send(box 10); assert!(rx.recv() == box 10); - }) + } } - test!(fn oneshot_single_thread_try_send_open() { + test! { fn oneshot_single_thread_try_send_open() { let (tx, rx) = channel::(); assert!(tx.send_opt(10).is_ok()); assert!(rx.recv() == 10); - }) + } } - test!(fn oneshot_single_thread_try_send_closed() { + test! { fn oneshot_single_thread_try_send_closed() { let (tx, rx) = channel::(); drop(rx); assert!(tx.send_opt(10).is_err()); - }) + } } - test!(fn oneshot_single_thread_try_recv_open() { + test! { fn oneshot_single_thread_try_recv_open() { let (tx, rx) = channel::(); tx.send(10); assert!(rx.recv_opt() == Ok(10)); - }) + } } - test!(fn oneshot_single_thread_try_recv_closed() { + test! { fn oneshot_single_thread_try_recv_closed() { let (tx, rx) = channel::(); drop(tx); assert!(rx.recv_opt() == Err(())); - }) + } } - test!(fn oneshot_single_thread_peek_data() { + test! { fn oneshot_single_thread_peek_data() { let (tx, rx) = channel::(); - assert_eq!(rx.try_recv(), Err(Empty)) + assert_eq!(rx.try_recv(), Err(Empty)); tx.send(10); assert_eq!(rx.try_recv(), Ok(10)); - }) + } } - test!(fn oneshot_single_thread_peek_close() { + test! { fn oneshot_single_thread_peek_close() { let (tx, rx) = channel::(); drop(tx); assert_eq!(rx.try_recv(), Err(Disconnected)); assert_eq!(rx.try_recv(), Err(Disconnected)); - }) + } } - test!(fn oneshot_single_thread_peek_open() { + test! { fn oneshot_single_thread_peek_open() { let (_tx, rx) = channel::(); assert_eq!(rx.try_recv(), Err(Empty)); - }) + } } - test!(fn oneshot_multi_task_recv_then_send() { + test! { fn oneshot_multi_task_recv_then_send() { let (tx, rx) = channel::>(); spawn(move|| { assert!(rx.recv() == box 10); }); tx.send(box 10); - }) + } } - test!(fn oneshot_multi_task_recv_then_close() { + test! { fn oneshot_multi_task_recv_then_close() { let (tx, rx) = channel::>(); spawn(move|| { drop(tx); @@ -1328,9 +1328,9 @@ mod test { assert!(rx.recv() == box 10); }); assert!(res.is_err()); - }) + } } - test!(fn oneshot_multi_thread_close_stress() { + test! { fn oneshot_multi_thread_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); spawn(move|| { @@ -1338,9 +1338,9 @@ mod test { }); drop(tx); } - }) + } } - test!(fn oneshot_multi_thread_send_close_stress() { + test! { fn oneshot_multi_thread_send_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); spawn(move|| { @@ -1350,9 +1350,9 @@ mod test { tx.send(1); }); } - }) + } } - test!(fn oneshot_multi_thread_recv_close_stress() { + test! { fn oneshot_multi_thread_recv_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); spawn(move|| { @@ -1367,9 +1367,9 @@ mod test { }); }); } - }) + } } - test!(fn oneshot_multi_thread_send_recv_stress() { + test! { fn oneshot_multi_thread_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel(); spawn(move|| { @@ -1379,9 +1379,9 @@ mod test { assert!(rx.recv() == box 10i); }); } - }) + } } - test!(fn stream_send_recv_stress() { + test! { fn stream_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel(); @@ -1406,16 +1406,16 @@ mod test { }); } } - }) + } } - test!(fn recv_a_lot() { + test! { fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = channel(); for _ in range(0i, 10000) { tx.send(()); } for _ in range(0i, 10000) { rx.recv(); } - }) + } } - test!(fn shared_chan_stress() { + test! { fn shared_chan_stress() { let (tx, rx) = channel(); let total = stress_factor() + 100; for _ in range(0, total) { @@ -1428,9 +1428,9 @@ mod test { for _ in range(0, total) { rx.recv(); } - }) + } } - test!(fn test_nested_recv_iter() { + test! { fn test_nested_recv_iter() { let (tx, rx) = channel::(); let (total_tx, total_rx) = channel::(); @@ -1447,9 +1447,9 @@ mod test { tx.send(2); drop(tx); assert_eq!(total_rx.recv(), 6); - }) + } } - test!(fn test_recv_iter_break() { + test! { fn test_recv_iter_break() { let (tx, rx) = channel::(); let (count_tx, count_rx) = channel(); @@ -1471,9 +1471,9 @@ mod test { let _ = tx.send_opt(2); drop(tx); assert_eq!(count_rx.recv(), 4); - }) + } } - test!(fn try_recv_states() { + test! { fn try_recv_states() { let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::<()>(); let (tx3, rx3) = channel::<()>(); @@ -1494,11 +1494,11 @@ mod test { tx2.send(()); rx3.recv(); assert_eq!(rx1.try_recv(), Err(Disconnected)); - }) + } } // This bug used to end up in a livelock inside of the Receiver destructor // because the internal state of the Shared packet was corrupted - test!(fn destroy_upgraded_shared_port_when_sender_still_active() { + test! { fn destroy_upgraded_shared_port_when_sender_still_active() { let (tx, rx) = channel(); let (tx2, rx2) = channel(); spawn(move|| { @@ -1516,9 +1516,9 @@ mod test { // wait for the child task to exit before we exit rx2.recv(); - }) + } } - test!(fn sends_off_the_runtime() { + test! { fn sends_off_the_runtime() { use rustrt::thread::Thread; let (tx, rx) = channel(); @@ -1531,9 +1531,9 @@ mod test { rx.recv(); } t.join(); - }) + } } - test!(fn try_recvs_off_the_runtime() { + test! { fn try_recvs_off_the_runtime() { use rustrt::thread::Thread; let (tx, rx) = channel(); @@ -1554,7 +1554,7 @@ mod test { } t.join(); pdone.recv(); - }) + } } } #[cfg(test)] @@ -1569,57 +1569,57 @@ mod sync_tests { } } - test!(fn smoke() { + test! { fn smoke() { let (tx, rx) = sync_channel::(1); tx.send(1); assert_eq!(rx.recv(), 1); - }) + } } - test!(fn drop_full() { + test! { fn drop_full() { let (tx, _rx) = sync_channel(1); tx.send(box 1i); - }) + } } - test!(fn smoke_shared() { + test! { fn smoke_shared() { let (tx, rx) = sync_channel::(1); tx.send(1); assert_eq!(rx.recv(), 1); let tx = tx.clone(); tx.send(1); assert_eq!(rx.recv(), 1); - }) + } } - test!(fn smoke_threads() { + test! { fn smoke_threads() { let (tx, rx) = sync_channel::(0); spawn(move|| { tx.send(1); }); assert_eq!(rx.recv(), 1); - }) + } } - test!(fn smoke_port_gone() { + test! { fn smoke_port_gone() { let (tx, rx) = sync_channel::(0); drop(rx); tx.send(1); - } #[should_fail]) + } #[should_fail] } - test!(fn smoke_shared_port_gone2() { + test! { fn smoke_shared_port_gone2() { let (tx, rx) = sync_channel::(0); drop(rx); let tx2 = tx.clone(); drop(tx); tx2.send(1); - } #[should_fail]) + } #[should_fail] } - test!(fn port_gone_concurrent() { + test! { fn port_gone_concurrent() { let (tx, rx) = sync_channel::(0); spawn(move|| { rx.recv(); }); loop { tx.send(1) } - } #[should_fail]) + } #[should_fail] } - test!(fn port_gone_concurrent_shared() { + test! { fn port_gone_concurrent_shared() { let (tx, rx) = sync_channel::(0); let tx2 = tx.clone(); spawn(move|| { @@ -1629,32 +1629,32 @@ mod sync_tests { tx.send(1); tx2.send(1); } - } #[should_fail]) + } #[should_fail] } - test!(fn smoke_chan_gone() { + test! { fn smoke_chan_gone() { let (tx, rx) = sync_channel::(0); drop(tx); rx.recv(); - } #[should_fail]) + } #[should_fail] } - test!(fn smoke_chan_gone_shared() { + test! { fn smoke_chan_gone_shared() { let (tx, rx) = sync_channel::<()>(0); let tx2 = tx.clone(); drop(tx); drop(tx2); rx.recv(); - } #[should_fail]) + } #[should_fail] } - test!(fn chan_gone_concurrent() { + test! { fn chan_gone_concurrent() { let (tx, rx) = sync_channel::(0); spawn(move|| { tx.send(1); tx.send(1); }); loop { rx.recv(); } - } #[should_fail]) + } #[should_fail] } - test!(fn stress() { + test! { fn stress() { let (tx, rx) = sync_channel::(0); spawn(move|| { for _ in range(0u, 10000) { tx.send(1); } @@ -1662,9 +1662,9 @@ mod sync_tests { for _ in range(0u, 10000) { assert_eq!(rx.recv(), 1); } - }) + } } - test!(fn stress_shared() { + test! { fn stress_shared() { static AMT: uint = 1000; static NTHREADS: uint = 8; let (tx, rx) = sync_channel::(0); @@ -1689,28 +1689,28 @@ mod sync_tests { } drop(tx); drx.recv(); - }) + } } - test!(fn oneshot_single_thread_close_port_first() { + test! { fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending let (_tx, rx) = sync_channel::(0); drop(rx); - }) + } } - test!(fn oneshot_single_thread_close_chan_first() { + test! { fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending let (tx, _rx) = sync_channel::(0); drop(tx); - }) + } } - test!(fn oneshot_single_thread_send_port_close() { + test! { fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed let (tx, rx) = sync_channel::>(0); drop(rx); tx.send(box 0); - } #[should_fail]) + } #[should_fail] } - test!(fn oneshot_single_thread_recv_chan_close() { + test! { fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = task::try(move|| { let (tx, rx) = sync_channel::(0); @@ -1719,72 +1719,72 @@ mod sync_tests { }); // What is our res? assert!(res.is_err()); - }) + } } - test!(fn oneshot_single_thread_send_then_recv() { + test! { fn oneshot_single_thread_send_then_recv() { let (tx, rx) = sync_channel::>(1); tx.send(box 10); assert!(rx.recv() == box 10); - }) + } } - test!(fn oneshot_single_thread_try_send_open() { + test! { fn oneshot_single_thread_try_send_open() { let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(10), Ok(())); assert!(rx.recv() == 10); - }) + } } - test!(fn oneshot_single_thread_try_send_closed() { + test! { fn oneshot_single_thread_try_send_closed() { let (tx, rx) = sync_channel::(0); drop(rx); assert_eq!(tx.try_send(10), Err(RecvDisconnected(10))); - }) + } } - test!(fn oneshot_single_thread_try_send_closed2() { + test! { fn oneshot_single_thread_try_send_closed2() { let (tx, _rx) = sync_channel::(0); assert_eq!(tx.try_send(10), Err(Full(10))); - }) + } } - test!(fn oneshot_single_thread_try_recv_open() { + test! { fn oneshot_single_thread_try_recv_open() { let (tx, rx) = sync_channel::(1); tx.send(10); assert!(rx.recv_opt() == Ok(10)); - }) + } } - test!(fn oneshot_single_thread_try_recv_closed() { + test! { fn oneshot_single_thread_try_recv_closed() { let (tx, rx) = sync_channel::(0); drop(tx); assert!(rx.recv_opt() == Err(())); - }) + } } - test!(fn oneshot_single_thread_peek_data() { + test! { fn oneshot_single_thread_peek_data() { let (tx, rx) = sync_channel::(1); - assert_eq!(rx.try_recv(), Err(Empty)) + assert_eq!(rx.try_recv(), Err(Empty)); tx.send(10); assert_eq!(rx.try_recv(), Ok(10)); - }) + } } - test!(fn oneshot_single_thread_peek_close() { + test! { fn oneshot_single_thread_peek_close() { let (tx, rx) = sync_channel::(0); drop(tx); assert_eq!(rx.try_recv(), Err(Disconnected)); assert_eq!(rx.try_recv(), Err(Disconnected)); - }) + } } - test!(fn oneshot_single_thread_peek_open() { + test! { fn oneshot_single_thread_peek_open() { let (_tx, rx) = sync_channel::(0); assert_eq!(rx.try_recv(), Err(Empty)); - }) + } } - test!(fn oneshot_multi_task_recv_then_send() { + test! { fn oneshot_multi_task_recv_then_send() { let (tx, rx) = sync_channel::>(0); spawn(move|| { assert!(rx.recv() == box 10); }); tx.send(box 10); - }) + } } - test!(fn oneshot_multi_task_recv_then_close() { + test! { fn oneshot_multi_task_recv_then_close() { let (tx, rx) = sync_channel::>(0); spawn(move|| { drop(tx); @@ -1793,9 +1793,9 @@ mod sync_tests { assert!(rx.recv() == box 10); }); assert!(res.is_err()); - }) + } } - test!(fn oneshot_multi_thread_close_stress() { + test! { fn oneshot_multi_thread_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); spawn(move|| { @@ -1803,9 +1803,9 @@ mod sync_tests { }); drop(tx); } - }) + } } - test!(fn oneshot_multi_thread_send_close_stress() { + test! { fn oneshot_multi_thread_send_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); spawn(move|| { @@ -1815,9 +1815,9 @@ mod sync_tests { tx.send(1); }); } - }) + } } - test!(fn oneshot_multi_thread_recv_close_stress() { + test! { fn oneshot_multi_thread_recv_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); spawn(move|| { @@ -1832,9 +1832,9 @@ mod sync_tests { }); }); } - }) + } } - test!(fn oneshot_multi_thread_send_recv_stress() { + test! { fn oneshot_multi_thread_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::>(0); spawn(move|| { @@ -1844,9 +1844,9 @@ mod sync_tests { assert!(rx.recv() == box 10i); }); } - }) + } } - test!(fn stream_send_recv_stress() { + test! { fn stream_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::>(0); @@ -1871,16 +1871,16 @@ mod sync_tests { }); } } - }) + } } - test!(fn recv_a_lot() { + test! { fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = sync_channel(10000); for _ in range(0u, 10000) { tx.send(()); } for _ in range(0u, 10000) { rx.recv(); } - }) + } } - test!(fn shared_chan_stress() { + test! { fn shared_chan_stress() { let (tx, rx) = sync_channel(0); let total = stress_factor() + 100; for _ in range(0, total) { @@ -1893,9 +1893,9 @@ mod sync_tests { for _ in range(0, total) { rx.recv(); } - }) + } } - test!(fn test_nested_recv_iter() { + test! { fn test_nested_recv_iter() { let (tx, rx) = sync_channel::(0); let (total_tx, total_rx) = sync_channel::(0); @@ -1912,9 +1912,9 @@ mod sync_tests { tx.send(2); drop(tx); assert_eq!(total_rx.recv(), 6); - }) + } } - test!(fn test_recv_iter_break() { + test! { fn test_recv_iter_break() { let (tx, rx) = sync_channel::(0); let (count_tx, count_rx) = sync_channel(0); @@ -1936,9 +1936,9 @@ mod sync_tests { let _ = tx.try_send(2); drop(tx); assert_eq!(count_rx.recv(), 4); - }) + } } - test!(fn try_recv_states() { + test! { fn try_recv_states() { let (tx1, rx1) = sync_channel::(1); let (tx2, rx2) = sync_channel::<()>(1); let (tx3, rx3) = sync_channel::<()>(1); @@ -1959,11 +1959,11 @@ mod sync_tests { tx2.send(()); rx3.recv(); assert_eq!(rx1.try_recv(), Err(Disconnected)); - }) + } } // This bug used to end up in a livelock inside of the Receiver destructor // because the internal state of the Shared packet was corrupted - test!(fn destroy_upgraded_shared_port_when_sender_still_active() { + test! { fn destroy_upgraded_shared_port_when_sender_still_active() { let (tx, rx) = sync_channel::<()>(0); let (tx2, rx2) = sync_channel::<()>(0); spawn(move|| { @@ -1981,9 +1981,9 @@ mod sync_tests { // wait for the child task to exit before we exit rx2.recv(); - }) + } } - test!(fn try_recvs_off_the_runtime() { + test! { fn try_recvs_off_the_runtime() { use rustrt::thread::Thread; let (tx, rx) = sync_channel::<()>(0); @@ -2004,28 +2004,28 @@ mod sync_tests { } t.join(); pdone.recv(); - }) + } } - test!(fn send_opt1() { + test! { fn send_opt1() { let (tx, rx) = sync_channel::(0); spawn(move|| { rx.recv(); }); assert_eq!(tx.send_opt(1), Ok(())); - }) + } } - test!(fn send_opt2() { + test! { fn send_opt2() { let (tx, rx) = sync_channel::(0); spawn(move|| { drop(rx); }); assert_eq!(tx.send_opt(1), Err(1)); - }) + } } - test!(fn send_opt3() { + test! { fn send_opt3() { let (tx, rx) = sync_channel::(1); assert_eq!(tx.send_opt(1), Ok(())); spawn(move|| { drop(rx); }); assert_eq!(tx.send_opt(1), Err(1)); - }) + } } - test!(fn send_opt4() { + test! { fn send_opt4() { let (tx, rx) = sync_channel::(0); let tx2 = tx.clone(); let (done, donerx) = channel(); @@ -2041,36 +2041,36 @@ mod sync_tests { drop(rx); donerx.recv(); donerx.recv(); - }) + } } - test!(fn try_send1() { + test! { fn try_send1() { let (tx, _rx) = sync_channel::(0); assert_eq!(tx.try_send(1), Err(Full(1))); - }) + } } - test!(fn try_send2() { + test! { fn try_send2() { let (tx, _rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); assert_eq!(tx.try_send(1), Err(Full(1))); - }) + } } - test!(fn try_send3() { + test! { fn try_send3() { let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); drop(rx); assert_eq!(tx.try_send(1), Err(RecvDisconnected(1))); - }) + } } - test!(fn try_send4() { + test! { fn try_send4() { let (tx, rx) = sync_channel::(0); spawn(move|| { for _ in range(0u, 1000) { task::deschedule(); } assert_eq!(tx.try_send(1), Ok(())); }); assert_eq!(rx.recv(), 1); - } #[ignore(reason = "flaky on libnative")]) + } #[ignore(reason = "flaky on libnative")] } - test!(fn issue_15761() { + test! { fn issue_15761() { fn repro() { let (tx1, rx1) = sync_channel::<()>(3); let (tx2, rx2) = sync_channel::<()>(3); @@ -2087,5 +2087,5 @@ mod sync_tests { for _ in range(0u, 100) { repro() } - }) + } } } diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index e145b0df7f3..de2b84b083c 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -347,58 +347,58 @@ mod test { }) } - test!(fn smoke() { + test! { fn smoke() { let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::(); tx1.send(1); - select! ( + select! { foo = rx1.recv() => { assert_eq!(foo, 1); }, _bar = rx2.recv() => { panic!() } - ) + } tx2.send(2); - select! ( + select! { _foo = rx1.recv() => { panic!() }, bar = rx2.recv() => { assert_eq!(bar, 2) } - ) + } drop(tx1); - select! ( + select! { foo = rx1.recv_opt() => { assert_eq!(foo, Err(())); }, _bar = rx2.recv() => { panic!() } - ) + } drop(tx2); - select! ( + select! { bar = rx2.recv_opt() => { assert_eq!(bar, Err(())); } - ) - }) + } + } } - test!(fn smoke2() { + test! { fn smoke2() { let (_tx1, rx1) = channel::(); let (_tx2, rx2) = channel::(); let (_tx3, rx3) = channel::(); let (_tx4, rx4) = channel::(); let (tx5, rx5) = channel::(); tx5.send(4); - select! ( + select! { _foo = rx1.recv() => { panic!("1") }, _foo = rx2.recv() => { panic!("2") }, _foo = rx3.recv() => { panic!("3") }, _foo = rx4.recv() => { panic!("4") }, foo = rx5.recv() => { assert_eq!(foo, 4); } - ) - }) + } + } } - test!(fn closed() { + test! { fn closed() { let (_tx1, rx1) = channel::(); let (tx2, rx2) = channel::(); drop(tx2); - select! ( + select! { _a1 = rx1.recv_opt() => { panic!() }, a2 = rx2.recv_opt() => { assert_eq!(a2, Err(())); } - ) - }) + } + } } - test!(fn unblocks() { + test! { fn unblocks() { let (tx1, rx1) = channel::(); let (_tx2, rx2) = channel::(); let (tx3, rx3) = channel::(); @@ -410,18 +410,18 @@ mod test { for _ in range(0u, 20) { task::deschedule(); } }); - select! ( + select! { a = rx1.recv() => { assert_eq!(a, 1); }, _b = rx2.recv() => { panic!() } - ) + } tx3.send(1); - select! ( + select! { a = rx1.recv_opt() => { assert_eq!(a, Err(())); }, _b = rx2.recv() => { panic!() } - ) - }) + } + } } - test!(fn both_ready() { + test! { fn both_ready() { let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); @@ -433,20 +433,20 @@ mod test { rx3.recv(); }); - select! ( + select! { a = rx1.recv() => { assert_eq!(a, 1); }, a = rx2.recv() => { assert_eq!(a, 2); } - ) - select! ( + } + select! { a = rx1.recv() => { assert_eq!(a, 1); }, a = rx2.recv() => { assert_eq!(a, 2); } - ) + } assert_eq!(rx1.try_recv(), Err(Empty)); assert_eq!(rx2.try_recv(), Err(Empty)); tx3.send(()); - }) + } } - test!(fn stress() { + test! { fn stress() { static AMT: int = 10000; let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::(); @@ -464,15 +464,15 @@ mod test { }); for i in range(0, AMT) { - select! ( + select! { i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1); }, i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2); } - ) + } tx3.send(()); } - }) + } } - test!(fn cloning() { + test! { fn cloning() { let (tx1, rx1) = channel::(); let (_tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); @@ -486,14 +486,14 @@ mod test { }); tx3.send(()); - select!( + select! { _i1 = rx1.recv() => {}, _i2 = rx2.recv() => panic!() - ) + } tx3.send(()); - }) + } } - test!(fn cloning2() { + test! { fn cloning2() { let (tx1, rx1) = channel::(); let (_tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); @@ -507,14 +507,14 @@ mod test { }); tx3.send(()); - select!( + select! { _i1 = rx1.recv() => {}, _i2 = rx2.recv() => panic!() - ) + } tx3.send(()); - }) + } } - test!(fn cloning3() { + test! { fn cloning3() { let (tx1, rx1) = channel::<()>(); let (tx2, rx2) = channel::<()>(); let (tx3, rx3) = channel::<()>(); @@ -532,44 +532,44 @@ mod test { drop(tx1.clone()); tx2.send(()); rx3.recv(); - }) + } } - test!(fn preflight1() { + test! { fn preflight1() { let (tx, rx) = channel(); tx.send(()); - select!( + select! { () = rx.recv() => {} - ) - }) + } + } } - test!(fn preflight2() { + test! { fn preflight2() { let (tx, rx) = channel(); tx.send(()); tx.send(()); - select!( + select! { () = rx.recv() => {} - ) - }) + } + } } - test!(fn preflight3() { + test! { fn preflight3() { let (tx, rx) = channel(); drop(tx.clone()); tx.send(()); - select!( + select! { () = rx.recv() => {} - ) - }) + } + } } - test!(fn preflight4() { + test! { fn preflight4() { let (tx, rx) = channel(); tx.send(()); let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - }) + } } - test!(fn preflight5() { + test! { fn preflight5() { let (tx, rx) = channel(); tx.send(()); tx.send(()); @@ -577,9 +577,9 @@ mod test { let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - }) + } } - test!(fn preflight6() { + test! { fn preflight6() { let (tx, rx) = channel(); drop(tx.clone()); tx.send(()); @@ -587,18 +587,18 @@ mod test { let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - }) + } } - test!(fn preflight7() { + test! { fn preflight7() { let (tx, rx) = channel::<()>(); drop(tx); let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - }) + } } - test!(fn preflight8() { + test! { fn preflight8() { let (tx, rx) = channel(); tx.send(()); drop(tx); @@ -607,9 +607,9 @@ mod test { let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - }) + } } - test!(fn preflight9() { + test! { fn preflight9() { let (tx, rx) = channel(); drop(tx.clone()); tx.send(()); @@ -619,9 +619,9 @@ mod test { let mut h = s.handle(&rx); unsafe { h.add(); } assert_eq!(s.wait2(false), h.id); - }) + } } - test!(fn oneshot_data_waiting() { + test! { fn oneshot_data_waiting() { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); spawn(move|| { @@ -634,9 +634,9 @@ mod test { for _ in range(0u, 100) { task::deschedule() } tx1.send(()); rx2.recv(); - }) + } } - test!(fn stream_data_waiting() { + test! { fn stream_data_waiting() { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); tx1.send(()); @@ -653,9 +653,9 @@ mod test { for _ in range(0u, 100) { task::deschedule() } tx1.send(()); rx2.recv(); - }) + } } - test!(fn shared_data_waiting() { + test! { fn shared_data_waiting() { let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); drop(tx1.clone()); @@ -671,17 +671,17 @@ mod test { for _ in range(0u, 100) { task::deschedule() } tx1.send(()); rx2.recv(); - }) + } } - test!(fn sync1() { + test! { fn sync1() { let (tx, rx) = sync_channel::(1); tx.send(1); select! { n = rx.recv() => { assert_eq!(n, 1); } } - }) + } } - test!(fn sync2() { + test! { fn sync2() { let (tx, rx) = sync_channel::(0); spawn(move|| { for _ in range(0u, 100) { task::deschedule() } @@ -690,9 +690,9 @@ mod test { select! { n = rx.recv() => { assert_eq!(n, 1); } } - }) + } } - test!(fn sync3() { + test! { fn sync3() { let (tx1, rx1) = sync_channel::(0); let (tx2, rx2): (Sender, Receiver) = channel(); spawn(move|| { tx1.send(1); }); @@ -707,5 +707,5 @@ mod test { assert_eq!(rx1.recv(), 1); } } - }) + } } } diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs index 58a41f4d7d5..89bccb8b99f 100644 --- a/src/libstd/failure.rs +++ b/src/libstd/failure.rs @@ -27,9 +27,11 @@ use str::Str; use string::String; // Defined in this module instead of io::stdio so that the unwinding -thread_local!(pub static LOCAL_STDERR: RefCell>> = { - RefCell::new(None) -}) +thread_local! { + pub static LOCAL_STDERR: RefCell>> = { + RefCell::new(None) + } +} impl Writer for Stdio { fn write(&mut self, bytes: &[u8]) -> IoResult<()> { diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index 24a000adef2..c1f1a5b7869 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -511,7 +511,7 @@ mod bench { use self::test::Bencher; // why is this a macro? wouldn't an inlined function work just as well? - macro_rules! u64_from_be_bytes_bench_impl( + macro_rules! u64_from_be_bytes_bench_impl { ($b:expr, $size:expr, $stride:expr, $start_index:expr) => ({ use super::u64_from_be_bytes; @@ -526,7 +526,7 @@ mod bench { } }); }) - ) + } #[bench] fn u64_from_be_bytes_4_aligned(b: &mut Bencher) { diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index f8df7e9b1f3..fd3bae73cd3 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -828,20 +828,20 @@ mod test { use ops::Drop; use str::StrPrelude; - macro_rules! check( ($e:expr) => ( + macro_rules! check { ($e:expr) => ( match $e { Ok(t) => t, Err(e) => panic!("{} failed with: {}", stringify!($e), e), } - ) ) + ) } - macro_rules! error( ($e:expr, $s:expr) => ( + macro_rules! error { ($e:expr, $s:expr) => ( match $e { Ok(_) => panic!("Unexpected success. Should've been: {}", $s), Err(ref err) => assert!(err.to_string().contains($s.as_slice()), format!("`{}` did not contain `{}`", err, $s)) } - ) ) + ) } pub struct TempDir(Path); diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index 092410fbc8e..5a3f5bd4668 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -478,7 +478,7 @@ fn resolve_socket_addr(s: &str, p: u16) -> IoResult> { } fn parse_and_resolve_socket_addr(s: &str) -> IoResult> { - macro_rules! try_opt( + macro_rules! try_opt { ($e:expr, $msg:expr) => ( match $e { Some(r) => r, @@ -489,7 +489,7 @@ fn parse_and_resolve_socket_addr(s: &str) -> IoResult> { }) } ) - ) + } // split the string by ':' and convert the second part to u16 let mut parts_iter = s.rsplitn(2, ':'); diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 844814fbfdd..73be389bb91 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -95,9 +95,11 @@ fn src(fd: libc::c_int, _readable: bool, f: F) -> T where } } -thread_local!(static LOCAL_STDOUT: RefCell>> = { - RefCell::new(None) -}) +thread_local! { + static LOCAL_STDOUT: RefCell>> = { + RefCell::new(None) + } +} /// A synchronized wrapper around a buffered reader from stdin #[deriving(Clone)] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index a02b37fcfd1..798dac1a72f 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -37,7 +37,7 @@ /// panic!("this is a {} {message}", "fancy", message = "message"); /// ``` #[macro_export] -macro_rules! panic( +macro_rules! panic { () => ({ panic!("explicit panic") }); @@ -70,7 +70,7 @@ macro_rules! panic( } format_args!(_run_fmt, $fmt, $($arg)*) }); -) +} /// Ensure that a boolean expression is `true` at runtime. /// @@ -93,7 +93,7 @@ macro_rules! panic( /// assert!(a + b == 30, "a = {}, b = {}", a, b); /// ``` #[macro_export] -macro_rules! assert( +macro_rules! assert { ($cond:expr) => ( if !$cond { panic!(concat!("assertion failed: ", stringify!($cond))) @@ -104,7 +104,7 @@ macro_rules! assert( panic!($($arg),+) } ); -) +} /// Asserts that two expressions are equal to each other, testing equality in /// both directions. @@ -119,7 +119,7 @@ macro_rules! assert( /// assert_eq!(a, b); /// ``` #[macro_export] -macro_rules! assert_eq( +macro_rules! assert_eq { ($left:expr , $right:expr) => ({ match (&($left), &($right)) { (left_val, right_val) => { @@ -132,7 +132,7 @@ macro_rules! assert_eq( } } }) -) +} /// Ensure that a boolean expression is `true` at runtime. /// @@ -160,9 +160,9 @@ macro_rules! assert_eq( /// debug_assert!(a + b == 30, "a = {}, b = {}", a, b); /// ``` #[macro_export] -macro_rules! debug_assert( +macro_rules! debug_assert { ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) -) +} /// Asserts that two expressions are equal to each other, testing equality in /// both directions. @@ -182,9 +182,9 @@ macro_rules! debug_assert( /// debug_assert_eq!(a, b); /// ``` #[macro_export] -macro_rules! debug_assert_eq( +macro_rules! debug_assert_eq { ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); }) -) +} /// A utility macro for indicating unreachable code. /// @@ -226,7 +226,7 @@ macro_rules! debug_assert_eq( /// } /// ``` #[macro_export] -macro_rules! unreachable( +macro_rules! unreachable { () => ({ panic!("internal error: entered unreachable code") }); @@ -236,14 +236,14 @@ macro_rules! unreachable( ($fmt:expr, $($arg:tt)*) => ({ panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) }); -) +} /// A standardised placeholder for marking unfinished code. It panics with the /// message `"not yet implemented"` when executed. #[macro_export] -macro_rules! unimplemented( +macro_rules! unimplemented { () => (panic!("not yet implemented")) -) +} /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. @@ -257,11 +257,11 @@ macro_rules! unimplemented( /// ``` #[macro_export] #[stable] -macro_rules! format( +macro_rules! format { ($($arg:tt)*) => ( format_args!(::std::fmt::format, $($arg)*) ) -) +} /// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. /// See `std::fmt` for more information. @@ -277,30 +277,30 @@ macro_rules! format( /// ``` #[macro_export] #[stable] -macro_rules! write( +macro_rules! write { ($dst:expr, $($arg:tt)*) => ({ let dst = &mut *$dst; format_args!(|args| { dst.write_fmt(args) }, $($arg)*) }) -) +} /// Equivalent to the `write!` macro, except that a newline is appended after /// the message is written. #[macro_export] #[stable] -macro_rules! writeln( +macro_rules! writeln { ($dst:expr, $fmt:expr $($arg:tt)*) => ( write!($dst, concat!($fmt, "\n") $($arg)*) ) -) +} /// Equivalent to the `println!` macro except that a newline is not printed at /// the end of the message. #[macro_export] #[stable] -macro_rules! print( +macro_rules! print { ($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*)) -) +} /// Macro for printing to a task's stdout handle. /// @@ -316,33 +316,33 @@ macro_rules! print( /// ``` #[macro_export] #[stable] -macro_rules! println( +macro_rules! println { ($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*)) -) +} /// Helper macro for unwrapping `Result` values while returning early with an /// error if the value of the expression is `Err`. For more information, see /// `std::io`. #[macro_export] -macro_rules! try ( +macro_rules! try { ($expr:expr) => ({ match $expr { Ok(val) => val, Err(err) => return Err(::std::error::FromError::from_error(err)) } }) -) +} /// Create a `std::vec::Vec` containing the arguments. #[macro_export] -macro_rules! vec[ +macro_rules! vec { ($($x:expr),*) => ({ use std::slice::BoxedSliceExt; let xs: ::std::boxed::Box<[_]> = box [$($x),*]; xs.into_vec() }); ($($x:expr,)*) => (vec![$($x),*]) -] +} /// A macro to select an event from a number of receivers. /// @@ -394,11 +394,11 @@ macro_rules! select { // uses. To get around this difference, we redefine the log!() macro here to be // just a dumb version of what it should be. #[cfg(test)] -macro_rules! log ( +macro_rules! log { ($lvl:expr, $($args:tt)*) => ( if log_enabled!($lvl) { println!($($args)*) } ) -) +} /// Built-in macros to the compiler itself. /// @@ -430,9 +430,9 @@ pub mod builtin { /// }, "hello {}", "world"); /// ``` #[macro_export] - macro_rules! format_args( ($closure:expr, $fmt:expr $($args:tt)*) => ({ + macro_rules! format_args { ($closure:expr, $fmt:expr $($args:tt)*) => ({ /* compiler built-in */ - }) ) + }) } /// Inspect an environment variable at compile time. /// @@ -450,7 +450,7 @@ pub mod builtin { /// println!("the $PATH variable at the time of compiling was: {}", path); /// ``` #[macro_export] - macro_rules! env( ($name:expr) => ({ /* compiler built-in */ }) ) + macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) } /// Optionally inspect an environment variable at compile time. /// @@ -469,7 +469,7 @@ pub mod builtin { /// println!("the secret key might be: {}", key); /// ``` #[macro_export] - macro_rules! option_env( ($name:expr) => ({ /* compiler built-in */ }) ) + macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) } /// Concatenate literals into a static byte slice. /// @@ -489,7 +489,7 @@ pub mod builtin { /// assert_eq!(rust[4], 255); /// ``` #[macro_export] - macro_rules! bytes( ($($e:expr),*) => ({ /* compiler built-in */ }) ) + macro_rules! bytes { ($($e:expr),*) => ({ /* compiler built-in */ }) } /// Concatenate identifiers into one identifier. /// @@ -513,7 +513,9 @@ pub mod builtin { /// # } /// ``` #[macro_export] - macro_rules! concat_idents( ($($e:ident),*) => ({ /* compiler built-in */ }) ) + macro_rules! concat_idents { + ($($e:ident),*) => ({ /* compiler built-in */ }) + } /// Concatenates literals into a static string slice. /// @@ -531,7 +533,7 @@ pub mod builtin { /// assert_eq!(s, "test10btrue"); /// ``` #[macro_export] - macro_rules! concat( ($($e:expr),*) => ({ /* compiler built-in */ }) ) + macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) } /// A macro which expands to the line number on which it was invoked. /// @@ -546,7 +548,7 @@ pub mod builtin { /// println!("defined on line: {}", current_line); /// ``` #[macro_export] - macro_rules! line( () => ({ /* compiler built-in */ }) ) + macro_rules! line { () => ({ /* compiler built-in */ }) } /// A macro which expands to the column number on which it was invoked. /// @@ -561,7 +563,7 @@ pub mod builtin { /// println!("defined on column: {}", current_col); /// ``` #[macro_export] - macro_rules! column( () => ({ /* compiler built-in */ }) ) + macro_rules! column { () => ({ /* compiler built-in */ }) } /// A macro which expands to the file name from which it was invoked. /// @@ -577,7 +579,7 @@ pub mod builtin { /// println!("defined in file: {}", this_file); /// ``` #[macro_export] - macro_rules! file( () => ({ /* compiler built-in */ }) ) + macro_rules! file { () => ({ /* compiler built-in */ }) } /// A macro which stringifies its argument. /// @@ -592,7 +594,7 @@ pub mod builtin { /// assert_eq!(one_plus_one, "1 + 1"); /// ``` #[macro_export] - macro_rules! stringify( ($t:tt) => ({ /* compiler built-in */ }) ) + macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) } /// Includes a utf8-encoded file as a string. /// @@ -606,7 +608,7 @@ pub mod builtin { /// let secret_key = include_str!("secret-key.ascii"); /// ``` #[macro_export] - macro_rules! include_str( ($file:expr) => ({ /* compiler built-in */ }) ) + macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) } /// Includes a file as a byte slice. /// @@ -620,7 +622,7 @@ pub mod builtin { /// let secret_key = include_bin!("secret-key.bin"); /// ``` #[macro_export] - macro_rules! include_bin( ($file:expr) => ({ /* compiler built-in */ }) ) + macro_rules! include_bin { ($file:expr) => ({ /* compiler built-in */ }) } /// Expands to a string that represents the current module path. /// @@ -640,7 +642,7 @@ pub mod builtin { /// test::foo(); /// ``` #[macro_export] - macro_rules! module_path( () => ({ /* compiler built-in */ }) ) + macro_rules! module_path { () => ({ /* compiler built-in */ }) } /// Boolean evaluation of configuration flags. /// @@ -661,5 +663,5 @@ pub mod builtin { /// }; /// ``` #[macro_export] - macro_rules! cfg( ($cfg:tt) => ({ /* compiler built-in */ }) ) + macro_rules! cfg { ($cfg:tt) => ({ /* compiler built-in */ }) } } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 9aac857bb65..60b17de1718 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -671,8 +671,8 @@ mod tests { let inf: f32 = Float::infinity(); let neg_inf: f32 = Float::neg_infinity(); let nan: f32 = Float::nan(); - assert_eq!(match inf.frexp() { (x, _) => x }, inf) - assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf) + assert_eq!(match inf.frexp() { (x, _) => x }, inf); + assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); assert!(match nan.frexp() { (x, _) => x.is_nan() }) } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 29ccfe512b9..4b31e33236d 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -673,8 +673,8 @@ mod tests { let inf: f64 = Float::infinity(); let neg_inf: f64 = Float::neg_infinity(); let nan: f64 = Float::nan(); - assert_eq!(match inf.frexp() { (x, _) => x }, inf) - assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf) + assert_eq!(match inf.frexp() { (x, _) => x }, inf); + assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); assert!(match nan.frexp() { (x, _) => x.is_nan() }) } diff --git a/src/libstd/num/float_macros.rs b/src/libstd/num/float_macros.rs index 4b3727ead61..fd00f15662a 100644 --- a/src/libstd/num/float_macros.rs +++ b/src/libstd/num/float_macros.rs @@ -12,11 +12,11 @@ #![macro_escape] #![doc(hidden)] -macro_rules! assert_approx_eq( +macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ use num::Float; let (a, b) = (&$a, &$b); assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); }) -) +} diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index 333d1d7df0b..367147b84be 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -15,4 +15,4 @@ pub use core::i16::{BITS, BYTES, MIN, MAX}; -int_module!(i16) +int_module! { i16 } diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 44b5397bf74..19fb40c9644 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -15,4 +15,4 @@ pub use core::i32::{BITS, BYTES, MIN, MAX}; -int_module!(i32) +int_module! { i32 } diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index de6fa0d3ef8..2379b03c64f 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -15,4 +15,4 @@ pub use core::i64::{BITS, BYTES, MIN, MAX}; -int_module!(i64) +int_module! { i64 } diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index 3b9fbcb768b..a09ceefc6a0 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -15,4 +15,4 @@ pub use core::i8::{BITS, BYTES, MIN, MAX}; -int_module!(i8) +int_module! { i8 } diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index 36c021efe0a..f59dab4b20b 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -15,4 +15,4 @@ pub use core::int::{BITS, BYTES, MIN, MAX}; -int_module!(int) +int_module! { int } diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 2f1162d28e5..fce150c4ad1 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -12,6 +12,6 @@ #![macro_escape] #![doc(hidden)] -macro_rules! int_module (($T:ty) => ( +macro_rules! int_module { ($T:ty) => ( -)) +) } diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 9aaaceb87e6..a568aafe1ed 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -161,7 +161,7 @@ mod tests { use u64; use uint; - macro_rules! test_cast_20( + macro_rules! test_cast_20 { ($_20:expr) => ({ let _20 = $_20; @@ -204,7 +204,7 @@ mod tests { assert_eq!(_20, cast(20f32).unwrap()); assert_eq!(_20, cast(20f64).unwrap()); }) - ) + } #[test] fn test_u8_cast() { test_cast_20!(20u8) } #[test] fn test_u16_cast() { test_cast_20!(20u16) } @@ -664,7 +664,7 @@ mod tests { assert_eq!(third.checked_mul(4), None); } - macro_rules! test_next_power_of_two( + macro_rules! test_next_power_of_two { ($test_name:ident, $T:ident) => ( fn $test_name() { #![test] @@ -676,15 +676,15 @@ mod tests { } } ) - ) + } - test_next_power_of_two!(test_next_power_of_two_u8, u8) - test_next_power_of_two!(test_next_power_of_two_u16, u16) - test_next_power_of_two!(test_next_power_of_two_u32, u32) - test_next_power_of_two!(test_next_power_of_two_u64, u64) - test_next_power_of_two!(test_next_power_of_two_uint, uint) + test_next_power_of_two! { test_next_power_of_two_u8, u8 } + test_next_power_of_two! { test_next_power_of_two_u16, u16 } + test_next_power_of_two! { test_next_power_of_two_u32, u32 } + test_next_power_of_two! { test_next_power_of_two_u64, u64 } + test_next_power_of_two! { test_next_power_of_two_uint, uint } - macro_rules! test_checked_next_power_of_two( + macro_rules! test_checked_next_power_of_two { ($test_name:ident, $T:ident) => ( fn $test_name() { #![test] @@ -699,13 +699,13 @@ mod tests { assert_eq!($T::MAX.checked_next_power_of_two(), None); } ) - ) + } - test_checked_next_power_of_two!(test_checked_next_power_of_two_u8, u8) - test_checked_next_power_of_two!(test_checked_next_power_of_two_u16, u16) - test_checked_next_power_of_two!(test_checked_next_power_of_two_u32, u32) - test_checked_next_power_of_two!(test_checked_next_power_of_two_u64, u64) - test_checked_next_power_of_two!(test_checked_next_power_of_two_uint, uint) + test_checked_next_power_of_two! { test_checked_next_power_of_two_u8, u8 } + test_checked_next_power_of_two! { test_checked_next_power_of_two_u16, u16 } + test_checked_next_power_of_two! { test_checked_next_power_of_two_u32, u32 } + test_checked_next_power_of_two! { test_checked_next_power_of_two_u64, u64 } + test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, uint } #[deriving(PartialEq, Show)] struct Value { x: int } @@ -759,13 +759,13 @@ mod tests { let one: T = Int::one(); range(0, exp).fold(one, |acc, _| acc * base) } - macro_rules! assert_pow( + macro_rules! assert_pow { (($num:expr, $exp:expr) => $expected:expr) => {{ let result = $num.pow($exp); assert_eq!(result, $expected); assert_eq!(result, naive_pow($num, $exp)); }} - ) + } assert_pow!((3i, 0 ) => 1); assert_pow!((5i, 1 ) => 5); assert_pow!((-4i, 2 ) => 16); diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs index 6d9b177574a..46699b78599 100644 --- a/src/libstd/num/u16.rs +++ b/src/libstd/num/u16.rs @@ -17,4 +17,4 @@ pub use core::u16::{BITS, BYTES, MIN, MAX}; use ops::FnOnce; -uint_module!(u16) +uint_module! { u16 } diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs index 0d6d17fa007..45ee9251d2f 100644 --- a/src/libstd/num/u32.rs +++ b/src/libstd/num/u32.rs @@ -17,4 +17,4 @@ pub use core::u32::{BITS, BYTES, MIN, MAX}; use ops::FnOnce; -uint_module!(u32) +uint_module! { u32 } diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs index ebb5d2946c5..1d8ff77dac8 100644 --- a/src/libstd/num/u64.rs +++ b/src/libstd/num/u64.rs @@ -17,4 +17,4 @@ pub use core::u64::{BITS, BYTES, MIN, MAX}; use ops::FnOnce; -uint_module!(u64) +uint_module! { u64 } diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs index 59aea214aae..0663ace2e5b 100644 --- a/src/libstd/num/u8.rs +++ b/src/libstd/num/u8.rs @@ -17,4 +17,4 @@ pub use core::u8::{BITS, BYTES, MIN, MAX}; use ops::FnOnce; -uint_module!(u8) +uint_module! { u8 } diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index 484d28dfed0..7f8edee571f 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -17,4 +17,4 @@ pub use core::uint::{BITS, BYTES, MIN, MAX}; use ops::FnOnce; -uint_module!(uint) +uint_module! { uint } diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index bd6f3d4bb28..c42b7eebfdd 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -13,7 +13,7 @@ #![doc(hidden)] #![allow(unsigned_negation)] -macro_rules! uint_module (($T:ty) => ( +macro_rules! uint_module { ($T:ty) => ( // String conversion functions and impl num -> str @@ -141,4 +141,4 @@ mod tests { } } -)) +) } diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index bea51712253..f872aa8e9a4 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -447,7 +447,7 @@ mod tests { use str; use str::StrPrelude; - macro_rules! t( + macro_rules! t { (s: $path:expr, $exp:expr) => ( { let path = $path; @@ -460,7 +460,7 @@ mod tests { assert!(path.as_vec() == $exp); } ) - ) + } #[test] fn test_paths() { @@ -533,14 +533,14 @@ mod tests { #[test] fn test_display_str() { - macro_rules! t( + macro_rules! t { ($path:expr, $disp:ident, $exp:expr) => ( { let path = Path::new($path); assert!(path.$disp().to_string() == $exp); } ) - ) + } t!("foo", display, "foo"); t!(b"foo\x80", display, "foo\u{FFFD}"); t!(b"foo\xFFbar", display, "foo\u{FFFD}bar"); @@ -563,7 +563,7 @@ mod tests { assert!(mo.as_slice() == $exp); } ) - ) + ); t!("foo", "foo"); t!(b"foo\x80", "foo\u{FFFD}"); @@ -585,7 +585,7 @@ mod tests { assert!(f == $expf); } ) - ) + ); t!(b"foo", "foo", "foo"); t!(b"foo/bar", "foo/bar", "bar"); @@ -619,7 +619,7 @@ mod tests { assert!(path.$op() == $exp); } ); - ) + ); t!(v: b"a/b/c", filename, Some(b"c")); t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF")); @@ -693,7 +693,7 @@ mod tests { assert!(p1 == p2.join(join)); } ) - ) + ); t!(s: "a/b/c", ".."); t!(s: "/a/b/c", "d"); @@ -712,7 +712,7 @@ mod tests { assert!(p.as_str() == Some($exp)); } ) - ) + ); t!(s: "a/b/c", "d", "a/b/c/d"); t!(s: "/a/b/c", "d", "/a/b/c/d"); @@ -739,7 +739,7 @@ mod tests { assert!(p.as_vec() == $exp); } ) - ) + ); t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e"); t!(s: "a/b/c", ["d", "/e"], "/e"); @@ -769,7 +769,7 @@ mod tests { assert!(result == $right); } ) - ) + ); t!(b: b"a/b/c", b"a/b", true); t!(b: b"a", b".", true); @@ -817,7 +817,7 @@ mod tests { assert!(res.as_str() == Some($exp)); } ) - ) + ); t!(s: "a/b/c", "..", "a/b"); t!(s: "/a/b/c", "d", "/a/b/c/d"); @@ -844,7 +844,7 @@ mod tests { assert!(res.as_vec() == $exp); } ) - ) + ); t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e"); t!(s: "a/b/c", ["..", "d"], "a/b/d"); @@ -928,7 +928,7 @@ mod tests { assert!(p1 == p2.$with(arg)); } ) - ) + ); t!(v: b"a/b/c", set_filename, with_filename, b"d"); t!(v: b"/", set_filename, with_filename, b"foo"); @@ -982,7 +982,7 @@ mod tests { assert!(path.extension() == $ext); } ) - ) + ); t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None); t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None); @@ -1029,7 +1029,7 @@ mod tests { assert_eq!(path.is_relative(), $rel); } ) - ) + ); t!(s: "a/b/c", false, true); t!(s: "/a/b/c", true, false); t!(s: "a", false, true); @@ -1050,7 +1050,7 @@ mod tests { assert_eq!(path.is_ancestor_of(&dest), $exp); } ) - ) + ); t!(s: "a/b/c", "a/b/c/d", true); t!(s: "a/b/c", "a/b/c", true); @@ -1091,7 +1091,7 @@ mod tests { assert_eq!(path.ends_with_path(&child), $exp); } ) - ) + ); t!(s: "a/b/c", "c", true); t!(s: "a/b/c", "d", false); @@ -1124,7 +1124,7 @@ mod tests { assert_eq!(res.as_ref().and_then(|x| x.as_str()), $exp); } ) - ) + ); t!(s: "a/b/c", "a/b", Some("c")); t!(s: "a/b/c", "a/b/d", Some("../c")); @@ -1186,7 +1186,7 @@ mod tests { assert_eq!(comps, exp) } ) - ) + ); t!(b: b"a/b/c", [b"a", b"b", b"c"]); t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]); @@ -1218,7 +1218,7 @@ mod tests { assert_eq!(comps, exp); } ) - ) + ); t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]); t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]); diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 8b18d1d8cd4..b376f6d0d5b 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1122,7 +1122,7 @@ mod tests { use super::*; use super::parse_prefix; - macro_rules! t( + macro_rules! t { (s: $path:expr, $exp:expr) => ( { let path = $path; @@ -1135,7 +1135,7 @@ mod tests { assert!(path.as_vec() == $exp); } ) - ) + } #[test] fn test_parse_prefix() { @@ -1149,7 +1149,7 @@ mod tests { "parse_prefix(\"{}\"): expected {}, found {}", path, exp, res); } ) - ) + ); t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5))); t!("\\\\", None); @@ -1348,7 +1348,7 @@ mod tests { assert_eq!(f, $expf); } ) - ) + ); t!("foo", "foo", "foo"); t!("foo\\bar", "foo\\bar", "bar"); @@ -1380,7 +1380,7 @@ mod tests { assert!(path.$op() == $exp); } ) - ) + ); t!(v: b"a\\b\\c", filename, Some(b"c")); t!(s: "a\\b\\c", filename_str, "c"); @@ -1491,7 +1491,7 @@ mod tests { assert!(p1 == p2.join(join)); } ) - ) + ); t!(s: "a\\b\\c", ".."); t!(s: "\\a\\b\\c", "d"); @@ -1524,7 +1524,7 @@ mod tests { assert_eq!(p.as_str(), Some($exp)); } ) - ) + ); t!(s: "a\\b\\c", "d", "a\\b\\c\\d"); t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d"); @@ -1582,7 +1582,7 @@ mod tests { assert_eq!(p.as_vec(), $exp); } ) - ) + ); t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e"); t!(s: "a\\b\\c", ["d", "\\e"], "\\e"); @@ -1617,7 +1617,7 @@ mod tests { assert!(result == $right); } ) - ) + ); t!(s: "a\\b\\c", "a\\b", true); t!(s: "a", ".", true); @@ -1694,7 +1694,7 @@ mod tests { assert_eq!(res.as_str(), Some($exp)); } ) - ) + ); t!(s: "a\\b\\c", "..", "a\\b"); t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d"); @@ -1723,7 +1723,7 @@ mod tests { assert_eq!(res.as_vec(), $exp); } ) - ) + ); t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e"); t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d"); @@ -1749,7 +1749,7 @@ mod tests { pstr, stringify!($op), arg, exp, res.as_str().unwrap()); } ) - ) + ); t!(s: "a\\b\\c", with_filename, "d", "a\\b\\d"); t!(s: ".", with_filename, "foo", "foo"); @@ -1842,7 +1842,7 @@ mod tests { assert!(p1 == p2.$with(arg)); } ) - ) + ); t!(v: b"a\\b\\c", set_filename, with_filename, b"d"); t!(v: b"\\", set_filename, with_filename, b"foo"); @@ -1897,7 +1897,7 @@ mod tests { assert!(path.extension() == $ext); } ) - ) + ); t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None); t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None); @@ -1951,7 +1951,7 @@ mod tests { path.as_str().unwrap(), rel, b); } ) - ) + ); t!("a\\b\\c", false, false, false, true); t!("\\a\\b\\c", false, true, false, false); t!("a", false, false, false, true); @@ -1984,7 +1984,7 @@ mod tests { path.as_str().unwrap(), dest.as_str().unwrap(), exp, res); } ) - ) + ); t!(s: "a\\b\\c", "a\\b\\c\\d", true); t!(s: "a\\b\\c", "a\\b\\c", true); @@ -2083,7 +2083,7 @@ mod tests { assert_eq!(path.ends_with_path(&child), $exp); } ); - ) + ); t!(s: "a\\b\\c", "c", true); t!(s: "a\\b\\c", "d", false); @@ -2120,7 +2120,7 @@ mod tests { res.as_ref().and_then(|x| x.as_str())); } ) - ) + ); t!(s: "a\\b\\c", "a\\b", Some("c")); t!(s: "a\\b\\c", "a\\b\\d", Some("..\\c")); @@ -2255,7 +2255,7 @@ mod tests { assert_eq!(comps, exp); } ); - ) + ); t!(s: b"a\\b\\c", ["a", "b", "c"]); t!(s: "a\\b\\c", ["a", "b", "c"]); @@ -2311,7 +2311,7 @@ mod tests { assert_eq!(comps, exp); } ) - ) + ); t!(s: "a\\b\\c", [b"a", b"b", b"c"]); t!(s: ".", [b"."]); @@ -2329,7 +2329,7 @@ mod tests { assert!(make_non_verbatim(&path) == exp); } ) - ) + ); t!(r"\a\b\c", Some(r"\a\b\c")); t!(r"a\b\c", Some(r"a\b\c")); diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 5b5fa2952e6..d8e1fc25654 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -350,7 +350,7 @@ pub fn task_rng() -> TaskRng { TASK_RNG_RESEED_THRESHOLD, TaskRngReseeder); Rc::new(RefCell::new(rng)) - }) + }); TaskRng { rng: TASK_RNG_KEY.with(|t| t.clone()) } } diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index ad4695eb7fe..c2fc7653b09 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -109,7 +109,7 @@ fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { rest = rest.slice_to(i); while rest.len() > 0 { if rest.starts_with("$") { - macro_rules! demangle( + macro_rules! demangle { ($($pat:expr => $demangled:expr),*) => ({ $(if rest.starts_with($pat) { try!(writer.write_str($demangled)); @@ -121,7 +121,8 @@ fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { } }) - ) + } + // see src/librustc/back/link.rs for these mappings demangle! ( "$SP$" => "@", @@ -933,12 +934,12 @@ mod imp { Err(..) => return Ok(()), }; - macro_rules! sym( ($e:expr, $t:ident) => (unsafe { + macro_rules! sym { ($e:expr, $t:ident) => (unsafe { match lib.symbol($e) { Ok(f) => mem::transmute::<*mut u8, $t>(f), Err(..) => return Ok(()) } - }) ) + }) } // Fetch the symbols necessary from dbghelp.dll let SymFromAddr = sym!("SymFromAddr", SymFromAddrFn); @@ -1003,11 +1004,13 @@ mod imp { #[cfg(test)] mod test { use prelude::*; - macro_rules! t( ($a:expr, $b:expr) => ({ + use io::MemWriter; + + macro_rules! t { ($a:expr, $b:expr) => ({ let mut m = Vec::new(); super::demangle(&mut m, $a).unwrap(); assert_eq!(String::from_utf8(m).unwrap(), $b); - }) ) + }) } #[test] fn demangle() { diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 107263c31a7..acbf2096326 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -23,7 +23,7 @@ use prelude::*; use io::{mod, IoResult, IoError}; use sys_common::mkerr_libc; -macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => ( +macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( static $name: Helper<$m> = Helper { lock: ::sync::MUTEX_INIT, cond: ::sync::CONDVAR_INIT, @@ -32,7 +32,7 @@ macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => ( initialized: ::cell::UnsafeCell { value: false }, shutdown: ::cell::UnsafeCell { value: false }, }; -) ) +) } pub mod c; pub mod ext; diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 4ef1757cc3a..835f4279d9b 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -28,7 +28,7 @@ use sys_common::{AsInner, mkerr_libc, timeout}; pub use sys_common::ProcessConfig; -helper_init!(static HELPER: Helper) +helper_init! { static HELPER: Helper } /// The unique id of the process (this should never be negative). pub struct Process { diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index 6ebbedb8e90..79a6a871f8d 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -60,7 +60,7 @@ use sys_common::helper_thread::Helper; use prelude::*; use io::IoResult; -helper_init!(static HELPER: Helper) +helper_init! { static HELPER: Helper } pub trait Callback { fn call(&mut self); diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index e46765f25b8..d1cb91bcdb3 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -169,7 +169,7 @@ pub mod compat { /// /// Note that arguments unused by the fallback implementation should not be called `_` as /// they are used to be passed to the real function if available. - macro_rules! compat_fn( + macro_rules! compat_fn { ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $fallback:block) => ( #[inline(always)] @@ -195,7 +195,7 @@ pub mod compat { ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => ( compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback) ) - ) + } /// Compatibility layer for functions in `kernel32.dll` /// @@ -211,20 +211,20 @@ pub mod compat { fn SetLastError(dwErrCode: DWORD); } - compat_fn!(kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR, + compat_fn! { kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR, _lpTargetFileName: LPCWSTR, _dwFlags: DWORD) -> BOOLEAN { unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); } 0 - }) + } } - compat_fn!(kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE, + compat_fn! { kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE, _lpszFilePath: LPCWSTR, _cchFilePath: DWORD, _dwFlags: DWORD) -> DWORD { unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); } 0 - }) + } } } } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 41361a0cde6..d22d4e0f534 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -24,7 +24,7 @@ use prelude::*; use io::{mod, IoResult, IoError}; use sync::{Once, ONCE_INIT}; -macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => ( +macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( static $name: Helper<$m> = Helper { lock: ::sync::MUTEX_INIT, cond: ::sync::CONDVAR_INIT, @@ -33,7 +33,7 @@ macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => ( initialized: ::cell::UnsafeCell { value: false }, shutdown: ::cell::UnsafeCell { value: false }, }; -) ) +) } pub mod c; pub mod ext; diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs index 9af3a7c8b6e..e2f9e2a9201 100644 --- a/src/libstd/sys/windows/timer.rs +++ b/src/libstd/sys/windows/timer.rs @@ -32,7 +32,7 @@ use sys_common::helper_thread::Helper; use prelude::*; use io::IoResult; -helper_init!(static HELPER: Helper) +helper_init! { static HELPER: Helper } pub trait Callback { fn call(&mut self); diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index 76fb703514b..1268ab8e0cf 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -109,7 +109,7 @@ pub struct Key { /// Declare a new thread local storage key of type `std::thread_local::Key`. #[macro_export] #[doc(hidden)] -macro_rules! thread_local( +macro_rules! thread_local { (static $name:ident: $t:ty = $init:expr) => ( static $name: ::std::thread_local::Key<$t> = { use std::cell::UnsafeCell as __UnsafeCell; @@ -119,7 +119,7 @@ macro_rules! thread_local( __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = { __UnsafeCell { value: __None } - }) + }); fn __init() -> $t { $init } fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> { &__KEY @@ -136,7 +136,7 @@ macro_rules! thread_local( __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = { __UnsafeCell { value: __None } - }) + }); fn __init() -> $t { $init } fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> { &__KEY @@ -144,7 +144,7 @@ macro_rules! thread_local( ::std::thread_local::Key { inner: __getit, init: __init } }; ); -) +} // Macro pain #4586: // @@ -167,7 +167,7 @@ macro_rules! thread_local( // itself. Woohoo. #[macro_export] -macro_rules! __thread_local_inner( +macro_rules! __thread_local_inner { (static $name:ident: $t:ty = $init:expr) => ( #[cfg_attr(any(target_os = "macos", target_os = "linux"), thread_local)] static $name: ::std::thread_local::KeyInner<$t> = @@ -204,7 +204,7 @@ macro_rules! __thread_local_inner( INIT }); -) +} impl Key { /// Acquire a reference to the value in this TLS key. @@ -459,7 +459,7 @@ mod tests { #[test] fn smoke_no_dtor() { - thread_local!(static FOO: UnsafeCell = UnsafeCell { value: 1 }) + thread_local!(static FOO: UnsafeCell = UnsafeCell { value: 1 }); FOO.with(|f| unsafe { assert_eq!(*f.get(), 1); @@ -483,7 +483,7 @@ mod tests { fn smoke_dtor() { thread_local!(static FOO: UnsafeCell> = UnsafeCell { value: None - }) + }); let (tx, rx) = channel(); spawn(move|| unsafe { @@ -501,10 +501,10 @@ mod tests { struct S2; thread_local!(static K1: UnsafeCell> = UnsafeCell { value: None - }) + }); thread_local!(static K2: UnsafeCell> = UnsafeCell { value: None - }) + }); static mut HITS: uint = 0; impl Drop for S1 { @@ -544,7 +544,7 @@ mod tests { struct S1; thread_local!(static K1: UnsafeCell> = UnsafeCell { value: None - }) + }); impl Drop for S1 { fn drop(&mut self) { @@ -562,10 +562,10 @@ mod tests { struct S1(Sender<()>); thread_local!(static K1: UnsafeCell> = UnsafeCell { value: None - }) + }); thread_local!(static K2: UnsafeCell> = UnsafeCell { value: None - }) + }); impl Drop for S1 { fn drop(&mut self) { @@ -597,7 +597,7 @@ mod dynamic_tests { #[test] fn smoke() { fn square(i: int) -> int { i * i } - thread_local!(static FOO: int = square(3)) + thread_local!(static FOO: int = square(3)); FOO.with(|f| { assert_eq!(*f, 9); @@ -611,7 +611,7 @@ mod dynamic_tests { m.insert(1, 2); RefCell::new(m) } - thread_local!(static FOO: RefCell> = map()) + thread_local!(static FOO: RefCell> = map()); FOO.with(|map| { assert_eq!(map.borrow()[1], 2); @@ -620,7 +620,7 @@ mod dynamic_tests { #[test] fn refcell_vec() { - thread_local!(static FOO: RefCell> = RefCell::new(vec![1, 2, 3])) + thread_local!(static FOO: RefCell> = RefCell::new(vec![1, 2, 3])); FOO.with(|vec| { assert_eq!(vec.borrow().len(), 3); diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs index ee742ab8375..7762d225b9a 100644 --- a/src/libstd/thread_local/scoped.rs +++ b/src/libstd/thread_local/scoped.rs @@ -24,7 +24,7 @@ //! # Example //! //! ``` -//! scoped_thread_local!(static FOO: uint) +//! scoped_thread_local!(static FOO: uint); //! //! // Initially each scoped slot is empty. //! assert!(!FOO.is_set()); @@ -60,18 +60,18 @@ pub struct Key { #[doc(hidden)] pub inner: KeyInner } /// This macro declares a `static` item on which methods are used to get and /// set the value stored within. #[macro_export] -macro_rules! scoped_thread_local( +macro_rules! scoped_thread_local { (static $name:ident: $t:ty) => ( __scoped_thread_local_inner!(static $name: $t) ); (pub static $name:ident: $t:ty) => ( __scoped_thread_local_inner!(pub static $name: $t) ); -) +} #[macro_export] #[doc(hidden)] -macro_rules! __scoped_thread_local_inner( +macro_rules! __scoped_thread_local_inner { (static $name:ident: $t:ty) => ( #[cfg_attr(not(any(windows, target_os = "android", target_os = "ios")), thread_local)] @@ -104,7 +104,7 @@ macro_rules! __scoped_thread_local_inner( INIT }) -) +} impl Key { /// Insert a value into this scoped thread local storage slot for a @@ -119,7 +119,7 @@ impl Key { /// # Example /// /// ``` - /// scoped_thread_local!(static FOO: uint) + /// scoped_thread_local!(static FOO: uint); /// /// FOO.set(&100, || { /// let val = FOO.with(|v| *v); @@ -171,7 +171,7 @@ impl Key { /// # Example /// /// ```no_run - /// scoped_thread_local!(static FOO: uint) + /// scoped_thread_local!(static FOO: uint); /// /// FOO.with(|slot| { /// // work with `slot` @@ -239,7 +239,7 @@ mod tests { #[test] fn smoke() { - scoped_thread_local!(static BAR: uint) + scoped_thread_local!(static BAR: uint); assert!(!BAR.is_set()); BAR.set(&1, || { @@ -253,7 +253,7 @@ mod tests { #[test] fn cell_allowed() { - scoped_thread_local!(static BAR: Cell) + scoped_thread_local!(static BAR: Cell); BAR.set(&Cell::new(1), || { BAR.with(|slot| { diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index f98cebd9675..8c4a5a6b8c7 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -40,9 +40,9 @@ const SECS_PER_DAY: i64 = 86400; /// The number of (non-leap) seconds in a week. const SECS_PER_WEEK: i64 = 604800; -macro_rules! try_opt( +macro_rules! try_opt { ($e:expr) => (match $e { Some(v) => v, None => return None }) -) +} /// ISO 8601 time duration with nanosecond precision. diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 98d858babb1..d4860766d47 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -31,6 +31,7 @@ pub use self::Lit_::*; pub use self::LitIntType::*; pub use self::LocalSource::*; pub use self::Mac_::*; +pub use self::MacStmtStyle::*; pub use self::MatchSource::*; pub use self::MetaItem_::*; pub use self::Method_::*; @@ -615,8 +616,20 @@ pub enum Stmt_ { /// Expr with trailing semi-colon (may have any type): StmtSemi(P, NodeId), - /// bool: is there a trailing semi-colon? - StmtMac(Mac, bool), + StmtMac(Mac, MacStmtStyle), +} + +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub enum MacStmtStyle { + /// The macro statement had a trailing semicolon, e.g. `foo! { ... };` + /// `foo!(...);`, `foo![...];` + MacStmtWithSemicolon, + /// The macro statement had braces; e.g. foo! { ... } + MacStmtWithBraces, + /// The macro statement had parentheses or brackets and no semicolon; e.g. + /// `foo!(...)`. All of these will end up being converted into macro + /// expressions. + MacStmtWithoutBraces, } /// Where a local declaration came from: either a true `let ... = diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 2e097d45515..aaa172633be 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -753,16 +753,20 @@ macro_rules! mf_method{ impl PostExpansionMethod for Method { - mf_method!(pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident) - mf_method!(pe_generics,&'a ast::Generics, - MethDecl(_,ref generics,_,_,_,_,_,_),generics) - mf_method!(pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi) - mf_method!(pe_explicit_self,&'a ast::ExplicitSelf, - MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self) - mf_method!(pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety) - mf_method!(pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl) - mf_method!(pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body) - mf_method!(pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis) + mf_method! { pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident } + mf_method! { + pe_generics,&'a ast::Generics, + MethDecl(_,ref generics,_,_,_,_,_,_),generics + } + mf_method! { pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi } + mf_method! { + pe_explicit_self,&'a ast::ExplicitSelf, + MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self + } + mf_method! { pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety } + mf_method! { pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl } + mf_method! { pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body } + mf_method! { pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis } } #[cfg(test)] diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 8248eae4b8c..598da6a5df0 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -29,7 +29,7 @@ use std::cell::{RefCell, Cell}; use std::collections::BitvSet; use std::collections::HashSet; -thread_local!(static USED_ATTRS: RefCell = RefCell::new(BitvSet::new())) +thread_local! { static USED_ATTRS: RefCell = RefCell::new(BitvSet::new()) } pub fn mark_used(attr: &Attribute) { let AttrId(id) = attr.node.id; @@ -169,7 +169,7 @@ pub fn mk_word_item(name: InternedString) -> P { P(dummy_spanned(MetaWord(name))) } -thread_local!(static NEXT_ATTR_ID: Cell = Cell::new(0)) +thread_local! { static NEXT_ATTR_ID: Cell = Cell::new(0) } pub fn mk_attr_id() -> AttrId { let id = NEXT_ATTR_ID.with(|slot| { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 592fdd7207c..17cafc2441f 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -329,7 +329,7 @@ impl FileMap { // the new charpos must be > the last one (or it's the first one). let mut lines = self.lines.borrow_mut(); let line_len = lines.len(); - assert!(line_len == 0 || ((*lines)[line_len - 1] < pos)) + assert!(line_len == 0 || ((*lines)[line_len - 1] < pos)); lines.push(pos); } diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index b4bf793d4e1..3107508a96a 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -11,44 +11,45 @@ #![macro_escape] #[macro_export] -macro_rules! register_diagnostic( - ($code:tt, $description:tt) => (__register_diagnostic!($code, $description)); - ($code:tt) => (__register_diagnostic!($code)) -) +macro_rules! register_diagnostic { + ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description }); + ($code:tt) => (__register_diagnostic! { $code }) +} #[macro_export] -macro_rules! span_err( +macro_rules! span_err { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ __diagnostic_used!($code); $session.span_err_with_code($span, format!($($message)*).as_slice(), stringify!($code)) }) -) +} #[macro_export] -macro_rules! span_warn( +macro_rules! span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ __diagnostic_used!($code); $session.span_warn_with_code($span, format!($($message)*).as_slice(), stringify!($code)) }) -) +} #[macro_export] -macro_rules! span_note( +macro_rules! span_note { ($session:expr, $span:expr, $($message:tt)*) => ({ ($session).span_note($span, format!($($message)*).as_slice()) }) -) +} #[macro_export] -macro_rules! span_help( +macro_rules! span_help { ($session:expr, $span:expr, $($message:tt)*) => ({ ($session).span_help($span, format!($($message)*).as_slice()) }) -) +} #[macro_export] -macro_rules! register_diagnostics( +macro_rules! register_diagnostics { ($($code:tt),*) => ( - $(register_diagnostic!($code))* + $(register_diagnostic! { $code })* ) -) +} + diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index cb2a1f8acd8..bcce5538314 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -18,12 +18,16 @@ use ext::build::AstBuilder; use parse::token; use ptr::P; -thread_local!(static REGISTERED_DIAGNOSTICS: RefCell>> = { - RefCell::new(HashMap::new()) -}) -thread_local!(static USED_DIAGNOSTICS: RefCell> = { - RefCell::new(HashMap::new()) -}) +thread_local! { + static REGISTERED_DIAGNOSTICS: RefCell>> = { + RefCell::new(HashMap::new()) + } +} +thread_local! { + static USED_DIAGNOSTICS: RefCell> = { + RefCell::new(HashMap::new()) + } +} fn with_registered_diagnostics(f: F) -> T where F: FnOnce(&mut HashMap>) -> T, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index e280e6e4491..20c8ff20b71 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -11,7 +11,8 @@ use self::Either::*; use ast::{Block, Crate, DeclLocal, ExprMac, PatMac}; use ast::{Local, Ident, MacInvocTT}; -use ast::{ItemMac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi}; +use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac}; +use ast::{StmtExpr, StmtSemi}; use ast::TokenTree; use ast; use ext::mtwt; @@ -354,7 +355,7 @@ fn expand_loop_block(loop_block: P, // eval $e with a new exts frame. // must be a macro so that $e isn't evaluated too early. -macro_rules! with_exts_frame ( +macro_rules! with_exts_frame { ($extsboxexpr:expr,$macros_escape:expr,$e:expr) => ({$extsboxexpr.push_frame(); $extsboxexpr.info().macros_escape = $macros_escape; @@ -362,7 +363,7 @@ macro_rules! with_exts_frame ( $extsboxexpr.pop_frame(); result }) -) +} // When we enter a module, record it, for the sake of `module!` pub fn expand_item(it: P, fld: &mut MacroExpander) @@ -636,8 +637,8 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) // I don't understand why this returns a vector... it looks like we're // half done adding machinery to allow macros to expand into multiple statements. fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector> { - let (mac, semi) = match s.node { - StmtMac(mac, semi) => (mac, semi), + let (mac, style) = match s.node { + StmtMac(mac, style) => (mac, style), _ => return expand_non_macro_stmt(s, fld) }; let expanded_stmt = match expand_mac_invoc(mac, s.span, @@ -653,7 +654,7 @@ fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector> { let fully_expanded = fld.fold_stmt(expanded_stmt); fld.cx.bt_pop(); - if semi { + if style == MacStmtWithSemicolon { fully_expanded.into_iter().map(|s| s.map(|Spanned {node, span}| { Spanned { node: match node { @@ -1324,7 +1325,7 @@ mod test { // make sure that macros can't escape fns #[should_fail] #[test] fn macros_cant_escape_fns_test () { - let src = "fn bogus() {macro_rules! z (() => (3+4))}\ + let src = "fn bogus() {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1338,7 +1339,7 @@ mod test { // make sure that macros can't escape modules #[should_fail] #[test] fn macros_cant_escape_mods_test () { - let src = "mod foo {macro_rules! z (() => (3+4))}\ + let src = "mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1350,7 +1351,7 @@ mod test { // macro_escape modules should allow macros to escape #[test] fn macros_can_escape_flattened_mods_test () { - let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4))}\ + let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1402,13 +1403,13 @@ mod test { #[test] fn macro_tokens_should_match(){ expand_crate_str( - "macro_rules! m((a)=>(13)) fn main(){m!(a);}".to_string()); + "macro_rules! m((a)=>(13)) ;fn main(){m!(a);}".to_string()); } // should be able to use a bound identifier as a literal in a macro definition: #[test] fn self_macro_parsing(){ expand_crate_str( - "macro_rules! foo ((zz) => (287u;)) + "macro_rules! foo ((zz) => (287u;)); fn f(zz : int) {foo!(zz);}".to_string() ); } @@ -1451,16 +1452,16 @@ mod test { ("fn main () {let x: int = 13;x;}", vec!(vec!(0)), false), // the use of b after the + should be renamed, the other one not: - ("macro_rules! f (($x:ident) => (b + $x)) fn a() -> int { let b = 13; f!(b)}", + ("macro_rules! f (($x:ident) => (b + $x)); fn a() -> int { let b = 13; f!(b)}", vec!(vec!(1)), false), // the b before the plus should not be renamed (requires marks) - ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})) fn a() -> int { f!(b)}", + ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})); fn a() -> int { f!(b)}", vec!(vec!(1)), false), // the marks going in and out of letty should cancel, allowing that $x to // capture the one following the semicolon. // this was an awesome test case, and caught a *lot* of bugs. - ("macro_rules! letty(($x:ident) => (let $x = 15;)) - macro_rules! user(($x:ident) => ({letty!($x); $x})) + ("macro_rules! letty(($x:ident) => (let $x = 15;)); + macro_rules! user(($x:ident) => ({letty!($x); $x})); fn main() -> int {user!(z)}", vec!(vec!(0)), false) ); @@ -1488,7 +1489,7 @@ mod test { #[test] fn issue_6994(){ run_renaming_test( &("macro_rules! g (($x:ident) => - ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)})) + ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)})); fn a(){g!(z)}", vec!(vec!(0)),false), 0) @@ -1498,7 +1499,7 @@ mod test { // fn z() {match 8 {x_1 => {match 9 {x_2 | x_2 if x_2 == x_1 => x_2 + x_1}}}} #[test] fn issue_9384(){ run_renaming_test( - &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}})) + &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}})); fn z() {match 8 {x => bad_macro!(x)}}", // NB: the third "binding" is the repeat of the second one. vec!(vec!(1,3),vec!(0,2),vec!(0,2)), @@ -1511,8 +1512,8 @@ mod test { // fn main(){let g1_1 = 13; g1_1}} #[test] fn pat_expand_issue_15221(){ run_renaming_test( - &("macro_rules! inner ( ($e:pat ) => ($e)) - macro_rules! outer ( ($e:pat ) => (inner!($e))) + &("macro_rules! inner ( ($e:pat ) => ($e)); + macro_rules! outer ( ($e:pat ) => (inner!($e))); fn main() { let outer!(g) = 13; g;}", vec!(vec!(0)), true), @@ -1527,8 +1528,8 @@ mod test { // method expands to fn get_x(&self_0, x_1:int) {self_0 + self_2 + x_3 + x_1} #[test] fn method_arg_hygiene(){ run_renaming_test( - &("macro_rules! inject_x (()=>(x)) - macro_rules! inject_self (()=>(self)) + &("macro_rules! inject_x (()=>(x)); + macro_rules! inject_self (()=>(self)); struct A; impl A{fn get_x(&self, x: int) {self + inject_self!() + inject_x!() + x;} }", vec!(vec!(0),vec!(3)), @@ -1542,8 +1543,8 @@ mod test { run_renaming_test( &("struct A; macro_rules! add_method (($T:ty) => - (impl $T { fn thingy(&self) {self;} })) - add_method!(A)", + (impl $T { fn thingy(&self) {self;} })); + add_method!(A);", vec!(vec!(0)), true), 0) @@ -1553,7 +1554,7 @@ mod test { // expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};} #[test] fn issue_9383(){ run_renaming_test( - &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex })) + &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex })); fn q(x:int) { bad_macro!(x); }", vec!(vec!(1),vec!(0)),true), 0) @@ -1563,7 +1564,7 @@ mod test { // expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);} #[test] fn closure_arg_hygiene(){ run_renaming_test( - &("macro_rules! inject_x (()=>(x)) + &("macro_rules! inject_x (()=>(x)); fn f(){(|x : int| {(inject_x!() + x)})(3);}", vec!(vec!(1)), true), @@ -1573,9 +1574,9 @@ mod test { // macro_rules in method position. Sadly, unimplemented. #[test] fn macro_in_method_posn(){ expand_crate_str( - "macro_rules! my_method (() => (fn thirteen(&self) -> int {13})) + "macro_rules! my_method (() => (fn thirteen(&self) -> int {13})); struct A; - impl A{ my_method!()} + impl A{ my_method!(); } fn f(){A.thirteen;}".to_string()); } @@ -1586,7 +1587,7 @@ mod test { &("macro_rules! item { ($i:item) => {$i}} struct Entries; macro_rules! iterator_impl { - () => { item!( impl Entries { fn size_hint(&self) { self;}})}} + () => { item!( impl Entries { fn size_hint(&self) { self;}});}} iterator_impl! { }", vec!(vec!(0)), true), 0) @@ -1666,9 +1667,9 @@ mod test { } #[test] fn fmt_in_macro_used_inside_module_macro() { - let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string())) -macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}})) -foo_module!() + let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string())); +macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}})); +foo_module!(); ".to_string(); let cr = expand_crate_str(crate_str); // find the xx binding diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index a4e06aeaf63..33936e6213f 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -108,7 +108,7 @@ pub fn apply_renames(renames: &RenameList, ctxt: SyntaxContext) -> SyntaxContext pub fn with_sctable(op: F) -> T where F: FnOnce(&SCTable) -> T, { - thread_local!(static SCTABLE_KEY: SCTable = new_sctable_internal()) + thread_local!(static SCTABLE_KEY: SCTable = new_sctable_internal()); SCTABLE_KEY.with(move |slot| op(slot)) } @@ -174,7 +174,7 @@ fn with_resolve_table_mut(op: F) -> T where { thread_local!(static RESOLVE_TABLE_KEY: RefCell = { RefCell::new(HashMap::new()) - }) + }); RESOLVE_TABLE_KEY.with(move |slot| op(&mut *slot.borrow_mut())) } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 45752499ad5..14e13feac98 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -100,7 +100,7 @@ pub mod rt { fn to_source_with_hygiene(&self) -> String; } - macro_rules! impl_to_source( + macro_rules! impl_to_source { (P<$t:ty>, $pp:ident) => ( impl ToSource for P<$t> { fn to_source(&self) -> String { @@ -125,7 +125,7 @@ pub mod rt { } } ); - ) + } fn slice_to_source<'a, T: ToSource>(sep: &'static str, xs: &'a [T]) -> String { xs.iter() @@ -144,7 +144,7 @@ pub mod rt { .to_string() } - macro_rules! impl_to_source_slice( + macro_rules! impl_to_source_slice { ($t:ty, $sep:expr) => ( impl ToSource for [$t] { fn to_source(&self) -> String { @@ -158,7 +158,7 @@ pub mod rt { } } ) - ) + } impl ToSource for ast::Ident { fn to_source(&self) -> String { @@ -172,18 +172,18 @@ pub mod rt { } } - impl_to_source!(ast::Ty, ty_to_string) - impl_to_source!(ast::Block, block_to_string) - impl_to_source!(ast::Arg, arg_to_string) - impl_to_source!(Generics, generics_to_string) - impl_to_source!(P, item_to_string) - impl_to_source!(P, method_to_string) - impl_to_source!(P, stmt_to_string) - impl_to_source!(P, expr_to_string) - impl_to_source!(P, pat_to_string) - impl_to_source!(ast::Arm, arm_to_string) - impl_to_source_slice!(ast::Ty, ", ") - impl_to_source_slice!(P, "\n\n") + impl_to_source! { ast::Ty, ty_to_string } + impl_to_source! { ast::Block, block_to_string } + impl_to_source! { ast::Arg, arg_to_string } + impl_to_source! { Generics, generics_to_string } + impl_to_source! { P, item_to_string } + impl_to_source! { P, method_to_string } + impl_to_source! { P, stmt_to_string } + impl_to_source! { P, expr_to_string } + impl_to_source! { P, pat_to_string } + impl_to_source! { ast::Arm, arm_to_string } + impl_to_source_slice! { ast::Ty, ", " } + impl_to_source_slice! { P, "\n\n" } impl ToSource for ast::Attribute_ { fn to_source(&self) -> String { @@ -244,7 +244,7 @@ pub mod rt { } } - macro_rules! impl_to_source_int( + macro_rules! impl_to_source_int { (signed, $t:ty, $tag:ident) => ( impl ToSource for $t { fn to_source(&self) -> String { @@ -272,23 +272,23 @@ pub mod rt { } } ); - ) + } - impl_to_source_int!(signed, int, TyI) - impl_to_source_int!(signed, i8, TyI8) - impl_to_source_int!(signed, i16, TyI16) - impl_to_source_int!(signed, i32, TyI32) - impl_to_source_int!(signed, i64, TyI64) + impl_to_source_int! { signed, int, TyI } + impl_to_source_int! { signed, i8, TyI8 } + impl_to_source_int! { signed, i16, TyI16 } + impl_to_source_int! { signed, i32, TyI32 } + impl_to_source_int! { signed, i64, TyI64 } - impl_to_source_int!(unsigned, uint, TyU) - impl_to_source_int!(unsigned, u8, TyU8) - impl_to_source_int!(unsigned, u16, TyU16) - impl_to_source_int!(unsigned, u32, TyU32) - impl_to_source_int!(unsigned, u64, TyU64) + impl_to_source_int! { unsigned, uint, TyU } + impl_to_source_int! { unsigned, u8, TyU8 } + impl_to_source_int! { unsigned, u16, TyU16 } + impl_to_source_int! { unsigned, u32, TyU32 } + impl_to_source_int! { unsigned, u64, TyU64 } // Alas ... we write these out instead. All redundant. - macro_rules! impl_to_tokens( + macro_rules! impl_to_tokens { ($t:ty) => ( impl ToTokens for $t { fn to_tokens(&self, cx: &ExtCtxt) -> Vec { @@ -296,9 +296,9 @@ pub mod rt { } } ) - ) + } - macro_rules! impl_to_tokens_lifetime( + macro_rules! impl_to_tokens_lifetime { ($t:ty) => ( impl<'a> ToTokens for $t { fn to_tokens(&self, cx: &ExtCtxt) -> Vec { @@ -306,36 +306,36 @@ pub mod rt { } } ) - ) - - impl_to_tokens!(ast::Ident) - impl_to_tokens!(P) - impl_to_tokens!(P) - impl_to_tokens!(ast::Arm) - impl_to_tokens!(P) - impl_to_tokens_lifetime!(&'a [P]) - impl_to_tokens!(ast::Ty) - impl_to_tokens_lifetime!(&'a [ast::Ty]) - impl_to_tokens!(Generics) - impl_to_tokens!(P) - impl_to_tokens!(P) - impl_to_tokens!(ast::Block) - impl_to_tokens!(ast::Arg) - impl_to_tokens!(ast::Attribute_) - impl_to_tokens_lifetime!(&'a str) - impl_to_tokens!(()) - impl_to_tokens!(char) - impl_to_tokens!(bool) - impl_to_tokens!(int) - impl_to_tokens!(i8) - impl_to_tokens!(i16) - impl_to_tokens!(i32) - impl_to_tokens!(i64) - impl_to_tokens!(uint) - impl_to_tokens!(u8) - impl_to_tokens!(u16) - impl_to_tokens!(u32) - impl_to_tokens!(u64) + } + + impl_to_tokens! { ast::Ident } + impl_to_tokens! { P } + impl_to_tokens! { P } + impl_to_tokens! { ast::Arm } + impl_to_tokens! { P } + impl_to_tokens_lifetime! { &'a [P] } + impl_to_tokens! { ast::Ty } + impl_to_tokens_lifetime! { &'a [ast::Ty] } + impl_to_tokens! { Generics } + impl_to_tokens! { P } + impl_to_tokens! { P } + impl_to_tokens! { ast::Block } + impl_to_tokens! { ast::Arg } + impl_to_tokens! { ast::Attribute_ } + impl_to_tokens_lifetime! { &'a str } + impl_to_tokens! { () } + impl_to_tokens! { char } + impl_to_tokens! { bool } + impl_to_tokens! { int } + impl_to_tokens! { i8 } + impl_to_tokens! { i16 } + impl_to_tokens! { i32 } + impl_to_tokens! { i64 } + impl_to_tokens! { uint } + impl_to_tokens! { u8 } + impl_to_tokens! { u16 } + impl_to_tokens! { u32 } + impl_to_tokens! { u64 } pub trait ExtParseUtils { fn parse_item(&self, s: String) -> P; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 7d2acd08d94..10860ee5e01 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1485,7 +1485,7 @@ mod test { } // maybe add to expand.rs... - macro_rules! assert_pred ( + macro_rules! assert_pred { ($pred:expr, $predname:expr, $a:expr , $b:expr) => ( { let pred_val = $pred; @@ -1497,7 +1497,7 @@ mod test { } } ) - ) + } // make sure idents get transformed everywhere #[test] fn ident_transformation () { @@ -1523,6 +1523,6 @@ mod test { matches_codepattern, "matches_codepattern", pprust::to_string(|s| fake_print_crate(s, &folded_crate)), - "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))".to_string()); + "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string()); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6e3cfe5854a..c234c172fd8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -40,9 +40,10 @@ use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitStr, LitInt, Local, LocalLet}; +use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces}; use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchNormal}; use ast::{Method, MutTy, BiMul, Mutability}; -use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot}; +use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle}; use ast::{PolyTraitRef}; @@ -132,7 +133,7 @@ enum ItemOrViewItem { /// macro expansion). Placement of these is not as complex as I feared it would /// be. The important thing is to make sure that lookahead doesn't balk at /// `token::Interpolated` tokens. -macro_rules! maybe_whole_expr ( +macro_rules! maybe_whole_expr { ($p:expr) => ( { let found = match $p.token { @@ -170,10 +171,10 @@ macro_rules! maybe_whole_expr ( } } ) -) +} /// As maybe_whole_expr, but for things other than expressions -macro_rules! maybe_whole ( +macro_rules! maybe_whole { ($p:expr, $constructor:ident) => ( { let found = match ($p).token { @@ -252,7 +253,7 @@ macro_rules! maybe_whole ( } } ) -) +} fn maybe_append(mut lhs: Vec, rhs: Option>) @@ -3708,21 +3709,32 @@ impl<'a> Parser<'a> { ); let hi = self.span.hi; + let style = if delim == token::Brace { + MacStmtWithBraces + } else { + MacStmtWithoutBraces + }; + if id.name == token::special_idents::invalid.name { - if self.check(&token::Dot) { - let span = self.span; - let token_string = self.this_token_to_string(); - self.span_err(span, - format!("expected statement, found `{}`", - token_string).as_slice()); - let mac_span = mk_sp(lo, hi); - self.span_help(mac_span, "try parenthesizing this macro invocation"); - self.abort_if_errors(); - } - P(spanned(lo, hi, StmtMac( - spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT)), false))) + P(spanned(lo, + hi, + StmtMac(spanned(lo, + hi, + MacInvocTT(pth, tts, EMPTY_CTXT)), + style))) } else { // if it has a special ident, it's definitely an item + // + // Require a semicolon or braces. + if style != MacStmtWithBraces { + if !self.eat(&token::Semi) { + let last_span = self.last_span; + self.span_err(last_span, + "macros that expand to items must \ + either be surrounded with braces or \ + followed by a semicolon"); + } + } P(spanned(lo, hi, StmtDecl( P(spanned(lo, hi, DeclItem( self.mk_item( @@ -3731,7 +3743,6 @@ impl<'a> Parser<'a> { Inherited, Vec::new(/*no attrs*/))))), ast::DUMMY_NODE_ID))) } - } else { let found_attrs = !item_attrs.is_empty(); let item_err = Parser::expected_item_err(item_attrs.as_slice()); @@ -3851,43 +3862,46 @@ impl<'a> Parser<'a> { attributes_box = Vec::new(); stmt.and_then(|Spanned {node, span}| match node { StmtExpr(e, stmt_id) => { - // expression without semicolon - if classify::expr_requires_semi_to_be_stmt(&*e) { - // Just check for errors and recover; do not eat semicolon yet. - self.commit_stmt(&[], &[token::Semi, - token::CloseDelim(token::Brace)]); - } - + self.handle_expression_like_statement(e, + stmt_id, + span, + &mut stmts, + &mut expr); + } + StmtMac(macro, MacStmtWithoutBraces) => { + // statement macro without braces; might be an + // expr depending on whether a semicolon follows match self.token { token::Semi => { - self.bump(); - let span_with_semi = Span { - lo: span.lo, - hi: self.last_span.hi, - expn_id: span.expn_id, - }; stmts.push(P(Spanned { - node: StmtSemi(e, stmt_id), - span: span_with_semi, + node: StmtMac(macro, + MacStmtWithSemicolon), + span: span, })); - } - token::CloseDelim(token::Brace) => { - expr = Some(e); + self.bump(); } _ => { - stmts.push(P(Spanned { - node: StmtExpr(e, stmt_id), - span: span - })); + let e = self.mk_mac_expr(span.lo, + span.hi, + macro.node); + let e = + self.parse_dot_or_call_expr_with(e); + self.handle_expression_like_statement( + e, + ast::DUMMY_NODE_ID, + span, + &mut stmts, + &mut expr); } } } - StmtMac(m, semi) => { + StmtMac(m, style) => { // statement macro; might be an expr match self.token { token::Semi => { stmts.push(P(Spanned { - node: StmtMac(m, true), + node: StmtMac(m, + MacStmtWithSemicolon), span: span, })); self.bump(); @@ -3902,7 +3916,7 @@ impl<'a> Parser<'a> { } _ => { stmts.push(P(Spanned { - node: StmtMac(m, semi), + node: StmtMac(m, style), span: span })); } @@ -3941,6 +3955,43 @@ impl<'a> Parser<'a> { }) } + fn handle_expression_like_statement( + &mut self, + e: P, + stmt_id: NodeId, + span: Span, + stmts: &mut Vec>, + last_block_expr: &mut Option>) { + // expression without semicolon + if classify::expr_requires_semi_to_be_stmt(&*e) { + // Just check for errors and recover; do not eat semicolon yet. + self.commit_stmt(&[], + &[token::Semi, token::CloseDelim(token::Brace)]); + } + + match self.token { + token::Semi => { + self.bump(); + let span_with_semi = Span { + lo: span.lo, + hi: self.last_span.hi, + expn_id: span.expn_id, + }; + stmts.push(P(Spanned { + node: StmtSemi(e, stmt_id), + span: span_with_semi, + })); + } + token::CloseDelim(token::Brace) => *last_block_expr = Some(e), + _ => { + stmts.push(P(Spanned { + node: StmtExpr(e, stmt_id), + span: span + })); + } + } + } + // Parses a sequence of bounds if a `:` is found, // otherwise returns empty list. fn parse_colon_then_ty_param_bounds(&mut self) @@ -4591,6 +4642,9 @@ impl<'a> Parser<'a> { let m: ast::Mac = codemap::Spanned { node: m_, span: mk_sp(self.span.lo, self.span.hi) }; + if delim != token::Brace { + self.expect(&token::Semi) + } (ast::MethMac(m), self.span.hi, attrs) } else { let unsafety = self.parse_unsafety(); @@ -5747,6 +5801,17 @@ impl<'a> Parser<'a> { let m: ast::Mac = codemap::Spanned { node: m, span: mk_sp(self.span.lo, self.span.hi) }; + + if delim != token::Brace { + if !self.eat(&token::Semi) { + let last_span = self.last_span; + self.span_err(last_span, + "macros that expand to items must either \ + be surrounded with braces or followed by \ + a semicolon"); + } + } + let item_ = ItemMac(m); let last_span = self.last_span; let item = self.mk_item(lo, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 1bdcd73d847..641239f1f8b 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -570,7 +570,7 @@ pub type IdentInterner = StrInterner; pub fn get_ident_interner() -> Rc { thread_local!(static KEY: Rc<::parse::token::IdentInterner> = { Rc::new(mk_fresh_ident_interner()) - }) + }); KEY.with(|k| k.clone()) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index cbbfcfef72e..1dd61a5ce19 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -409,12 +409,12 @@ pub fn arg_to_string(arg: &ast::Arg) -> String { } pub fn mac_to_string(arg: &ast::Mac) -> String { - $to_string(|s| s.print_mac(arg)) + $to_string(|s| s.print_mac(arg, ::parse::token::Paren)) } } } -thing_to_string_impls!(to_string) +thing_to_string_impls! { to_string } // FIXME (Issue #16472): the whole `with_hygiene` mod should go away // after we revise the syntax::ext::quote::ToToken impls to go directly @@ -437,7 +437,7 @@ pub mod with_hygiene { }) } - thing_to_string_impls!(to_string_hyg) + thing_to_string_impls! { to_string_hyg } } pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String { @@ -992,6 +992,7 @@ impl<'a> State<'a> { try!(self.popen()); try!(self.print_tts(tts.as_slice())); try!(self.pclose()); + try!(word(&mut self.s, ";")); try!(self.end()); } } @@ -1258,6 +1259,7 @@ impl<'a> State<'a> { try!(self.popen()); try!(self.print_tts(tts.as_slice())); try!(self.pclose()); + try!(word(&mut self.s, ";")); self.end() } } @@ -1330,11 +1332,16 @@ impl<'a> State<'a> { try!(self.print_expr(&**expr)); try!(word(&mut self.s, ";")); } - ast::StmtMac(ref mac, semi) => { + ast::StmtMac(ref mac, style) => { try!(self.space_if_not_bol()); - try!(self.print_mac(mac)); - if semi { - try!(word(&mut self.s, ";")); + let delim = match style { + ast::MacStmtWithBraces => token::Brace, + _ => token::Paren + }; + try!(self.print_mac(mac, delim)); + match style { + ast::MacStmtWithBraces => {} + _ => try!(word(&mut self.s, ";")), } } } @@ -1461,15 +1468,24 @@ impl<'a> State<'a> { self.print_else(elseopt) } - pub fn print_mac(&mut self, m: &ast::Mac) -> IoResult<()> { + pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) + -> IoResult<()> { match m.node { // I think it's reasonable to hide the ctxt here: ast::MacInvocTT(ref pth, ref tts, _) => { try!(self.print_path(pth, false)); try!(word(&mut self.s, "!")); - try!(self.popen()); + match delim { + token::Paren => try!(self.popen()), + token::Bracket => try!(word(&mut self.s, "[")), + token::Brace => try!(self.bopen()), + } try!(self.print_tts(tts.as_slice())); - self.pclose() + match delim { + token::Paren => self.pclose(), + token::Bracket => word(&mut self.s, "]"), + token::Brace => self.bclose(m.span), + } } } } @@ -1817,7 +1833,7 @@ impl<'a> State<'a> { })); try!(self.pclose()); } - ast::ExprMac(ref m) => try!(self.print_mac(m)), + ast::ExprMac(ref m) => try!(self.print_mac(m, token::Paren)), ast::ExprParen(ref e) => { try!(self.popen()); try!(self.print_expr(&**e)); @@ -2098,7 +2114,7 @@ impl<'a> State<'a> { |s, p| s.print_pat(&**p))); try!(word(&mut self.s, "]")); } - ast::PatMac(ref m) => try!(self.print_mac(m)), + ast::PatMac(ref m) => try!(self.print_mac(m, token::Paren)), } self.ann.post(self, NodePat(pat)) } @@ -2187,7 +2203,7 @@ impl<'a> State<'a> { try!(self.nbsp()); try!(self.print_ident(name)); try!(self.print_generics(generics)); - try!(self.print_fn_args_and_ret(decl, opt_explicit_self)) + try!(self.print_fn_args_and_ret(decl, opt_explicit_self)); self.print_where_clause(generics) } diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index 9b5e6f5cc9f..fe96d7b8b7d 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -165,7 +165,7 @@ pub fn parse(file: &mut io::Reader, longnames: bool) Ok(e) => e, Err(e) => return Err(format!("{}", e)) } - ) ) + ) ); let bnames; let snames; diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index f9e6907f0e8..7441b39f35b 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -459,14 +459,14 @@ mod tests { use std::io; use std::f64; - macro_rules! assert_approx_eq( + macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ use std::num::Float; let (a, b) = (&$a, &$b); assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); }) - ) + } fn check(samples: &[f64], summ: &Summary) { diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index 4790ae11b21..add54ed01e0 100644 --- a/src/test/auxiliary/lint_group_plugin_test.rs +++ b/src/test/auxiliary/lint_group_plugin_test.rs @@ -23,11 +23,9 @@ use syntax::parse::token; use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; use rustc::plugin::Registry; -declare_lint!(TEST_LINT, Warn, - "Warn about items named 'lintme'") +declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); -declare_lint!(PLEASE_LINT, Warn, - "Warn about items named 'pleaselintme'") +declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'"); struct Pass; diff --git a/src/test/auxiliary/lint_plugin_test.rs b/src/test/auxiliary/lint_plugin_test.rs index e18cef6d136..6c78cdce28a 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -23,8 +23,7 @@ use syntax::parse::token; use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; use rustc::plugin::Registry; -declare_lint!(TEST_LINT, Warn, - "Warn about items named 'lintme'") +declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); struct Pass; diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index 0be2f31e282..82af18b189b 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -183,14 +183,14 @@ pub struct LockedTupleStruct(pub int); #[macro_export] macro_rules! macro_test( () => (deprecated()); -) +); #[macro_export] macro_rules! macro_test_arg( ($func:expr) => ($func); -) +); #[macro_export] macro_rules! macro_test_arg_nested( ($func:ident) => (macro_test_arg!($func())); -) +); diff --git a/src/test/auxiliary/macro_crate_def_only.rs b/src/test/auxiliary/macro_crate_def_only.rs index 56053a0cd75..ad3e72f5fa2 100644 --- a/src/test/auxiliary/macro_crate_def_only.rs +++ b/src/test/auxiliary/macro_crate_def_only.rs @@ -13,4 +13,4 @@ #[macro_export] macro_rules! make_a_5( () => (5) -) +); diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index 1c26ac26d7c..b82cfcbc8fc 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -24,9 +24,9 @@ use syntax::ptr::P; use rustc::plugin::Registry; #[macro_export] -macro_rules! exported_macro (() => (2i)) +macro_rules! exported_macro (() => (2i)); -macro_rules! unexported_macro (() => (3i)) +macro_rules! unexported_macro (() => (3i)); #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { diff --git a/src/test/auxiliary/macro_export_inner_module.rs b/src/test/auxiliary/macro_export_inner_module.rs index 1e8c15f6b44..9b4b1ceb5c1 100644 --- a/src/test/auxiliary/macro_export_inner_module.rs +++ b/src/test/auxiliary/macro_export_inner_module.rs @@ -14,5 +14,5 @@ pub mod inner { #[macro_export] macro_rules! foo( () => (1) - ) + ); } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 6e2cd508291..16129593485 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -31,7 +31,7 @@ fn main() { ($id:ident) => (maybe_run_test(argv.as_slice(), stringify!($id).to_string(), - $id))) + $id))); bench!(shift_push); bench!(read_line); diff --git a/src/test/compile-fail/const-block-non-item-statement.rs b/src/test/compile-fail/const-block-non-item-statement.rs index d8f771cfb5a..0a004c101ee 100644 --- a/src/test/compile-fail/const-block-non-item-statement.rs +++ b/src/test/compile-fail/const-block-non-item-statement.rs @@ -19,7 +19,7 @@ static B: uint = { { } 2 }; macro_rules! foo { () => (()) //~ ERROR: blocks in constants are limited to items and tail expressions } -static C: uint = { foo!() 2 }; +static C: uint = { foo!(); 2 }; static D: uint = { let x = 4u; 2 }; //~^ ERROR: blocks in constants are limited to items and tail expressions diff --git a/src/test/compile-fail/gated-macro-rules.rs b/src/test/compile-fail/gated-macro-rules.rs index 7f771c72416..ae2f03fd5f7 100644 --- a/src/test/compile-fail/gated-macro-rules.rs +++ b/src/test/compile-fail/gated-macro-rules.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! foo(() => ()) +macro_rules! foo(() => ()); //~^ ERROR: macro definitions are not stable enough for use fn main() {} diff --git a/src/test/compile-fail/infinite-macro-expansion.rs b/src/test/compile-fail/infinite-macro-expansion.rs index 67a7cdf1024..22ac2eb1f7d 100644 --- a/src/test/compile-fail/infinite-macro-expansion.rs +++ b/src/test/compile-fail/infinite-macro-expansion.rs @@ -14,7 +14,7 @@ macro_rules! recursive( () => ( recursive!() //~ ERROR recursion limit reached while expanding the macro `recursive` ) - ) + ); fn main() { recursive!() diff --git a/src/test/compile-fail/issue-19734.rs b/src/test/compile-fail/issue-19734.rs index cee92cae2aa..ab88b580ba1 100644 --- a/src/test/compile-fail/issue-19734.rs +++ b/src/test/compile-fail/issue-19734.rs @@ -11,5 +11,5 @@ fn main() {} impl Type { - undef!() //~ ERROR macro undefined: 'undef!' + undef!(); //~ ERROR macro undefined: 'undef!' } diff --git a/src/test/compile-fail/issue-6596.rs b/src/test/compile-fail/issue-6596.rs index 267b30677a1..3222b2cd537 100644 --- a/src/test/compile-fail/issue-6596.rs +++ b/src/test/compile-fail/issue-6596.rs @@ -16,7 +16,7 @@ macro_rules! e( ($inp:ident) => ( $nonexistent ); -) +); fn main() { e!(foo); diff --git a/src/test/compile-fail/liveness-return-last-stmt-semi.rs b/src/test/compile-fail/liveness-return-last-stmt-semi.rs index f2ea2ca96a5..e92faa6bdaf 100644 --- a/src/test/compile-fail/liveness-return-last-stmt-semi.rs +++ b/src/test/compile-fail/liveness-return-last-stmt-semi.rs @@ -12,7 +12,7 @@ #![feature(macro_rules)] -macro_rules! test ( () => { fn foo() -> int { 1i; } } ) +macro_rules! test ( () => { fn foo() -> int { 1i; } } ); //~^ ERROR not all control paths return a value //~^^ HELP consider removing this semicolon diff --git a/src/test/compile-fail/macro-incomplete-parse.rs b/src/test/compile-fail/macro-incomplete-parse.rs index 94386858d29..71b656d0bbb 100644 --- a/src/test/compile-fail/macro-incomplete-parse.rs +++ b/src/test/compile-fail/macro-incomplete-parse.rs @@ -26,10 +26,10 @@ macro_rules! ignored_pat { () => ( 1, 2 ) //~ ERROR macro expansion ignores token `,` } -ignored_item!() +ignored_item!(); fn main() { - ignored_expr!() + ignored_expr!(); match 1 { ignored_pat!() => (), _ => (), diff --git a/src/test/compile-fail/macro-inner-attributes.rs b/src/test/compile-fail/macro-inner-attributes.rs index 4c4fb5572d6..f64b7be50e3 100644 --- a/src/test/compile-fail/macro-inner-attributes.rs +++ b/src/test/compile-fail/macro-inner-attributes.rs @@ -12,15 +12,15 @@ macro_rules! test ( ($nm:ident, #[$a:meta], - $i:item) => (mod $nm { #![$a] $i }); ) + $i:item) => (mod $nm { #![$a] $i }); ); test!(a, #[cfg(qux)], - pub fn bar() { }) + pub fn bar() { }); test!(b, #[cfg(not(qux))], - pub fn bar() { }) + pub fn bar() { }); #[qux] fn main() { diff --git a/src/test/compile-fail/macro-invocation-dot-help.rs b/src/test/compile-fail/macro-invocation-dot-help.rs deleted file mode 100644 index bd45b76dd5a..00000000000 --- a/src/test/compile-fail/macro-invocation-dot-help.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2014 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. - -fn main() { - foo!() //~ HELP try parenthesizing this macro invocation - .bar //~ ERROR expected statement -} diff --git a/src/test/compile-fail/macro-local-data-key-priv.rs b/src/test/compile-fail/macro-local-data-key-priv.rs index 3f2ecd86abe..3818c8f7754 100644 --- a/src/test/compile-fail/macro-local-data-key-priv.rs +++ b/src/test/compile-fail/macro-local-data-key-priv.rs @@ -11,7 +11,7 @@ // check that the local data keys are private by default. mod bar { - thread_local!(static baz: f64 = 0.0) + thread_local!(static baz: f64 = 0.0); } fn main() { diff --git a/src/test/compile-fail/macro-match-nonterminal.rs b/src/test/compile-fail/macro-match-nonterminal.rs index d6d32d94a29..150187aa07d 100644 --- a/src/test/compile-fail/macro-match-nonterminal.rs +++ b/src/test/compile-fail/macro-match-nonterminal.rs @@ -10,7 +10,7 @@ #![feature(macro_rules)] -macro_rules! test ( ($a, $b) => (()); ) //~ ERROR Cannot transcribe +macro_rules! test ( ($a, $b) => (()); ); //~ ERROR Cannot transcribe fn main() { test!() diff --git a/src/test/compile-fail/macro-outer-attributes.rs b/src/test/compile-fail/macro-outer-attributes.rs index e41f1bd369a..6d59c203d14 100644 --- a/src/test/compile-fail/macro-outer-attributes.rs +++ b/src/test/compile-fail/macro-outer-attributes.rs @@ -12,15 +12,15 @@ macro_rules! test ( ($nm:ident, #[$a:meta], - $i:item) => (mod $nm { #[$a] $i }); ) + $i:item) => (mod $nm { #[$a] $i }); ); test!(a, #[cfg(qux)], - pub fn bar() { }) + pub fn bar() { }); test!(b, #[cfg(not(qux))], - pub fn bar() { }) + pub fn bar() { }); // test1!(#[bar]) #[qux] diff --git a/src/test/compile-fail/macros-no-semicolon-items.rs b/src/test/compile-fail/macros-no-semicolon-items.rs new file mode 100644 index 00000000000..f1f31a99e97 --- /dev/null +++ b/src/test/compile-fail/macros-no-semicolon-items.rs @@ -0,0 +1,15 @@ +// Copyright 2014 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. + +macro_rules! foo() //~ ERROR semicolon + +fn main() { +} + diff --git a/src/test/compile-fail/macros-no-semicolon.rs b/src/test/compile-fail/macros-no-semicolon.rs new file mode 100644 index 00000000000..fd5f5866f09 --- /dev/null +++ b/src/test/compile-fail/macros-no-semicolon.rs @@ -0,0 +1,16 @@ +// Copyright 2014 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. + +fn main() { + assert!(1 == 2) + assert!(3 == 4) //~ ERROR expected one of `.`, `;`, or `}`, found `assert` + println!("hello"); +} + diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index dc41e2e02a8..747b4815ac2 100644 --- a/src/test/compile-fail/method-macro-backtrace.rs +++ b/src/test/compile-fail/method-macro-backtrace.rs @@ -14,20 +14,20 @@ macro_rules! make_method ( ($name:ident) => ( fn $name(&self) { } -)) +)); struct S; impl S { // We had a bug where these wouldn't clean up macro backtrace frames. - make_method!(foo1) - make_method!(foo2) - make_method!(foo3) - make_method!(foo4) - make_method!(foo5) - make_method!(foo6) - make_method!(foo7) - make_method!(foo8) + make_method!(foo1); + make_method!(foo2); + make_method!(foo3); + make_method!(foo4); + make_method!(foo5); + make_method!(foo6); + make_method!(foo7); + make_method!(foo8); // Cause an error. It shouldn't have any macro backtrace frames. fn bar(&self) { } diff --git a/src/test/compile-fail/pattern-macro-hygeine.rs b/src/test/compile-fail/pattern-macro-hygeine.rs deleted file mode 100644 index 0b6a14c0fc9..00000000000 --- a/src/test/compile-fail/pattern-macro-hygeine.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 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. - -#![feature(macro_rules)] - -macro_rules! foo ( () => ( x ) ) - -fn main() { - let foo!() = 2; - x + 1; //~ ERROR unresolved name `x` -} diff --git a/src/test/compile-fail/pattern-macro-hygiene.rs b/src/test/compile-fail/pattern-macro-hygiene.rs new file mode 100644 index 00000000000..3322fecf950 --- /dev/null +++ b/src/test/compile-fail/pattern-macro-hygiene.rs @@ -0,0 +1,18 @@ +// Copyright 2014 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. + +#![feature(macro_rules)] + +macro_rules! foo ( () => ( x ) ); + +fn main() { + let foo!() = 2; + x + 1; //~ ERROR unresolved name `x` +} diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs index 1da7f47677a..de0d5c90fdd 100644 --- a/src/test/compile-fail/recursion_limit.rs +++ b/src/test/compile-fail/recursion_limit.rs @@ -22,19 +22,19 @@ macro_rules! link { } } -link!(A,B) -link!(B,C) -link!(C,D) -link!(D,E) -link!(E,F) -link!(F,G) -link!(G,H) -link!(H,I) -link!(I,J) -link!(J,K) -link!(K,L) -link!(L,M) -link!(M,N) +link! { A, B } +link! { B, C } +link! { C, D } +link! { D, E } +link! { E, F } +link! { F, G } +link! { G, H } +link! { H, I } +link! { I, J } +link! { J, K } +link! { K, L } +link! { L, M } +link! { M, N } enum N { N(uint) } diff --git a/src/test/debuginfo/lexical-scope-with-macro.rs b/src/test/debuginfo/lexical-scope-with-macro.rs index 5a59ed5b2f3..2c76f2ca7df 100644 --- a/src/test/debuginfo/lexical-scope-with-macro.rs +++ b/src/test/debuginfo/lexical-scope-with-macro.rs @@ -113,23 +113,23 @@ #![feature(macro_rules)] -macro_rules! trivial( +macro_rules! trivial { ($e1:expr) => ($e1) -) +} -macro_rules! no_new_scope( +macro_rules! no_new_scope { ($e1:expr) => (($e1 + 2) - 1) -) +} -macro_rules! new_scope( +macro_rules! new_scope { () => ({ let a = 890242i; zzz(); // #break sentinel(); }) -) +} -macro_rules! shadow_within_macro( +macro_rules! shadow_within_macro { ($e1:expr) => ({ let a = $e1 + 2; @@ -141,12 +141,12 @@ macro_rules! shadow_within_macro( zzz(); // #break sentinel(); }) -) +} -macro_rules! dup_expr( +macro_rules! dup_expr { ($e1:expr) => (($e1) + ($e1)) -) +} fn main() { diff --git a/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs b/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs index c5cfabd74e1..08c9f8b4aa7 100644 --- a/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs +++ b/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs @@ -15,7 +15,7 @@ #[phase(plugin)] extern crate issue_16723_multiple_items_syntax_ext; -multiple_items!() +multiple_items!(); impl Struct1 { fn foo() {} diff --git a/src/test/run-pass/cleanup-rvalue-scopes.rs b/src/test/run-pass/cleanup-rvalue-scopes.rs index 35c69705925..42f6914e081 100644 --- a/src/test/run-pass/cleanup-rvalue-scopes.rs +++ b/src/test/run-pass/cleanup-rvalue-scopes.rs @@ -74,7 +74,7 @@ macro_rules! end_of_block( check_flags(1); } ) -) +); macro_rules! end_of_stmt( ($pat:pat, $expr:expr) => ( @@ -91,7 +91,7 @@ macro_rules! end_of_stmt( check_flags(0); } ) -) +); pub fn main() { diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs index f4dba3f6c7f..cac805189b8 100644 --- a/src/test/run-pass/const-binops.rs +++ b/src/test/run-pass/const-binops.rs @@ -17,7 +17,7 @@ macro_rules! assert_approx_eq( assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); }) -) +); static A: int = -4 + 3; static A2: uint = 3 + 3; diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 4e625ce1d1f..a0fa2d178b9 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -26,7 +26,7 @@ use std::str; macro_rules! succeed( ($e:expr) => ( match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) } -) ) +) ); fn test_destroy_once() { let mut p = sleeper(); diff --git a/src/test/run-pass/deriving-in-macro.rs b/src/test/run-pass/deriving-in-macro.rs index 218216e3a34..52b5c040d86 100644 --- a/src/test/run-pass/deriving-in-macro.rs +++ b/src/test/run-pass/deriving-in-macro.rs @@ -17,8 +17,8 @@ macro_rules! define_vec ( pub struct bar; } ) -) +); -define_vec!() +define_vec!(); pub fn main() {} diff --git a/src/test/run-pass/exponential-notation.rs b/src/test/run-pass/exponential-notation.rs index 318305b7ec3..f63ab7fb7c9 100644 --- a/src/test/run-pass/exponential-notation.rs +++ b/src/test/run-pass/exponential-notation.rs @@ -13,22 +13,22 @@ use std::num::strconv as s; use std::num::strconv::float_to_str_common as to_string; -macro_rules! t(($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()) } }) +macro_rules! t(($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()); } }); pub fn main() { // Basic usage t!(to_string(1.2345678e-5f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpDec, false), - "1.234568e-5") + "1.234568e-5"); // Hexadecimal output t!(to_string(7.281738281250e+01f64, 16u, true, s::SignAll, s::DigMax(6), s::ExpBin, false), - "+1.2345p+6") + "+1.2345p+6"); t!(to_string(-1.777768135071e-02f64, 16u, true, s::SignAll, s::DigMax(6), s::ExpBin, false), - "-1.2345p-6") + "-1.2345p-6"); // Some denormals t!(to_string(4.9406564584124654e-324f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpBin, false), - "1p-1074") + "1p-1074"); t!(to_string(2.2250738585072009e-308f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpBin, false), - "1p-1022") + "1p-1022"); } diff --git a/src/test/run-pass/html-literals.rs b/src/test/run-pass/html-literals.rs index 18e35e72c02..0d56f28e8fa 100644 --- a/src/test/run-pass/html-literals.rs +++ b/src/test/run-pass/html-literals.rs @@ -31,7 +31,7 @@ macro_rules! html ( ( $($body:tt)* ) => ( parse_node!( []; []; $($body)* ) ) -) +); macro_rules! parse_node ( ( @@ -85,7 +85,7 @@ macro_rules! parse_node ( ); ( []; [:$e:expr]; ) => ( $e ); -) +); pub fn main() { let _page = html! ( diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index b78371c51e4..9eac9c30dc8 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -38,7 +38,7 @@ impl fmt::Show for C { } } -macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a.as_slice(), $b) }) +macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a.as_slice(), $b) }); pub fn main() { // Various edge cases without formats diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index c3ba7ca12d0..9f2fe155cdf 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -18,7 +18,7 @@ macro_rules! assert_approx_eq( assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); }) -) +); mod rusti { extern "rust-intrinsic" { diff --git a/src/test/run-pass/issue-15189.rs b/src/test/run-pass/issue-15189.rs index 16212b5f529..01c96b7563a 100644 --- a/src/test/run-pass/issue-15189.rs +++ b/src/test/run-pass/issue-15189.rs @@ -12,7 +12,7 @@ #![feature(macro_rules)] -macro_rules! third(($e:expr)=>({let x = 2; $e[x]})) +macro_rules! third(($e:expr)=>({let x = 2; $e[x]})); fn main() { let x = vec!(10u,11u,12u,13u); diff --git a/src/test/run-pass/issue-15221.rs b/src/test/run-pass/issue-15221.rs index 378fd4a222e..a11b34e4762 100644 --- a/src/test/run-pass/issue-15221.rs +++ b/src/test/run-pass/issue-15221.rs @@ -11,10 +11,10 @@ #![feature(macro_rules)] macro_rules! inner ( - ($e:pat ) => ($e)) + ($e:pat ) => ($e)); macro_rules! outer ( - ($e:pat ) => (inner!($e))) + ($e:pat ) => (inner!($e))); fn main() { let outer!(g1) = 13i; diff --git a/src/test/run-pass/issue-5060.rs b/src/test/run-pass/issue-5060.rs index adf1d1e614a..0cd25bc2c71 100644 --- a/src/test/run-pass/issue-5060.rs +++ b/src/test/run-pass/issue-5060.rs @@ -21,7 +21,7 @@ macro_rules! print_hd_tl ( // FIXME: #9970 print!("{}", "]\n"); }) -) +); pub fn main() { print_hd_tl!(x, y, z, w) diff --git a/src/test/run-pass/issue-7911.rs b/src/test/run-pass/issue-7911.rs index d8bb61477a0..c69b66f4dbd 100644 --- a/src/test/run-pass/issue-7911.rs +++ b/src/test/run-pass/issue-7911.rs @@ -37,9 +37,9 @@ macro_rules! generate_test(($type_:path, $slf:ident, $field:expr) => ( &mut $field as &mut FooBar } } -)) +)); -generate_test!(Foo, self, self.bar) +generate_test!(Foo, self, self.bar); pub fn main() { let mut foo: Foo = Foo { bar: Bar(42) }; diff --git a/src/test/run-pass/issue-8709.rs b/src/test/run-pass/issue-8709.rs index 9f2aaa4d005..d4ea05004a0 100644 --- a/src/test/run-pass/issue-8709.rs +++ b/src/test/run-pass/issue-8709.rs @@ -12,13 +12,13 @@ macro_rules! sty( ($t:ty) => (stringify!($t)) -) +); macro_rules! spath( ($t:path) => (stringify!($t)) -) +); fn main() { - assert_eq!(sty!(int), "int") - assert_eq!(spath!(std::option), "std::option") + assert_eq!(sty!(int), "int"); + assert_eq!(spath!(std::option), "std::option"); } diff --git a/src/test/run-pass/issue-8851.rs b/src/test/run-pass/issue-8851.rs index bf84721c984..5826a5f9919 100644 --- a/src/test/run-pass/issue-8851.rs +++ b/src/test/run-pass/issue-8851.rs @@ -29,9 +29,9 @@ macro_rules! test( } } ) -) +); -test!(y, 10 + (y as int)) +test!(y, 10 + (y as int)); pub fn main() { foo(T::A(20)); diff --git a/src/test/run-pass/issue-9110.rs b/src/test/run-pass/issue-9110.rs index ff086355f9d..60011281d42 100644 --- a/src/test/run-pass/issue-9110.rs +++ b/src/test/run-pass/issue-9110.rs @@ -17,8 +17,8 @@ macro_rules! silly_macro( pub fn bar(_foo : Foo) {} } ); -) +); -silly_macro!() +silly_macro!(); pub fn main() {} diff --git a/src/test/run-pass/issue-9129.rs b/src/test/run-pass/issue-9129.rs index b61263d1754..a6746f45206 100644 --- a/src/test/run-pass/issue-9129.rs +++ b/src/test/run-pass/issue-9129.rs @@ -20,7 +20,7 @@ impl bomb for S { fn boom(&self, _: Ident) { } } pub struct Ident { name: uint } // macro_rules! int3( () => ( unsafe { asm!( "int3" ); } ) ) -macro_rules! int3( () => ( { } ) ) +macro_rules! int3( () => ( { } ) ); fn Ident_new() -> Ident { int3!(); diff --git a/src/test/run-pass/let-var-hygiene.rs b/src/test/run-pass/let-var-hygiene.rs index 7b9fa3bcf7f..5eed791e058 100644 --- a/src/test/run-pass/let-var-hygiene.rs +++ b/src/test/run-pass/let-var-hygiene.rs @@ -11,7 +11,7 @@ #![feature(macro_rules)] // shouldn't affect evaluation of $ex: -macro_rules! bad_macro (($ex:expr) => ({let _x = 9i; $ex})) +macro_rules! bad_macro (($ex:expr) => ({let _x = 9i; $ex})); pub fn main() { let _x = 8i; assert_eq!(bad_macro!(_x),8i) diff --git a/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs b/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs index afcd154f647..95a5f1003b6 100644 --- a/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs +++ b/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs @@ -14,8 +14,8 @@ // macros can occur. // items -trace_macros!(false) -log_syntax!() +trace_macros!(false); +log_syntax!(); fn main() { diff --git a/src/test/run-pass/macro-2.rs b/src/test/run-pass/macro-2.rs index 0daa405fc6b..7b4d376993a 100644 --- a/src/test/run-pass/macro-2.rs +++ b/src/test/run-pass/macro-2.rs @@ -19,7 +19,7 @@ pub fn main() { fn f($x: int) -> int { return $body; }; f }) - ) + ); - assert!(mylambda_tt!(y, y * 2)(8) == 16) + assert!(mylambda_tt!(y, y * 2)(8) == 16); } diff --git a/src/test/run-pass/macro-attribute-expansion.rs b/src/test/run-pass/macro-attribute-expansion.rs index 6cf5dc8dec4..3c170634c22 100644 --- a/src/test/run-pass/macro-attribute-expansion.rs +++ b/src/test/run-pass/macro-attribute-expansion.rs @@ -22,8 +22,8 @@ macro_rules! descriptions { } // item -descriptions!(DOG is "an animal") -descriptions!(RUST is "a language") +descriptions! { DOG is "an animal" } +descriptions! { RUST is "a language" } pub fn main() { } diff --git a/src/test/run-pass/macro-attributes.rs b/src/test/run-pass/macro-attributes.rs index e09ca68f6d1..4df3b94c1c9 100644 --- a/src/test/run-pass/macro-attributes.rs +++ b/src/test/run-pass/macro-attributes.rs @@ -27,7 +27,7 @@ macro_rules! compiles_fine { } // item -compiles_fine!(#[foo]) +compiles_fine!(#[foo]); pub fn main() { // statement diff --git a/src/test/run-pass/macro-delimiter-significance.rs b/src/test/run-pass/macro-delimiter-significance.rs new file mode 100644 index 00000000000..fcf2dff66a5 --- /dev/null +++ b/src/test/run-pass/macro-delimiter-significance.rs @@ -0,0 +1,14 @@ +// Copyright 2014 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. + +fn main() { + vec![1u, 2, 3].len(); +} + diff --git a/src/test/run-pass/macro-include-items.rs b/src/test/run-pass/macro-include-items.rs index 0e7e6e247f5..5c95f67257c 100644 --- a/src/test/run-pass/macro-include-items.rs +++ b/src/test/run-pass/macro-include-items.rs @@ -12,7 +12,7 @@ fn bar() {} -include!(concat!("", "", "../auxiliary/", "macro-include-items-item.rs")) +include!(concat!("", "", "../auxiliary/", "macro-include-items-item.rs")); fn main() { foo(); diff --git a/src/test/run-pass/macro-interpolation.rs b/src/test/run-pass/macro-interpolation.rs index 672efa68398..45712f5c62a 100644 --- a/src/test/run-pass/macro-interpolation.rs +++ b/src/test/run-pass/macro-interpolation.rs @@ -22,7 +22,8 @@ macro_rules! overly_complicated ( } }) -) +); + pub fn main() { assert!(overly_complicated!(f, x, Option, { return Some(x); }, Some(8u), Some(y), y) == 8u) diff --git a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs index 847024d42ba..4c124d85eee 100644 --- a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs +++ b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs @@ -12,7 +12,8 @@ macro_rules! four ( () => (4) -) +); + fn main() { let _x: [u16, ..four!()]; } diff --git a/src/test/run-pass/macro-meta-items.rs b/src/test/run-pass/macro-meta-items.rs index 91f67abd8af..4b01fdf8162 100644 --- a/src/test/run-pass/macro-meta-items.rs +++ b/src/test/run-pass/macro-meta-items.rs @@ -27,8 +27,8 @@ macro_rules! emit { } // item -compiles_fine!(bar) -emit!(foo) +compiles_fine!(bar); +emit!(foo); fn foo() { println!("{}", MISTYPED); diff --git a/src/test/run-pass/macro-method-issue-4621.rs b/src/test/run-pass/macro-method-issue-4621.rs index b5400edb41f..aa6de9acf6b 100644 --- a/src/test/run-pass/macro-method-issue-4621.rs +++ b/src/test/run-pass/macro-method-issue-4621.rs @@ -13,7 +13,7 @@ struct A; macro_rules! make_thirteen_method {() => (fn thirteen(&self)->int {13})} -impl A { make_thirteen_method!() } +impl A { make_thirteen_method!(); } fn main() { assert_eq!(A.thirteen(),13); diff --git a/src/test/run-pass/macro-multiple-items.rs b/src/test/run-pass/macro-multiple-items.rs index d56d211b606..4fb130f0e13 100644 --- a/src/test/run-pass/macro-multiple-items.rs +++ b/src/test/run-pass/macro-multiple-items.rs @@ -20,9 +20,9 @@ macro_rules! make_foo( fn bar(&self) {} } ) -) +); -make_foo!() +make_foo!(); pub fn main() { Foo.bar() diff --git a/src/test/run-pass/macro-nt-list.rs b/src/test/run-pass/macro-nt-list.rs index 2a00e5b8616..9367a231d4f 100644 --- a/src/test/run-pass/macro-nt-list.rs +++ b/src/test/run-pass/macro-nt-list.rs @@ -14,11 +14,11 @@ macro_rules! list ( ( ($($id:ident),*) ) => (()); ( [$($id:ident),*] ) => (()); ( {$($id:ident),*} ) => (()); -) +); macro_rules! tt_list ( ( ($($tt:tt),*) ) => (()); -) +); pub fn main() { list!( () ); diff --git a/src/test/run-pass/macro-of-higher-order.rs b/src/test/run-pass/macro-of-higher-order.rs index 561933d7599..c47b5e11089 100644 --- a/src/test/run-pass/macro-of-higher-order.rs +++ b/src/test/run-pass/macro-of-higher-order.rs @@ -12,10 +12,10 @@ macro_rules! higher_order ( (subst $lhs:tt => $rhs:tt) => ({ - macro_rules! anon ( $lhs => $rhs ) + macro_rules! anon ( $lhs => $rhs ); anon!(1u, 2u, "foo") }); -) +); fn main() { let val = higher_order!(subst ($x:expr, $y:expr, $foo:expr) => (($x + $y, $foo))); diff --git a/src/test/run-pass/macro-pat.rs b/src/test/run-pass/macro-pat.rs index 3e89466bc0f..496cef9d644 100644 --- a/src/test/run-pass/macro-pat.rs +++ b/src/test/run-pass/macro-pat.rs @@ -14,31 +14,31 @@ macro_rules! mypat( () => ( Some('y') ) -) +); macro_rules! char_x( () => ( 'x' ) -) +); macro_rules! some( ($x:pat) => ( Some($x) ) -) +); macro_rules! indirect( () => ( some!(char_x!()) ) -) +); macro_rules! ident_pat( ($x:ident) => ( $x ) -) +); fn f(c: Option) -> uint { match c { diff --git a/src/test/run-pass/macro-stmt.rs b/src/test/run-pass/macro-stmt.rs index 49e146cb0cf..7be49e1acd8 100644 --- a/src/test/run-pass/macro-stmt.rs +++ b/src/test/run-pass/macro-stmt.rs @@ -16,9 +16,9 @@ macro_rules! myfn( ( $f:ident, ( $( $x:ident ),* ), $body:block ) => ( fn $f( $( $x : int),* ) -> int $body ) -) +); -myfn!(add, (a,b), { return a+b; } ) +myfn!(add, (a,b), { return a+b; } ); pub fn main() { @@ -37,7 +37,7 @@ pub fn main() { macro_rules! actually_an_expr_macro ( () => ( 16i ) - ) + ); assert_eq!({ actually_an_expr_macro!() }, 16i); diff --git a/src/test/run-pass/macro-with-attrs1.rs b/src/test/run-pass/macro-with-attrs1.rs index aaa2be66ff4..631fc866671 100644 --- a/src/test/run-pass/macro-with-attrs1.rs +++ b/src/test/run-pass/macro-with-attrs1.rs @@ -13,10 +13,10 @@ #![feature(macro_rules)] #[cfg(foo)] -macro_rules! foo( () => (1i) ) +macro_rules! foo( () => (1i) ); #[cfg(not(foo))] -macro_rules! foo( () => (2i) ) +macro_rules! foo( () => (2i) ); pub fn main() { assert_eq!(foo!(), 1i); diff --git a/src/test/run-pass/macro-with-attrs2.rs b/src/test/run-pass/macro-with-attrs2.rs index 4a191b2fa66..3ac0d47e61a 100644 --- a/src/test/run-pass/macro-with-attrs2.rs +++ b/src/test/run-pass/macro-with-attrs2.rs @@ -11,10 +11,10 @@ #![feature(macro_rules)] #[cfg(foo)] -macro_rules! foo( () => (1i) ) +macro_rules! foo( () => (1i) ); #[cfg(not(foo))] -macro_rules! foo( () => (2i) ) +macro_rules! foo( () => (2i) ); pub fn main() { assert_eq!(foo!(), 2i); diff --git a/src/test/run-pass/macro-with-braces-in-expr-position.rs b/src/test/run-pass/macro-with-braces-in-expr-position.rs index 8b59f26d869..024dc4c03e1 100644 --- a/src/test/run-pass/macro-with-braces-in-expr-position.rs +++ b/src/test/run-pass/macro-with-braces-in-expr-position.rs @@ -10,7 +10,7 @@ #![feature(macro_rules)] -macro_rules! expr (($e: expr) => { $e }) +macro_rules! expr (($e: expr) => { $e }); macro_rules! spawn { ($($code: tt)*) => { diff --git a/src/test/run-pass/match-in-macro.rs b/src/test/run-pass/match-in-macro.rs index 2f8e184033a..a776999ec8a 100644 --- a/src/test/run-pass/match-in-macro.rs +++ b/src/test/run-pass/match-in-macro.rs @@ -20,7 +20,7 @@ macro_rules! match_inside_expansion( Foo::B { b1:b2 , bb1:bb2 } => b2+bb2 } ) -) +); pub fn main() { assert_eq!(match_inside_expansion!(),129); diff --git a/src/test/run-pass/non-built-in-quote.rs b/src/test/run-pass/non-built-in-quote.rs index c6dd3736857..9151564b340 100644 --- a/src/test/run-pass/non-built-in-quote.rs +++ b/src/test/run-pass/non-built-in-quote.rs @@ -10,7 +10,7 @@ #![feature(macro_rules)] -macro_rules! quote_tokens ( () => (()) ) +macro_rules! quote_tokens ( () => (()) ); pub fn main() { quote_tokens!(); diff --git a/src/test/run-pass/overloaded-index-assoc-list.rs b/src/test/run-pass/overloaded-index-assoc-list.rs index 7c6ad45a9ef..c0359a34186 100644 --- a/src/test/run-pass/overloaded-index-assoc-list.rs +++ b/src/test/run-pass/overloaded-index-assoc-list.rs @@ -47,9 +47,9 @@ pub fn main() { list.push(foo.clone(), 22i); list.push(bar.clone(), 44i); - assert!(list[foo] == 22) - assert!(list[bar] == 44) + assert!(list[foo] == 22); + assert!(list[bar] == 44); - assert!(list[foo] == 22) - assert!(list[bar] == 44) + assert!(list[foo] == 22); + assert!(list[bar] == 44); } diff --git a/src/test/run-pass/slice-2.rs b/src/test/run-pass/slice-2.rs index 768c28cb8de..f03b4609637 100644 --- a/src/test/run-pass/slice-2.rs +++ b/src/test/run-pass/slice-2.rs @@ -15,57 +15,57 @@ fn main() { let x: &[int] = &[1, 2, 3, 4, 5]; let cmp: &[int] = &[1, 2, 3, 4, 5]; - assert!(x[] == cmp) + assert!(x[] == cmp); let cmp: &[int] = &[3, 4, 5]; - assert!(x[2..] == cmp) + assert!(x[2..] == cmp); let cmp: &[int] = &[1, 2, 3]; - assert!(x[..3] == cmp) + assert!(x[..3] == cmp); let cmp: &[int] = &[2, 3, 4]; - assert!(x[1..4] == cmp) + assert!(x[1..4] == cmp); let x: Vec = vec![1, 2, 3, 4, 5]; let cmp: &[int] = &[1, 2, 3, 4, 5]; - assert!(x[] == cmp) + assert!(x[] == cmp); let cmp: &[int] = &[3, 4, 5]; - assert!(x[2..] == cmp) + assert!(x[2..] == cmp); let cmp: &[int] = &[1, 2, 3]; - assert!(x[..3] == cmp) + assert!(x[..3] == cmp); let cmp: &[int] = &[2, 3, 4]; - assert!(x[1..4] == cmp) + assert!(x[1..4] == cmp); let x: &mut [int] = &mut [1, 2, 3, 4, 5]; { let cmp: &mut [int] = &mut [1, 2, 3, 4, 5]; - assert!(x[mut] == cmp) + assert!(x[mut] == cmp); } { let cmp: &mut [int] = &mut [3, 4, 5]; - assert!(x[mut 2..] == cmp) + assert!(x[mut 2..] == cmp); } { let cmp: &mut [int] = &mut [1, 2, 3]; - assert!(x[mut ..3] == cmp) + assert!(x[mut ..3] == cmp); } { let cmp: &mut [int] = &mut [2, 3, 4]; - assert!(x[mut 1..4] == cmp) + assert!(x[mut 1..4] == cmp); } let mut x: Vec = vec![1, 2, 3, 4, 5]; { let cmp: &mut [int] = &mut [1, 2, 3, 4, 5]; - assert!(x[mut] == cmp) + assert!(x[mut] == cmp); } { let cmp: &mut [int] = &mut [3, 4, 5]; - assert!(x[mut 2..] == cmp) + assert!(x[mut 2..] == cmp); } { let cmp: &mut [int] = &mut [1, 2, 3]; - assert!(x[mut ..3] == cmp) + assert!(x[mut ..3] == cmp); } { let cmp: &mut [int] = &mut [2, 3, 4]; - assert!(x[mut 1..4] == cmp) + assert!(x[mut 1..4] == cmp); } } diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs index 2761d0cbcce..104a47e1afe 100644 --- a/src/test/run-pass/syntax-extension-source-utils.rs +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -21,7 +21,7 @@ pub mod m1 { } } -macro_rules! indirect_line( () => ( line!() ) ) +macro_rules! indirect_line( () => ( line!() ) ); pub fn main() { assert_eq!(line!(), 27); diff --git a/src/test/run-pass/typeck-macro-interaction-issue-8852.rs b/src/test/run-pass/typeck-macro-interaction-issue-8852.rs index 1b08955adfc..4dec227d520 100644 --- a/src/test/run-pass/typeck-macro-interaction-issue-8852.rs +++ b/src/test/run-pass/typeck-macro-interaction-issue-8852.rs @@ -30,9 +30,9 @@ macro_rules! test( } } ) -) +); -test!(x,y,x + y) +test!(x,y,x + y); pub fn main() { foo(T::A(1), T::A(2)); diff --git a/src/test/run-pass/vec-macro-with-brackets.rs b/src/test/run-pass/vec-macro-with-brackets.rs index d06e3dc0633..2c784dade57 100644 --- a/src/test/run-pass/vec-macro-with-brackets.rs +++ b/src/test/run-pass/vec-macro-with-brackets.rs @@ -16,7 +16,7 @@ macro_rules! vec [ $(_temp.push($e);)* _temp }) -] +]; pub fn main() { let my_vec = vec![1i, 2, 3, 4, 5]; -- cgit 1.4.1-3-g733a5 From 86f8c127dd806940fe201b510b9284750fb17271 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 14 Dec 2014 23:32:24 -0500 Subject: libsyntax: use `#[deriving(Copy)]` --- src/libsyntax/abi.rs | 19 ++---- src/libsyntax/ast.rs | 120 +++++++++------------------------- src/libsyntax/ast_map/blocks.rs | 6 +- src/libsyntax/ast_map/mod.rs | 12 +--- src/libsyntax/ast_util.rs | 4 +- src/libsyntax/attr.rs | 16 ++--- src/libsyntax/codemap.rs | 27 ++------ src/libsyntax/diagnostic.rs | 18 ++--- src/libsyntax/ext/base.rs | 3 +- src/libsyntax/ext/deriving/cmp/ord.rs | 3 +- src/libsyntax/ext/mtwt.rs | 4 +- src/libsyntax/feature_gate.rs | 3 +- src/libsyntax/parse/lexer/comments.rs | 4 +- src/libsyntax/parse/obsolete.rs | 4 +- src/libsyntax/parse/parser.rs | 4 +- src/libsyntax/parse/token.rs | 19 ++---- src/libsyntax/print/pp.rs | 18 ++--- src/libsyntax/print/pprust.rs | 6 +- src/libsyntax/visit.rs | 3 +- 19 files changed, 77 insertions(+), 216 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 71d29bca401..70bad90aea1 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -15,7 +15,7 @@ pub use self::AbiArchitecture::*; use std::fmt; -#[deriving(PartialEq)] +#[deriving(Copy, PartialEq)] pub enum Os { OsWindows, OsMacos, @@ -26,9 +26,7 @@ pub enum Os { OsDragonfly, } -impl Copy for Os {} - -#[deriving(PartialEq, Eq, Hash, Encodable, Decodable, Clone)] +#[deriving(Copy, PartialEq, Eq, Hash, Encodable, Decodable, Clone)] pub enum Abi { // NB: This ordering MUST match the AbiDatas array below. // (This is ensured by the test indices_are_correct().) @@ -48,10 +46,8 @@ pub enum Abi { RustCall, } -impl Copy for Abi {} - #[allow(non_camel_case_types)] -#[deriving(PartialEq)] +#[deriving(Copy, PartialEq)] pub enum Architecture { X86, X86_64, @@ -60,8 +56,7 @@ pub enum Architecture { Mipsel } -impl Copy for Architecture {} - +#[deriving(Copy)] pub struct AbiData { abi: Abi, @@ -69,8 +64,7 @@ pub struct AbiData { name: &'static str, } -impl Copy for AbiData {} - +#[deriving(Copy)] pub enum AbiArchitecture { /// Not a real ABI (e.g., intrinsic) RustArch, @@ -80,9 +74,6 @@ pub enum AbiArchitecture { Archs(u32) } -#[allow(non_upper_case_globals)] -impl Copy for AbiArchitecture {} - #[allow(non_upper_case_globals)] static AbiDatas: &'static [AbiData] = &[ // Platform-specific ABIs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d4860766d47..be8f32bc4d5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -80,14 +80,12 @@ use serialize::{Encodable, Decodable, Encoder, Decoder}; /// table) and a SyntaxContext to track renaming and /// macro expansion per Flatt et al., "Macros /// That Work Together" -#[deriving(Clone, Hash, PartialOrd, Eq, Ord)] +#[deriving(Clone, Copy, Hash, PartialOrd, Eq, Ord)] pub struct Ident { pub name: Name, pub ctxt: SyntaxContext } -impl Copy for Ident {} - impl Ident { /// Construct an identifier with the given name and an empty context: pub fn new(name: Name) -> Ident { Ident {name: name, ctxt: EMPTY_CTXT}} @@ -160,11 +158,9 @@ pub const ILLEGAL_CTXT : SyntaxContext = 1; /// A name is a part of an identifier, representing a string or gensym. It's /// the result of interning. -#[deriving(Eq, Ord, PartialEq, PartialOrd, Hash, Encodable, Decodable, Clone)] +#[deriving(Copy, Eq, Ord, PartialEq, PartialOrd, Hash, Encodable, Decodable, Clone)] pub struct Name(pub u32); -impl Copy for Name {} - impl Name { pub fn as_str<'a>(&'a self) -> &'a str { unsafe { @@ -201,15 +197,13 @@ impl, E> Decodable for Ident { /// Function name (not all functions have names) pub type FnIdent = Option; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Lifetime { pub id: NodeId, pub span: Span, pub name: Name } -impl Copy for Lifetime {} - #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct LifetimeDef { pub lifetime: Lifetime, @@ -353,14 +347,12 @@ pub type CrateNum = u32; pub type NodeId = u32; -#[deriving(Clone, Eq, Ord, PartialOrd, PartialEq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, Encodable, Decodable, Hash, Show)] pub struct DefId { pub krate: CrateNum, pub node: NodeId, } -impl Copy for DefId {} - /// Item definitions in the currently-compiled crate would have the CrateNum /// LOCAL_CRATE in their DefId. pub const LOCAL_CRATE: CrateNum = 0; @@ -513,15 +505,13 @@ pub struct FieldPat { pub is_shorthand: bool, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum BindingMode { BindByRef(Mutability), BindByValue(Mutability), } -impl Copy for BindingMode {} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum PatWildKind { /// Represents the wildcard pattern `_` PatWildSingle, @@ -530,8 +520,6 @@ pub enum PatWildKind { PatWildMulti, } -impl Copy for PatWildKind {} - #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Pat_ { /// Represents a wildcard pattern (either `_` or `..`) @@ -561,15 +549,13 @@ pub enum Pat_ { PatMac(Mac), } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Mutability { MutMutable, MutImmutable, } -impl Copy for Mutability {} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum BinOp { BiAdd, BiSub, @@ -591,9 +577,7 @@ pub enum BinOp { BiGt, } -impl Copy for BinOp {} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum UnOp { UnUniq, UnDeref, @@ -601,8 +585,6 @@ pub enum UnOp { UnNeg } -impl Copy for UnOp {} - pub type Stmt = Spanned; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] @@ -634,14 +616,12 @@ pub enum MacStmtStyle { /// Where a local declaration came from: either a true `let ... = /// ...;`, or one desugared from the pattern of a for loop. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum LocalSource { LocalLet, LocalFor, } -impl Copy for LocalSource {} - // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. /// Local represents a `let` statement, e.g., `let : = ;` @@ -683,22 +663,18 @@ pub struct Field { pub type SpannedIdent = Spanned; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum BlockCheckMode { DefaultBlock, UnsafeBlock(UnsafeSource), } -impl Copy for BlockCheckMode {} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum UnsafeSource { CompilerGenerated, UserProvided, } -impl Copy for UnsafeSource {} - #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Expr { pub id: NodeId, @@ -775,23 +751,19 @@ pub struct QPath { pub item_name: Ident, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum MatchSource { MatchNormal, MatchIfLetDesugar, MatchWhileLetDesugar, } -impl Copy for MatchSource {} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum CaptureClause { CaptureByValue, CaptureByRef, } -impl Copy for CaptureClause {} - /// A delimited sequence of token trees #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Delimited { @@ -842,14 +814,12 @@ pub struct SequenceRepetition { /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) /// for token sequences. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum KleeneOp { ZeroOrMore, OneOrMore, } -impl Copy for KleeneOp {} - /// When the main rust parser encounters a syntax-extension invocation, it /// parses the arguments to the invocation as a token-tree. This is a very /// loose structure, such that all sorts of different AST-fragments can @@ -959,24 +929,20 @@ pub enum Mac_ { MacInvocTT(Path, Vec , SyntaxContext), // new macro-invocation } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum StrStyle { CookedStr, RawStr(uint) } -impl Copy for StrStyle {} - pub type Lit = Spanned; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Sign { Minus, Plus } -impl Copy for Sign {} - impl Sign where T: Int { pub fn new(n: T) -> Sign { if n < Int::zero() { @@ -987,15 +953,13 @@ impl Sign where T: Int { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum LitIntType { SignedIntLit(IntTy, Sign), UnsignedIntLit(UintTy), UnsuffixedIntLit(Sign) } -impl Copy for LitIntType {} - impl LitIntType { pub fn suffix_len(&self) -> uint { match *self { @@ -1082,7 +1046,7 @@ pub struct Typedef { pub typ: P, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum IntTy { TyI, TyI8, @@ -1091,8 +1055,6 @@ pub enum IntTy { TyI64, } -impl Copy for IntTy {} - impl fmt::Show for IntTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::int_ty_to_string(*self, None)) @@ -1109,7 +1071,7 @@ impl IntTy { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum UintTy { TyU, TyU8, @@ -1118,8 +1080,6 @@ pub enum UintTy { TyU64, } -impl Copy for UintTy {} - impl UintTy { pub fn suffix_len(&self) -> uint { match *self { @@ -1136,14 +1096,12 @@ impl fmt::Show for UintTy { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum FloatTy { TyF32, TyF64, } -impl Copy for FloatTy {} - impl fmt::Show for FloatTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", ast_util::float_ty_to_string(*self)) @@ -1177,7 +1135,7 @@ pub struct Ty { } /// Not represented directly in the AST, referred to by name through a ty_path. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum PrimTy { TyInt(IntTy), TyUint(UintTy), @@ -1187,16 +1145,12 @@ pub enum PrimTy { TyChar } -impl Copy for PrimTy {} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash)] pub enum Onceness { Once, Many } -impl Copy for Onceness {} - impl fmt::Show for Onceness { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -1259,14 +1213,12 @@ pub enum Ty_ { TyInfer, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum AsmDialect { AsmAtt, AsmIntel } -impl Copy for AsmDialect {} - #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct InlineAsm { pub asm: InternedString, @@ -1433,14 +1385,12 @@ pub struct Variant_ { pub type Variant = Spanned; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum PathListItem_ { PathListIdent { name: Ident, id: NodeId }, PathListMod { id: NodeId } } -impl Copy for PathListItem_ {} - impl PathListItem_ { pub fn id(&self) -> NodeId { match *self { @@ -1494,19 +1444,15 @@ pub type Attribute = Spanned; /// Distinguishes between Attributes that decorate items and Attributes that /// are contained as statements within items. These two cases need to be /// distinguished for pretty-printing. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum AttrStyle { AttrOuter, AttrInner, } -impl Copy for AttrStyle {} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct AttrId(pub uint); -impl Copy for AttrId {} - /// Doc-comments are promoted to attributes that have is_sugared_doc = true #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Attribute_ { @@ -1536,14 +1482,12 @@ pub struct PolyTraitRef { pub trait_ref: TraitRef } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Visibility { Public, Inherited, } -impl Copy for Visibility {} - impl Visibility { pub fn inherit_from(&self, parent_visibility: Visibility) -> Visibility { match self { @@ -1572,15 +1516,13 @@ impl StructField_ { pub type StructField = Spanned; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum StructFieldKind { NamedField(Ident, Visibility), /// Element of a tuple-like struct UnnamedField(Visibility), } -impl Copy for StructFieldKind {} - impl StructFieldKind { pub fn is_unnamed(&self) -> bool { match *self { @@ -1682,15 +1624,13 @@ impl ForeignItem_ { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum UnboxedClosureKind { FnUnboxedClosureKind, FnMutUnboxedClosureKind, FnOnceUnboxedClosureKind, } -impl Copy for UnboxedClosureKind {} - /// The data we save and restore about an inlined item or method. This is not /// part of the AST that we parse from a file, but it becomes part of the tree /// that we trans. diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 6decfd1c3ad..7c89245f53e 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -41,10 +41,9 @@ use visit; /// - The default implementation for a trait method. /// /// To construct one, use the `Code::from_node` function. +#[deriving(Copy)] pub struct FnLikeNode<'a> { node: ast_map::Node<'a> } -impl<'a> Copy for FnLikeNode<'a> {} - /// MaybeFnLike wraps a method that indicates if an object /// corresponds to some FnLikeNode. pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } @@ -82,13 +81,12 @@ impl MaybeFnLike for ast::Expr { /// Carries either an FnLikeNode or a Block, as these are the two /// constructs that correspond to "code" (as in, something from which /// we can construct a control-flow graph). +#[deriving(Copy)] pub enum Code<'a> { FnLikeCode(FnLikeNode<'a>), BlockCode(&'a Block), } -impl<'a> Copy for Code<'a> {} - impl<'a> Code<'a> { pub fn id(&self) -> ast::NodeId { match *self { diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 6089f39e828..a95c9e19906 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -32,14 +32,12 @@ use std::slice; pub mod blocks; -#[deriving(Clone, PartialEq)] +#[deriving(Clone, Copy, PartialEq)] pub enum PathElem { PathMod(Name), PathName(Name) } -impl Copy for PathElem {} - impl PathElem { pub fn name(&self) -> Name { match *self { @@ -102,7 +100,7 @@ pub fn path_to_string>(path: PI) -> String { }).to_string() } -#[deriving(Show)] +#[deriving(Copy, Show)] pub enum Node<'ast> { NodeItem(&'ast Item), NodeForeignItem(&'ast ForeignItem), @@ -122,11 +120,9 @@ pub enum Node<'ast> { NodeLifetime(&'ast Lifetime), } -impl<'ast> Copy for Node<'ast> {} - /// Represents an entry and its parent Node ID /// The odd layout is to bring down the total size. -#[deriving(Show)] +#[deriving(Copy, Show)] enum MapEntry<'ast> { /// Placeholder for holes in the map. NotPresent, @@ -151,8 +147,6 @@ enum MapEntry<'ast> { RootInlinedParent(&'ast InlinedParent) } -impl<'ast> Copy for MapEntry<'ast> {} - impl<'ast> Clone for MapEntry<'ast> { fn clone(&self) -> MapEntry<'ast> { *self diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 5243f07f327..02771809ae6 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -343,14 +343,12 @@ pub fn empty_generics() -> Generics { // ______________________________________________________________________ // Enumerating the IDs which appear in an AST -#[deriving(Encodable, Decodable, Show)] +#[deriving(Copy, Encodable, Decodable, Show)] pub struct IdRange { pub min: NodeId, pub max: NodeId, } -impl Copy for IdRange {} - impl IdRange { pub fn max() -> IdRange { IdRange { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 598da6a5df0..127cc5ed51d 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -277,7 +277,7 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option { first_attr_value_str_by_name(attrs, "crate_name") } -#[deriving(PartialEq)] +#[deriving(Copy, PartialEq)] pub enum InlineAttr { InlineNone, InlineHint, @@ -285,8 +285,6 @@ pub enum InlineAttr { InlineNever, } -impl Copy for InlineAttr {} - /// Determine what `#[inline]` attribute is present in `attrs`, if any. pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { // FIXME (#2809)---validate the usage of #[inline] and #[inline] @@ -349,7 +347,7 @@ pub struct Stability { } /// The available stability levels. -#[deriving(Encodable,Decodable,PartialEq,PartialOrd,Clone,Show)] +#[deriving(Copy,Encodable,Decodable,PartialEq,PartialOrd,Clone,Show)] pub enum StabilityLevel { Deprecated, Experimental, @@ -359,8 +357,6 @@ pub enum StabilityLevel { Locked } -impl Copy for StabilityLevel {} - pub fn find_stability_generic<'a, AM: AttrMetaMethods, I: Iterator<&'a AM>> @@ -468,7 +464,7 @@ fn int_type_of_word(s: &str) -> Option { } } -#[deriving(PartialEq, Show, Encodable, Decodable)] +#[deriving(Copy, PartialEq, Show, Encodable, Decodable)] pub enum ReprAttr { ReprAny, ReprInt(Span, IntType), @@ -476,8 +472,6 @@ pub enum ReprAttr { ReprPacked, } -impl Copy for ReprAttr {} - impl ReprAttr { pub fn is_ffi_safe(&self) -> bool { match *self { @@ -489,14 +483,12 @@ impl ReprAttr { } } -#[deriving(Eq, Hash, PartialEq, Show, Encodable, Decodable)] +#[deriving(Copy, Eq, Hash, PartialEq, Show, Encodable, Decodable)] pub enum IntType { SignedInt(ast::IntTy), UnsignedInt(ast::UintTy) } -impl Copy for IntType {} - impl IntType { #[inline] pub fn is_signed(self) -> bool { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 17cafc2441f..b7c0678cf13 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -31,19 +31,15 @@ pub trait Pos { /// A byte offset. Keep this small (currently 32-bits), as AST contains /// a lot of them. -#[deriving(Clone, PartialEq, Eq, Hash, PartialOrd, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Show)] pub struct BytePos(pub u32); -impl Copy for BytePos {} - /// A character offset. Because of multibyte utf8 characters, a byte offset /// is not equivalent to a character offset. The CodeMap will convert BytePos /// values to CharPos values as necessary. -#[deriving(PartialEq, Hash, PartialOrd, Show)] +#[deriving(Copy, PartialEq, Hash, PartialOrd, Show)] pub struct CharPos(pub uint); -impl Copy for CharPos {} - // FIXME: Lots of boilerplate in these impls, but so far my attempts to fix // have been unsuccessful @@ -121,7 +117,7 @@ impl Sub for CharPos { /// are *absolute* positions from the beginning of the codemap, not positions /// relative to FileMaps. Methods on the CodeMap can be used to relate spans back /// to the original source. -#[deriving(Clone, Show, Hash)] +#[deriving(Clone, Copy, Show, Hash)] pub struct Span { pub lo: BytePos, pub hi: BytePos, @@ -130,18 +126,14 @@ pub struct Span { pub expn_id: ExpnId } -impl Copy for Span {} - pub const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: NO_EXPANSION }; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Spanned { pub node: T, pub span: Span, } -impl Copy for Spanned {} - impl PartialEq for Span { fn eq(&self, other: &Span) -> bool { return (*self).lo == (*other).lo && (*self).hi == (*other).hi; @@ -219,7 +211,7 @@ pub struct FileMapAndLine { pub fm: Rc, pub line: uint } pub struct FileMapAndBytePos { pub fm: Rc, pub pos: BytePos } /// The syntax with which a macro was invoked. -#[deriving(Clone, Hash, Show)] +#[deriving(Clone, Copy, Hash, Show)] pub enum MacroFormat { /// e.g. #[deriving(...)] MacroAttribute, @@ -227,8 +219,6 @@ pub enum MacroFormat { MacroBang } -impl Copy for MacroFormat {} - #[deriving(Clone, Hash, Show)] pub struct NameAndSpan { /// The name of the macro that was invoked to create the thing @@ -264,11 +254,9 @@ pub struct ExpnInfo { pub callee: NameAndSpan } -#[deriving(PartialEq, Eq, Clone, Show, Hash, Encodable, Decodable)] +#[deriving(Copy, PartialEq, Eq, Clone, Show, Hash, Encodable, Decodable)] pub struct ExpnId(u32); -impl Copy for ExpnId {} - pub const NO_EXPANSION: ExpnId = ExpnId(-1); impl ExpnId { @@ -290,6 +278,7 @@ pub struct FileLines { } /// Identifies an offset of a multi-byte character in a FileMap +#[deriving(Copy)] pub struct MultiByteChar { /// The absolute offset of the character in the CodeMap pub pos: BytePos, @@ -297,8 +286,6 @@ pub struct MultiByteChar { pub bytes: uint, } -impl Copy for MultiByteChar {} - /// A single source in the CodeMap pub struct FileMap { /// The name of the file that the source came from, source that doesn't diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 3a816987922..4d765f49aca 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -28,7 +28,7 @@ use term; /// maximum number of lines we will print for each error; arbitrary. static MAX_LINES: uint = 6u; -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub enum RenderSpan { /// A FullSpan renders with both with an initial line for the /// message, prefixed by file:linenum, followed by a summary of @@ -40,8 +40,6 @@ pub enum RenderSpan { FileLine(Span), } -impl Copy for RenderSpan {} - impl RenderSpan { fn span(self) -> Span { match self { @@ -56,15 +54,13 @@ impl RenderSpan { } } -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub enum ColorConfig { Auto, Always, Never } -impl Copy for ColorConfig {} - pub trait Emitter { fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, Span)>, msg: &str, code: Option<&str>, lvl: Level); @@ -75,16 +71,14 @@ pub trait Emitter { /// This structure is used to signify that a task has panicked with a fatal error /// from the diagnostics. You can use this with the `Any` trait to figure out /// how a rustc task died (if so desired). +#[deriving(Copy)] pub struct FatalError; -impl Copy for FatalError {} - /// Signifies that the compiler died with an explicit call to `.bug` /// or `.span_bug` rather than a failed assertion, etc. +#[deriving(Copy)] pub struct ExplicitBug; -impl Copy for ExplicitBug {} - /// A span-handler is like a handler but also /// accepts span information for source-location /// reporting. @@ -228,7 +222,7 @@ pub fn mk_handler(e: Box) -> Handler { } } -#[deriving(PartialEq, Clone)] +#[deriving(Copy, PartialEq, Clone)] pub enum Level { Bug, Fatal, @@ -238,8 +232,6 @@ pub enum Level { Help, } -impl Copy for Level {} - impl fmt::Show for Level { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::fmt::Show; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 354b53bfc01..3947a602809 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -223,13 +223,12 @@ impl MacResult for MacItems { /// Fill-in macro expansion result, to allow compilation to continue /// after hitting errors. +#[deriving(Copy)] pub struct DummyResult { expr_only: bool, span: Span } -impl Copy for DummyResult {} - impl DummyResult { /// Create a default MacResult that can be anything. /// diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index bd1962de56e..10e14e0c975 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -83,12 +83,11 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, trait_def.expand(cx, mitem, item, push) } +#[deriving(Copy)] pub enum OrderingOp { PartialCmpOp, LtOp, LeOp, GtOp, GeOp, } -impl Copy for OrderingOp {} - pub fn some_ordering_collapsed(cx: &mut ExtCtxt, span: Span, op: OrderingOp, diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index 33936e6213f..ae979020bc7 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -39,7 +39,7 @@ pub struct SCTable { rename_memo: RefCell>, } -#[deriving(PartialEq, Encodable, Decodable, Hash, Show)] +#[deriving(Copy, PartialEq, Encodable, Decodable, Hash, Show)] pub enum SyntaxContext_ { EmptyCtxt, Mark (Mrk,SyntaxContext), @@ -56,8 +56,6 @@ pub enum SyntaxContext_ { IllegalCtxt } -impl Copy for SyntaxContext_ {} - /// A list of ident->name renamings pub type RenameList = Vec<(Ident, Name)>; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9656629e14d..0e0a87c74f8 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -97,6 +97,7 @@ enum Status { } /// A set of features to be used by later passes. +#[deriving(Copy)] pub struct Features { pub default_type_params: bool, pub unboxed_closures: bool, @@ -107,8 +108,6 @@ pub struct Features { pub opt_out_copy: bool, } -impl Copy for Features {} - impl Features { pub fn new() -> Features { Features { diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index a17d66476c0..95bae63f58f 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -24,7 +24,7 @@ use std::str; use std::string::String; use std::uint; -#[deriving(Clone, PartialEq)] +#[deriving(Clone, Copy, PartialEq)] pub enum CommentStyle { /// No code on either side of each line of the comment Isolated, @@ -36,8 +36,6 @@ pub enum CommentStyle { BlankLine, } -impl Copy for CommentStyle {} - #[deriving(Clone)] pub struct Comment { pub style: CommentStyle, diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 3a7cc77515d..a6ddcbf9ac4 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -22,7 +22,7 @@ use parse::token; use ptr::P; /// The specific types of unsupported syntax -#[deriving(PartialEq, Eq, Hash)] +#[deriving(Copy, PartialEq, Eq, Hash)] pub enum ObsoleteSyntax { ObsoleteOwnedType, ObsoleteOwnedExpr, @@ -36,8 +36,6 @@ pub enum ObsoleteSyntax { ObsoleteProcExpr, } -impl Copy for ObsoleteSyntax {} - pub trait ParserObsoleteMethods { /// Reports an obsolete syntax non-fatal error. fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c234c172fd8..3ad224b93ce 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -104,7 +104,7 @@ type ItemInfo = (Ident, Item_, Option >); /// How to parse a path. There are four different kinds of paths, all of which /// are parsed somewhat differently. -#[deriving(PartialEq)] +#[deriving(Copy, PartialEq)] pub enum PathParsingMode { /// A path with no type parameters; e.g. `foo::bar::Baz` NoTypesAllowed, @@ -116,8 +116,6 @@ pub enum PathParsingMode { LifetimeAndTypesWithColons, } -impl Copy for PathParsingMode {} - enum ItemOrViewItem { /// Indicates a failure to parse any kind of item. The attributes are /// returned. diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 641239f1f8b..dad369792d7 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -28,7 +28,7 @@ use std::path::BytesContainer; use std::rc::Rc; #[allow(non_camel_case_types)] -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, Copy, Encodable, Decodable, PartialEq, Eq, Hash, Show)] pub enum BinOpToken { Plus, Minus, @@ -42,10 +42,8 @@ pub enum BinOpToken { Shr, } -impl Copy for BinOpToken {} - /// A delimeter token -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, Copy, Encodable, Decodable, PartialEq, Eq, Hash, Show)] pub enum DelimToken { /// A round parenthesis: `(` or `)` Paren, @@ -55,16 +53,14 @@ pub enum DelimToken { Brace, } -impl Copy for DelimToken {} - -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, Copy, Encodable, Decodable, PartialEq, Eq, Hash, Show)] pub enum IdentStyle { /// `::` follows the identifier with no whitespace in-between. ModName, Plain, } -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, Copy, Encodable, Decodable, PartialEq, Eq, Hash, Show)] pub enum Lit { Byte(ast::Name), Char(ast::Name), @@ -89,10 +85,6 @@ impl Lit { } } -impl Copy for Lit {} - -impl Copy for IdentStyle {} - #[allow(non_camel_case_types)] #[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] pub enum Token { @@ -438,13 +430,12 @@ macro_rules! declare_special_idents_and_keywords {( pub use self::Keyword::*; use ast; + #[deriving(Copy)] pub enum Keyword { $( $sk_variant, )* $( $rk_variant, )* } - impl Copy for Keyword {} - impl Keyword { pub fn to_name(&self) -> ast::Name { match *self { diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index c4e040a0f7c..bfa47a46e74 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -66,30 +66,24 @@ pub use self::Token::*; use std::io; use std::string; -#[deriving(Clone, PartialEq)] +#[deriving(Clone, Copy, PartialEq)] pub enum Breaks { Consistent, Inconsistent, } -impl Copy for Breaks {} - -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub struct BreakToken { offset: int, blank_space: int } -impl Copy for BreakToken {} - -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub struct BeginToken { offset: int, breaks: Breaks } -impl Copy for BeginToken {} - #[deriving(Clone)] pub enum Token { String(string::String, int), @@ -153,20 +147,18 @@ pub fn buf_str(toks: Vec, return s.into_string(); } +#[deriving(Copy)] pub enum PrintStackBreak { Fits, Broken(Breaks), } -impl Copy for PrintStackBreak {} - +#[deriving(Copy)] pub struct PrintStackElem { offset: int, pbreak: PrintStackBreak } -impl Copy for PrintStackElem {} - static SIZE_INFINITY: int = 0xffff; pub fn mk_printer(out: Box, linewidth: uint) -> Printer { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 1dd61a5ce19..d2cc0cba317 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -45,19 +45,17 @@ pub trait PpAnn { fn post(&self, _state: &mut State, _node: AnnNode) -> IoResult<()> { Ok(()) } } +#[deriving(Copy)] pub struct NoAnn; -impl Copy for NoAnn {} - impl PpAnn for NoAnn {} +#[deriving(Copy)] pub struct CurrentCommentAndLiteral { cur_cmnt: uint, cur_lit: uint, } -impl Copy for CurrentCommentAndLiteral {} - pub struct State<'a> { pub s: pp::Printer, cm: Option<&'a CodeMap>, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 5a1a186c74c..b89e9a59349 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -32,6 +32,7 @@ use codemap::Span; use ptr::P; use owned_slice::OwnedSlice; +#[deriving(Copy)] pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() FkItemFn(Ident, &'a Generics, Unsafety, Abi), @@ -44,8 +45,6 @@ pub enum FnKind<'a> { FkFnBlock, } -impl<'a> Copy for FnKind<'a> {} - /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; -- cgit 1.4.1-3-g733a5 From 314ed2df096858e7c174254b0babd5f949ae6d27 Mon Sep 17 00:00:00 2001 From: Barosl Lee Date: Sat, 20 Dec 2014 07:58:02 +0900 Subject: Drop the Match prefix from the MatchSource variants --- src/librustc/lint/builtin.rs | 6 +++--- src/librustc/middle/check_match.rs | 6 +++--- src/librustc/util/ppaux.rs | 5 +++-- src/librustc_typeck/check/_match.rs | 3 ++- src/libsyntax/ast.rs | 7 +++---- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/ext/expand.rs | 12 ++++++++---- src/libsyntax/parse/parser.rs | 4 ++-- 8 files changed, 25 insertions(+), 20 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 88b12aa5660..f5c7ac16478 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1157,9 +1157,9 @@ impl LintPass for UnusedParens { ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), ast::ExprMatch(ref head, _, source) => match source { - ast::MatchNormal => (head, "`match` head expression", true), - ast::MatchIfLetDesugar => (head, "`if let` head expression", true), - ast::MatchWhileLetDesugar => (head, "`while let` head expression", true), + ast::MatchSource::Normal => (head, "`match` head expression", true), + ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true), + ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true), }, ast::ExprRet(Some(ref value)) => (value, "`return` value", false), ast::ExprAssign(_, ref value) => (value, "assigned value", false), diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 79e776c3308..ca338f5d02a 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -307,7 +307,7 @@ fn check_arms(cx: &MatchCheckCtxt, match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) { NotUseful => { match source { - ast::MatchIfLetDesugar => { + ast::MatchSource::IfLetDesugar { .. } => { if printed_if_let_err { // we already printed an irrefutable if-let pattern error. // We don't want two, that's just confusing. @@ -321,7 +321,7 @@ fn check_arms(cx: &MatchCheckCtxt, } }, - ast::MatchWhileLetDesugar => { + ast::MatchSource::WhileLetDesugar => { // find the first arm pattern so we can use its span let &(ref first_arm_pats, _) = &arms[0]; let first_pat = &first_arm_pats[0]; @@ -329,7 +329,7 @@ fn check_arms(cx: &MatchCheckCtxt, span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern"); }, - ast::MatchNormal => { + ast::MatchSource::Normal => { span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern") }, } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index b0124977c9f..71146918d99 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -93,8 +93,9 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region) ast::ExprMethodCall(..) => { explain_span(cx, "method call", expr.span) }, - ast::ExprMatch(_, _, ast::MatchIfLetDesugar) => explain_span(cx, "if let", expr.span), - ast::ExprMatch(_, _, ast::MatchWhileLetDesugar) => { + ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => + explain_span(cx, "if let", expr.span), + ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => { explain_span(cx, "while let", expr.span) }, ast::ExprMatch(..) => explain_span(cx, "match", expr.span), diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index d4b89621ace..3b48808b362 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -293,7 +293,8 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } else { let (origin, expected, found) = match match_src { /* if-let construct without an else block */ - ast::MatchIfLetDesugar(contains_else_arm) if !contains_else_arm => ( + ast::MatchSource::IfLetDesugar { contains_else_clause } + if !contains_else_clause => ( infer::IfExpressionWithNoElse(expr.span), bty, result_ty, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ab338da63bf..cb0254a7ec5 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -32,7 +32,6 @@ pub use self::LitIntType::*; pub use self::LocalSource::*; pub use self::Mac_::*; pub use self::MacStmtStyle::*; -pub use self::MatchSource::*; pub use self::MetaItem_::*; pub use self::Method_::*; pub use self::Mutability::*; @@ -753,9 +752,9 @@ pub struct QPath { #[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum MatchSource { - MatchNormal, - MatchIfLetDesugar(bool /* contains_else_arm */), - MatchWhileLetDesugar, + Normal, + IfLetDesugar { contains_else_clause: bool }, + WhileLetDesugar, } #[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)] diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index d35091f8ab0..9d4992f7453 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -868,7 +868,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_match(&self, span: Span, arg: P, arms: Vec) -> P { - self.expr(span, ast::ExprMatch(arg, arms, ast::MatchNormal)) + self.expr(span, ast::ExprMatch(arg, arms, ast::MatchSource::Normal)) } fn expr_if(&self, span: Span, cond: P, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 63bd38de8a0..bf19eecbf65 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -97,7 +97,7 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { // `match { ... }` let arms = vec![pat_arm, break_arm]; let match_expr = fld.cx.expr(span, - ast::ExprMatch(expr, arms, ast::MatchWhileLetDesugar)); + ast::ExprMatch(expr, arms, ast::MatchSource::WhileLetDesugar)); // `[opt_ident]: loop { ... }` let loop_block = fld.cx.block_expr(match_expr); @@ -158,6 +158,8 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { arms }; + let contains_else_clause = elseopt.is_some(); + // `_ => [ | ()]` let else_arm = { let pat_under = fld.cx.pat_wild(span); @@ -170,9 +172,11 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { arms.extend(else_if_arms.into_iter()); arms.push(else_arm); - let match_expr = fld.cx.expr(span, ast::ExprMatch(expr, - arms, - ast::MatchIfLetDesugar(elseopt.is_some()))); + let match_expr = fld.cx.expr(span, + ast::ExprMatch(expr, arms, + ast::MatchSource::IfLetDesugar { + contains_else_clause: contains_else_clause, + })); fld.fold_expr(match_expr) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3ad224b93ce..b6efbecc78a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -41,7 +41,7 @@ use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitStr, LitInt, Local, LocalLet}; use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces}; -use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchNormal}; +use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource}; use ast::{Method, MutTy, BiMul, Mutability}; use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; @@ -3114,7 +3114,7 @@ impl<'a> Parser<'a> { } let hi = self.span.hi; self.bump(); - return self.mk_expr(lo, hi, ExprMatch(discriminant, arms, MatchNormal)); + return self.mk_expr(lo, hi, ExprMatch(discriminant, arms, MatchSource::Normal)); } pub fn parse_arm(&mut self) -> Arm { -- cgit 1.4.1-3-g733a5 From 2e86929a4a5a36f3993e577b4582ba70d84bbb40 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 20 Dec 2014 15:20:51 +1300 Subject: Allow use of `[_ ; n]` syntax for fixed length and repeating arrays. This does NOT break any existing programs because the `[_, ..n]` syntax is also supported. --- src/librustc/util/ppaux.rs | 2 +- src/librustc_trans/trans/debuginfo.rs | 4 +-- src/libsyntax/parse/parser.rs | 11 ++++++- src/libsyntax/print/pprust.rs | 5 ++-- src/test/auxiliary/nested_item.rs | 2 +- src/test/bench/noise.rs | 12 ++++---- src/test/bench/shootout-fannkuch-redux.rs | 14 ++++----- src/test/bench/shootout-fasta-redux.rs | 12 ++++---- src/test/bench/shootout-fasta.rs | 2 +- src/test/bench/shootout-k-nucleotide.rs | 4 +-- src/test/bench/shootout-nbody.rs | 8 ++--- src/test/bench/shootout-reverse-complement.rs | 8 ++--- src/test/bench/sudoku.rs | 6 ++-- src/test/compile-fail/better-expected.rs | 2 +- .../borrowck-for-loop-correct-cmt-for-pattern.rs | 2 +- src/test/compile-fail/coercion-slice.rs | 4 +-- src/test/compile-fail/const-cast-wrong-type.rs | 2 +- src/test/compile-fail/dst-bad-coerce1.rs | 4 +-- src/test/compile-fail/dst-bad-coerce2.rs | 2 +- src/test/compile-fail/dst-bad-coerce3.rs | 2 +- src/test/compile-fail/dst-bad-coerce4.rs | 4 +-- src/test/compile-fail/dst-bad-deep.rs | 2 +- src/test/compile-fail/huge-array-simple.rs | 2 +- src/test/compile-fail/huge-array.rs | 8 ++--- src/test/compile-fail/huge-enum.rs | 4 +-- src/test/compile-fail/issue-13446.rs | 2 +- src/test/compile-fail/issue-13482-2.rs | 2 +- src/test/compile-fail/issue-13482.rs | 2 +- src/test/compile-fail/issue-14845.rs | 6 ++-- src/test/compile-fail/issue-17252.rs | 4 +-- src/test/compile-fail/issue-17441.rs | 4 +-- .../compile-fail/issue-17718-borrow-interior.rs | 2 +- src/test/compile-fail/issue-19244-1.rs | 2 +- src/test/compile-fail/issue-19244-2.rs | 2 +- src/test/compile-fail/issue-2149.rs | 2 +- src/test/compile-fail/issue-4517.rs | 4 +-- src/test/compile-fail/lint-uppercase-variables.rs | 2 +- src/test/compile-fail/move-fragments-9.rs | 16 +++++----- src/test/compile-fail/moves-based-on-type-exprs.rs | 2 +- .../non-constant-enum-for-vec-repeat.rs | 2 +- .../non-constant-expr-for-fixed-len-vec.rs | 2 +- .../non-constant-expr-for-vec-repeat.rs | 2 +- .../compile-fail/non-exhaustive-pattern-witness.rs | 2 +- .../packed-struct-generic-transmute.rs | 2 +- src/test/compile-fail/removed-syntax-fixed-vec.rs | 2 +- .../compile-fail/removed-syntax-mut-vec-expr.rs | 2 +- src/test/compile-fail/removed-syntax-mut-vec-ty.rs | 2 +- src/test/compile-fail/repeat-to-run-dtor-twice.rs | 2 +- src/test/compile-fail/repeat_count.rs | 14 ++++----- .../compile-fail/static-vec-repeat-not-constant.rs | 2 +- .../compile-fail/trailing-comma-array-repeat.rs | 13 -------- src/test/compile-fail/transmute-type-parameters.rs | 2 +- src/test/compile-fail/vector-cast-weirdness.rs | 10 +++---- src/test/debuginfo/evec-in-struct.rs | 18 +++++------ .../lexical-scopes-in-block-expression.rs | 4 +-- src/test/debuginfo/recursive-struct.rs | 2 +- src/test/debuginfo/type-names.rs | 4 +-- src/test/debuginfo/vec.rs | 2 +- src/test/pretty/blank-lines.rs | 2 +- src/test/pretty/issue-4264.pp | 35 +++++++++++----------- src/test/run-make/no-stack-check/attr.rs | 2 +- src/test/run-make/no-stack-check/flag.rs | 2 +- src/test/run-make/target-specs/foo.rs | 2 +- src/test/run-pass/cast-in-array-size.rs | 8 ++--- src/test/run-pass/check-static-slice.rs | 6 ++-- src/test/run-pass/const-autoderef.rs | 4 +-- src/test/run-pass/const-enum-vec-index.rs | 2 +- src/test/run-pass/const-enum-vector.rs | 2 +- .../run-pass/const-expr-in-fixed-length-vec.rs | 2 +- src/test/run-pass/const-expr-in-vec-repeat.rs | 2 +- src/test/run-pass/const-fields-and-indexing.rs | 2 +- src/test/run-pass/const-region-ptrs-noncopy.rs | 2 +- src/test/run-pass/const-str-ptr.rs | 4 +-- src/test/run-pass/const-vecs-and-slices.rs | 4 +-- src/test/run-pass/dst-struct.rs | 2 +- src/test/run-pass/enum-vec-initializer.rs | 8 ++--- src/test/run-pass/evec-internal.rs | 10 +++---- src/test/run-pass/huge-largest-array.rs | 4 +-- src/test/run-pass/issue-11205.rs | 24 +++++++-------- src/test/run-pass/issue-13259-windows-tcb-trash.rs | 2 +- src/test/run-pass/issue-13763.rs | 4 +-- src/test/run-pass/issue-13837.rs | 2 +- src/test/run-pass/issue-14940.rs | 2 +- src/test/run-pass/issue-15673.rs | 2 +- src/test/run-pass/issue-17302.rs | 2 +- src/test/run-pass/issue-17877.rs | 4 +-- src/test/run-pass/issue-18425.rs | 2 +- src/test/run-pass/issue-19244.rs | 4 +-- src/test/run-pass/issue-2904.rs | 2 +- src/test/run-pass/issue-3656.rs | 2 +- src/test/run-pass/issue-4387.rs | 2 +- src/test/run-pass/issue-5688.rs | 2 +- src/test/run-pass/issue-7784.rs | 4 +-- src/test/run-pass/issue-9942.rs | 2 +- ...ro-invocation-in-count-expr-fixed-array-type.rs | 2 +- src/test/run-pass/match-arm-statics.rs | 2 +- .../method-mut-self-modifies-mut-slice-lvalue.rs | 2 +- ...od-two-traits-distinguished-via-where-clause.rs | 2 +- ...mutability-inherits-through-fixed-length-vec.rs | 4 +-- src/test/run-pass/new-style-fixed-length-vec.rs | 2 +- .../run-pass/nullable-pointer-iotareduction.rs | 4 +-- src/test/run-pass/nullable-pointer-size.rs | 2 +- src/test/run-pass/order-drop-with-match.rs | 2 +- .../run-pass/out-of-stack-new-thread-no-split.rs | 2 +- src/test/run-pass/out-of-stack-no-split.rs | 2 +- src/test/run-pass/out-of-stack.rs | 2 +- src/test/run-pass/packed-struct-generic-layout.rs | 4 +-- src/test/run-pass/packed-struct-layout.rs | 6 ++-- src/test/run-pass/packed-struct-size.rs | 2 +- src/test/run-pass/packed-struct-vec.rs | 4 +-- src/test/run-pass/packed-tuple-struct-layout.rs | 6 ++-- src/test/run-pass/packed-tuple-struct-size.rs | 2 +- src/test/run-pass/regions-dependent-addr-of.rs | 2 +- src/test/run-pass/repeat-expr-in-static.rs | 4 +-- src/test/run-pass/repeated-vector-syntax.rs | 4 +-- src/test/run-pass/uninit-empty-types.rs | 2 +- src/test/run-pass/unsized3.rs | 4 +-- src/test/run-pass/variadic-ffi.rs | 2 +- src/test/run-pass/vec-dst.rs | 10 +++---- src/test/run-pass/vec-fixed-length.rs | 6 ++-- src/test/run-pass/vec-repeat-with-cast.rs | 2 +- src/test/run-pass/vector-sort-panic-safe.rs | 2 +- 122 files changed, 260 insertions(+), 266 deletions(-) delete mode 100644 src/test/compile-fail/trailing-comma-array-repeat.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index b0124977c9f..b65473bb767 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -452,7 +452,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { ty_vec(t, sz) => { let inner_str = ty_to_string(cx, t); match sz { - Some(n) => format!("[{}, ..{}]", inner_str, n), + Some(n) => format!("[{}; {}]", inner_str, n), None => format!("[{}]", inner_str), } } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 9a5e6830da1..cdb36602f15 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -334,7 +334,7 @@ impl<'tcx> TypeMap<'tcx> { // mut ptr (*mut) -> {*mut :pointee-uid:} // unique ptr (~) -> {~ :pointee-uid:} // @-ptr (@) -> {@ :pointee-uid:} - // sized vec ([T, ..x]) -> {[:size:] :element-uid:} + // sized vec ([T; x]) -> {[:size:] :element-uid:} // unsized vec ([T]) -> {[] :element-uid:} // trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> } // closure -> { :store-sigil: |(:param-uid:),* <,_...>| -> \ @@ -3752,7 +3752,7 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, match optional_length { Some(len) => { - output.push_str(format!(", ..{}", len).as_slice()); + output.push_str(format!("; {}", len).as_slice()); } None => { /* nothing to do */ } }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3ad224b93ce..620dfd643d2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1548,7 +1548,7 @@ impl<'a> Parser<'a> { self.expect(&token::OpenDelim(token::Bracket)); let t = self.parse_ty_sum(); - // Parse the `, ..e` in `[ int, ..e ]` + // Parse the `; e` in `[ int; e ]` // where `e` is a const expression let t = match self.maybe_parse_fixed_vstore() { None => TyVec(t), @@ -1716,6 +1716,9 @@ impl<'a> Parser<'a> { self.bump(); self.bump(); Some(self.parse_expr()) + } else if self.check(&token::Semi) { + self.bump(); + Some(self.parse_expr()) } else { None } @@ -2262,6 +2265,12 @@ impl<'a> Parser<'a> { let count = self.parse_expr(); self.expect(&token::CloseDelim(token::Bracket)); ex = ExprRepeat(first_expr, count); + } else if self.check(&token::Semi) { + // Repeating vector syntax: [ 0; 512 ] + self.bump(); + let count = self.parse_expr(); + self.expect(&token::CloseDelim(token::Bracket)); + ex = ExprRepeat(first_expr, count); } else if self.check(&token::Comma) { // Vector with two or more elements. self.bump(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d2cc0cba317..993fbed10a8 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -755,7 +755,7 @@ impl<'a> State<'a> { ast::TyFixedLengthVec(ref ty, ref v) => { try!(word(&mut self.s, "[")); try!(self.print_type(&**ty)); - try!(word(&mut self.s, ", ..")); + try!(word(&mut self.s, "; ")); try!(self.print_expr(&**v)); try!(word(&mut self.s, "]")); } @@ -1531,8 +1531,7 @@ impl<'a> State<'a> { try!(self.ibox(indent_unit)); try!(word(&mut self.s, "[")); try!(self.print_expr(&**element)); - try!(word(&mut self.s, ",")); - try!(word(&mut self.s, "..")); + try!(self.word_space(";")); try!(self.print_expr(&**count)); try!(word(&mut self.s, "]")); try!(self.end()); diff --git a/src/test/auxiliary/nested_item.rs b/src/test/auxiliary/nested_item.rs index 96bae656390..d97a2e3cda1 100644 --- a/src/test/auxiliary/nested_item.rs +++ b/src/test/auxiliary/nested_item.rs @@ -28,7 +28,7 @@ impl Foo { pub struct Parser; impl> Parser { fn in_doctype(&mut self) { - static DOCTYPEPattern: [char, ..6] = ['O', 'C', 'T', 'Y', 'P', 'E']; + static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E']; } } diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index 025f8467d20..75cf864ce49 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -37,20 +37,20 @@ fn gradient(orig: Vec2, grad: Vec2, p: Vec2) -> f32 { } struct Noise2DContext { - rgradients: [Vec2, ..256], - permutations: [i32, ..256], + rgradients: [Vec2; 256], + permutations: [i32; 256], } impl Noise2DContext { fn new() -> Noise2DContext { let mut rng = StdRng::new().unwrap(); - let mut rgradients = [Vec2 { x: 0.0, y: 0.0 }, ..256]; + let mut rgradients = [Vec2 { x: 0.0, y: 0.0 }; 256]; for x in rgradients.iter_mut() { *x = random_gradient(&mut rng); } - let mut permutations = [0i32, ..256]; + let mut permutations = [0i32; 256]; for (i, x) in permutations.iter_mut().enumerate() { *x = i as i32; } @@ -65,7 +65,7 @@ impl Noise2DContext { self.rgradients[(idx & 255) as uint] } - fn get_gradients(&self, x: f32, y: f32) -> ([Vec2, ..4], [Vec2, ..4]) { + fn get_gradients(&self, x: f32, y: f32) -> ([Vec2; 4], [Vec2; 4]) { let x0f = x.floor(); let y0f = y.floor(); let x1f = x0f + 1.0; @@ -102,7 +102,7 @@ impl Noise2DContext { fn main() { let symbols = [' ', '░', '▒', '▓', '█', '█']; - let mut pixels = [0f32, ..256*256]; + let mut pixels = [0f32; 256*256]; let n2d = Noise2DContext::new(); for _ in range(0u, 100) { diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index 4849421a3f0..723b2b722d7 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -64,14 +64,14 @@ fn next_permutation(perm: &mut [i32], count: &mut [i32]) { } struct P { - p: [i32, .. 16], + p: [i32; 16], } impl Copy for P {} struct Perm { - cnt: [i32, .. 16], - fact: [u32, .. 16], + cnt: [i32; 16], + fact: [u32; 16], n: u32, permcount: u32, perm: P, @@ -81,21 +81,21 @@ impl Copy for Perm {} impl Perm { fn new(n: u32) -> Perm { - let mut fact = [1, .. 16]; + let mut fact = [1; 16]; for i in range(1, n as uint + 1) { fact[i] = fact[i - 1] * i as u32; } Perm { - cnt: [0, .. 16], + cnt: [0; 16], fact: fact, n: n, permcount: 0, - perm: P { p: [0, .. 16 ] } + perm: P { p: [0; 16 ] } } } fn get(&mut self, mut idx: i32) -> P { - let mut pp = [0u8, .. 16]; + let mut pp = [0u8; 16]; self.permcount = idx as u32; for (i, place) in self.perm.p.iter_mut().enumerate() { *place = i as i32 + 1; diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index afffbe5bed4..eb18cfdaed3 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -64,7 +64,7 @@ const ALU: &'static str = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\ const NULL_AMINO_ACID: AminoAcid = AminoAcid { c: ' ' as u8, p: 0.0 }; -static IUB: [AminoAcid, ..15] = [ +static IUB: [AminoAcid;15] = [ AminoAcid { c: 'a' as u8, p: 0.27 }, AminoAcid { c: 'c' as u8, p: 0.12 }, AminoAcid { c: 'g' as u8, p: 0.12 }, @@ -82,7 +82,7 @@ static IUB: [AminoAcid, ..15] = [ AminoAcid { c: 'Y' as u8, p: 0.02 }, ]; -static HOMO_SAPIENS: [AminoAcid, ..4] = [ +static HOMO_SAPIENS: [AminoAcid;4] = [ AminoAcid { c: 'a' as u8, p: 0.3029549426680 }, AminoAcid { c: 'c' as u8, p: 0.1979883004921 }, AminoAcid { c: 'g' as u8, p: 0.1975473066391 }, @@ -148,8 +148,8 @@ impl<'a, W: Writer> RepeatFasta<'a, W> { } } -fn make_lookup(a: &[AminoAcid]) -> [AminoAcid, ..LOOKUP_SIZE] { - let mut lookup = [ NULL_AMINO_ACID, ..LOOKUP_SIZE ]; +fn make_lookup(a: &[AminoAcid]) -> [AminoAcid;LOOKUP_SIZE] { + let mut lookup = [ NULL_AMINO_ACID;LOOKUP_SIZE ]; let mut j = 0; for (i, slot) in lookup.iter_mut().enumerate() { while a[j].p < (i as f32) { @@ -162,7 +162,7 @@ fn make_lookup(a: &[AminoAcid]) -> [AminoAcid, ..LOOKUP_SIZE] { struct RandomFasta<'a, W:'a> { seed: u32, - lookup: [AminoAcid, ..LOOKUP_SIZE], + lookup: [AminoAcid;LOOKUP_SIZE], out: &'a mut W, } @@ -193,7 +193,7 @@ impl<'a, W: Writer> RandomFasta<'a, W> { fn make(&mut self, n: uint) -> IoResult<()> { let lines = n / LINE_LEN; let chars_left = n % LINE_LEN; - let mut buf = [0, ..LINE_LEN + 1]; + let mut buf = [0;LINE_LEN + 1]; for _ in range(0, lines) { for i in range(0u, LINE_LEN) { diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 1f0bed05521..2de61cf3572 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -89,7 +89,7 @@ fn make_fasta>( -> std::io::IoResult<()> { try!(wr.write(header.as_bytes())); - let mut line = [0u8, .. LINE_LENGTH + 1]; + let mut line = [0u8; LINE_LENGTH + 1]; while n > 0 { let nb = min(LINE_LENGTH, n); for i in range(0, nb) { diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index d112fe60674..8521e2216e9 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -46,10 +46,10 @@ use std::string::String; use std::slice; use std::sync::{Arc, Future}; -static TABLE: [u8, ..4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ]; +static TABLE: [u8;4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ]; static TABLE_SIZE: uint = 2 << 16; -static OCCURRENCES: [&'static str, ..5] = [ +static OCCURRENCES: [&'static str;5] = [ "GGT", "GGTA", "GGTATT", diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index 3f36c16aff6..dab67331120 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -45,7 +45,7 @@ const SOLAR_MASS: f64 = 4.0 * PI * PI; const YEAR: f64 = 365.24; const N_BODIES: uint = 5; -static BODIES: [Planet, ..N_BODIES] = [ +static BODIES: [Planet;N_BODIES] = [ // Sun Planet { x: 0.0, y: 0.0, z: 0.0, @@ -102,7 +102,7 @@ struct Planet { impl Copy for Planet {} -fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: int) { +fn advance(bodies: &mut [Planet;N_BODIES], dt: f64, steps: int) { for _ in range(0, steps) { let mut b_slice = bodies.as_mut_slice(); loop { @@ -135,7 +135,7 @@ fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: int) { } } -fn energy(bodies: &[Planet, ..N_BODIES]) -> f64 { +fn energy(bodies: &[Planet;N_BODIES]) -> f64 { let mut e = 0.0; let mut bodies = bodies.iter(); loop { @@ -155,7 +155,7 @@ fn energy(bodies: &[Planet, ..N_BODIES]) -> f64 { e } -fn offset_momentum(bodies: &mut [Planet, ..N_BODIES]) { +fn offset_momentum(bodies: &mut [Planet;N_BODIES]) { let mut px = 0.0; let mut py = 0.0; let mut pz = 0.0; diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index 312ee2dd27e..d746ec1dbab 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -50,17 +50,17 @@ use std::ptr::{copy_memory}; use std::io::{IoResult, EndOfFile}; struct Tables { - table8: [u8, ..1 << 8], - table16: [u16, ..1 << 16] + table8: [u8;1 << 8], + table16: [u16;1 << 16] } impl Tables { fn new() -> Tables { - let mut table8 = [0, ..1 << 8]; + let mut table8 = [0;1 << 8]; for (i, v) in table8.iter_mut().enumerate() { *v = Tables::computed_cpl8(i as u8); } - let mut table16 = [0, ..1 << 16]; + let mut table16 = [0;1 << 16]; for (i, v) in table16.iter_mut().enumerate() { *v = table8[i & 255] as u16 << 8 | table8[i >> 8] as u16; diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index c55f85f40e8..5fb7e2c3a84 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -46,7 +46,7 @@ impl Sudoku { return Sudoku { grid: g } } - pub fn from_vec(vec: &[[u8, ..9], ..9]) -> Sudoku { + pub fn from_vec(vec: &[[u8;9];9]) -> Sudoku { let g = Vec::from_fn(9u, |i| { Vec::from_fn(9u, |j| { vec[i][j] }) }); @@ -198,7 +198,7 @@ impl Colors { } } -static DEFAULT_SUDOKU: [[u8, ..9], ..9] = [ +static DEFAULT_SUDOKU: [[u8;9];9] = [ /* 0 1 2 3 4 5 6 7 8 */ /* 0 */ [0u8, 4u8, 0u8, 6u8, 0u8, 0u8, 0u8, 3u8, 2u8], /* 1 */ [0u8, 0u8, 8u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8], @@ -212,7 +212,7 @@ static DEFAULT_SUDOKU: [[u8, ..9], ..9] = [ ]; #[cfg(test)] -static DEFAULT_SOLUTION: [[u8, ..9], ..9] = [ +static DEFAULT_SOLUTION: [[u8;9];9] = [ /* 0 1 2 3 4 5 6 7 8 */ /* 0 */ [1u8, 4u8, 9u8, 6u8, 7u8, 5u8, 8u8, 3u8, 2u8], /* 1 */ [5u8, 3u8, 8u8, 1u8, 2u8, 9u8, 7u8, 4u8, 6u8], diff --git a/src/test/compile-fail/better-expected.rs b/src/test/compile-fail/better-expected.rs index 489f892726a..2e0f2a174c6 100644 --- a/src/test/compile-fail/better-expected.rs +++ b/src/test/compile-fail/better-expected.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - let x: [int ..3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `..` + let x: [int 3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, `;`, or `]`, found `3` } diff --git a/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs b/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs index 93a4383b4f5..f0d42bb9ac1 100644 --- a/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs +++ b/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs @@ -11,7 +11,7 @@ // Issue #16205. struct Foo { - a: [Box, ..3], + a: [Box; 3], } fn main() { diff --git a/src/test/compile-fail/coercion-slice.rs b/src/test/compile-fail/coercion-slice.rs index bb020688f58..b6b46fadb13 100644 --- a/src/test/compile-fail/coercion-slice.rs +++ b/src/test/compile-fail/coercion-slice.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Tests that we forbid coercion from `[T, ..n]` to `&[T]` +// Tests that we forbid coercion from `[T; n]` to `&[T]` fn main() { - let _: &[int] = [0i]; //~ERROR: mismatched types: expected `&[int]`, found `[int, ..1]` + let _: &[int] = [0i]; //~ERROR: mismatched types: expected `&[int]`, found `[int; 1]` } diff --git a/src/test/compile-fail/const-cast-wrong-type.rs b/src/test/compile-fail/const-cast-wrong-type.rs index 223426dc7c6..b3597441834 100644 --- a/src/test/compile-fail/const-cast-wrong-type.rs +++ b/src/test/compile-fail/const-cast-wrong-type.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static a: [u8, ..3] = ['h' as u8, 'i' as u8, 0 as u8]; +static a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8]; static b: *const i8 = &a as *const i8; //~ ERROR mismatched types fn main() { diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index 59499ac070d..c77ae25e0cf 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -20,9 +20,9 @@ trait Bar {} pub fn main() { // With a vec of ints. let f1 = Fat { ptr: [1, 2, 3] }; - let f2: &Fat<[int, ..3]> = &f1; + let f2: &Fat<[int; 3]> = &f1; let f3: &Fat<[uint]> = f2; - //~^ ERROR mismatched types: expected `&Fat<[uint]>`, found `&Fat<[int, ..3]>` + //~^ ERROR mismatched types: expected `&Fat<[uint]>`, found `&Fat<[int; 3]>` // With a trait. let f1 = Fat { ptr: Foo }; diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index e1a754b6332..6eb650e9781 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -21,7 +21,7 @@ impl Bar for Foo {} pub fn main() { // With a vec of ints. let f1 = Fat { ptr: [1, 2, 3] }; - let f2: &Fat<[int, ..3]> = &f1; + let f2: &Fat<[int; 3]> = &f1; let f3: &mut Fat<[int]> = f2; //~ ERROR mismatched types // With a trait. diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index 7cf647a26d7..b0bd5176374 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -21,7 +21,7 @@ impl Bar for Foo {} fn baz<'a>() { // With a vec of ints. let f1 = Fat { ptr: [1, 2, 3] }; - let f2: &Fat<[int, ..3]> = &f1; //~ ERROR `f1` does not live long enough + let f2: &Fat<[int; 3]> = &f1; //~ ERROR `f1` does not live long enough let f3: &'a Fat<[int]> = f2; // With a trait. diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs index 9010185f76b..783a32d6302 100644 --- a/src/test/compile-fail/dst-bad-coerce4.rs +++ b/src/test/compile-fail/dst-bad-coerce4.rs @@ -17,6 +17,6 @@ struct Fat { pub fn main() { // With a vec of ints. let f1: &Fat<[int]> = &Fat { ptr: [1, 2, 3] }; - let f2: &Fat<[int, ..3]> = f1; - //~^ ERROR mismatched types: expected `&Fat<[int, ..3]>`, found `&Fat<[int]>` + let f2: &Fat<[int; 3]> = f1; + //~^ ERROR mismatched types: expected `&Fat<[int; 3]>`, found `&Fat<[int]>` } diff --git a/src/test/compile-fail/dst-bad-deep.rs b/src/test/compile-fail/dst-bad-deep.rs index 506322d41f5..0833a74f1da 100644 --- a/src/test/compile-fail/dst-bad-deep.rs +++ b/src/test/compile-fail/dst-bad-deep.rs @@ -18,7 +18,7 @@ struct Fat { } pub fn main() { - let f: Fat<[int, ..3]> = Fat { ptr: [5i, 6, 7] }; + let f: Fat<[int; 3]> = Fat { ptr: [5i, 6, 7] }; let g: &Fat<[int]> = &f; let h: &Fat> = &Fat { ptr: *g }; //~^ ERROR the trait `core::kinds::Sized` is not implemented diff --git a/src/test/compile-fail/huge-array-simple.rs b/src/test/compile-fail/huge-array-simple.rs index 17f85c7bd2b..a9dda771b7f 100644 --- a/src/test/compile-fail/huge-array-simple.rs +++ b/src/test/compile-fail/huge-array-simple.rs @@ -11,5 +11,5 @@ // error-pattern: too big for the current fn main() { - let fat : [u8, ..(1<<61)+(1<<31)] = [0, ..(1u64<<61) as uint +(1u64<<31) as uint]; + let fat : [u8; (1<<61)+(1<<31)] = [0; (1u64<<61) as uint +(1u64<<31) as uint]; } diff --git a/src/test/compile-fail/huge-array.rs b/src/test/compile-fail/huge-array.rs index 4b91564154b..029e9651cb3 100644 --- a/src/test/compile-fail/huge-array.rs +++ b/src/test/compile-fail/huge-array.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: ..1518599999 +// error-pattern:; 1518599999 fn generic(t: T) { - let s: [T, ..1518600000] = [t, ..1518600000]; + let s: [T; 1518600000] = [t; 1518600000]; } fn main() { - let x: [u8, ..1518599999] = [0, ..1518599999]; - generic::<[u8, ..1518599999]>(x); + let x: [u8; 1518599999] = [0; 1518599999]; + generic::<[u8; 1518599999]>(x); } diff --git a/src/test/compile-fail/huge-enum.rs b/src/test/compile-fail/huge-enum.rs index 4a85cb5753b..7c7a75abf3f 100644 --- a/src/test/compile-fail/huge-enum.rs +++ b/src/test/compile-fail/huge-enum.rs @@ -14,10 +14,10 @@ #[cfg(target_word_size = "32")] fn main() { - let big: Option<[u32, ..(1<<29)-1]> = None; + let big: Option<[u32; (1<<29)-1]> = None; } #[cfg(target_word_size = "64")] fn main() { - let big: Option<[u32, ..(1<<45)-1]> = None; + let big: Option<[u32; (1<<45)-1]> = None; } diff --git a/src/test/compile-fail/issue-13446.rs b/src/test/compile-fail/issue-13446.rs index 162324b7c59..a0a7660428d 100644 --- a/src/test/compile-fail/issue-13446.rs +++ b/src/test/compile-fail/issue-13446.rs @@ -13,7 +13,7 @@ // error-pattern: mismatched types -static VEC: [u32, ..256] = vec!(); +static VEC: [u32; 256] = vec!(); fn main() {} diff --git a/src/test/compile-fail/issue-13482-2.rs b/src/test/compile-fail/issue-13482-2.rs index 4ec8c2b1b7e..ef7d3d4d158 100644 --- a/src/test/compile-fail/issue-13482-2.rs +++ b/src/test/compile-fail/issue-13482-2.rs @@ -14,7 +14,7 @@ fn main() { let x = [1,2]; let y = match x { [] => None, - //~^ ERROR types: expected `[_#0i, ..2]`, found `[_#7t, ..0]` + //~^ ERROR types: expected `[_#0i; 2]`, found `[_#7t; 0]` // (expected array of 2 elements, found array of 0 elements) [a,_] => Some(a) }; diff --git a/src/test/compile-fail/issue-13482.rs b/src/test/compile-fail/issue-13482.rs index 18070ed53b0..157280b1719 100644 --- a/src/test/compile-fail/issue-13482.rs +++ b/src/test/compile-fail/issue-13482.rs @@ -12,7 +12,7 @@ fn main() { let x = [1,2]; let y = match x { [] => None, -//~^ ERROR types: expected `[_, ..2]`, found `[_, ..0]` +//~^ ERROR types: expected `[_; 2]`, found `[_; 0]` // (expected array of 2 elements, found array of 0 elements) [a,_] => Some(a) }; diff --git a/src/test/compile-fail/issue-14845.rs b/src/test/compile-fail/issue-14845.rs index bc606d8139f..5166d84a025 100644 --- a/src/test/compile-fail/issue-14845.rs +++ b/src/test/compile-fail/issue-14845.rs @@ -10,15 +10,15 @@ struct X { - a: [u8, ..1] + a: [u8; 1] } fn main() { let x = X { a: [0] }; let _f = &x.a as *mut u8; - //~^ ERROR mismatched types: expected `*mut u8`, found `&[u8, ..1]` + //~^ ERROR mismatched types: expected `*mut u8`, found `&[u8; 1]` let local = [0u8]; let _v = &local as *mut u8; - //~^ ERROR mismatched types: expected `*mut u8`, found `&[u8, ..1]` + //~^ ERROR mismatched types: expected `*mut u8`, found `&[u8; 1]` } diff --git a/src/test/compile-fail/issue-17252.rs b/src/test/compile-fail/issue-17252.rs index 4a6b80d765b..4adb3f041a3 100644 --- a/src/test/compile-fail/issue-17252.rs +++ b/src/test/compile-fail/issue-17252.rs @@ -11,10 +11,10 @@ static FOO: uint = FOO; //~ ERROR recursive constant fn main() { - let _x: [u8, ..FOO]; // caused stack overflow prior to fix + let _x: [u8; FOO]; // caused stack overflow prior to fix let _y: uint = 1 + { static BAR: uint = BAR; //~ ERROR recursive constant - let _z: [u8, ..BAR]; // caused stack overflow prior to fix + let _z: [u8; BAR]; // caused stack overflow prior to fix 1 }; } diff --git a/src/test/compile-fail/issue-17441.rs b/src/test/compile-fail/issue-17441.rs index 11c815da1c7..e5da5c5504e 100644 --- a/src/test/compile-fail/issue-17441.rs +++ b/src/test/compile-fail/issue-17441.rs @@ -10,7 +10,7 @@ fn main() { let _foo = &[1u, 2] as [uint]; - //~^ ERROR cast to unsized type: `&[uint, ..2]` as `[uint]` + //~^ ERROR cast to unsized type: `&[uint; 2]` as `[uint]` //~^^ HELP consider using an implicit coercion to `&[uint]` instead let _bar = box 1u as std::fmt::Show; //~^ ERROR cast to unsized type: `Box` as `core::fmt::Show` @@ -19,6 +19,6 @@ fn main() { //~^ ERROR cast to unsized type: `uint` as `core::fmt::Show` //~^^ HELP consider using a box or reference as appropriate let _quux = [1u, 2] as [uint]; - //~^ ERROR cast to unsized type: `[uint, ..2]` as `[uint]` + //~^ ERROR cast to unsized type: `[uint; 2]` as `[uint]` //~^^ HELP consider using a box or reference as appropriate } diff --git a/src/test/compile-fail/issue-17718-borrow-interior.rs b/src/test/compile-fail/issue-17718-borrow-interior.rs index 1f763dbdc9f..8aa5fdf1c4d 100644 --- a/src/test/compile-fail/issue-17718-borrow-interior.rs +++ b/src/test/compile-fail/issue-17718-borrow-interior.rs @@ -15,7 +15,7 @@ static B: &'static uint = &A.a; static C: &'static uint = &(A.a); //~^ ERROR: cannot refer to the interior of another static -static D: [uint, ..1] = [1]; +static D: [uint; 1] = [1]; static E: uint = D[0]; //~^ ERROR: cannot refer to other statics by value static F: &'static uint = &D[0]; diff --git a/src/test/compile-fail/issue-19244-1.rs b/src/test/compile-fail/issue-19244-1.rs index 7ca83f21305..fafe6377397 100644 --- a/src/test/compile-fail/issue-19244-1.rs +++ b/src/test/compile-fail/issue-19244-1.rs @@ -11,6 +11,6 @@ const TUP: (uint,) = (42,); fn main() { - let a: [int, ..TUP.1]; + let a: [int; TUP.1]; //~^ ERROR expected constant expr for array length: tuple index out of bounds } diff --git a/src/test/compile-fail/issue-19244-2.rs b/src/test/compile-fail/issue-19244-2.rs index d9aeecc0222..95965ca35f9 100644 --- a/src/test/compile-fail/issue-19244-2.rs +++ b/src/test/compile-fail/issue-19244-2.rs @@ -12,6 +12,6 @@ struct MyStruct { field: uint } const STRUCT: MyStruct = MyStruct { field: 42 }; fn main() { - let a: [int, ..STRUCT.nonexistent_field]; + let a: [int; STRUCT.nonexistent_field]; //~^ ERROR expected constant expr for array length: nonexistent struct field } diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index 1150f40db76..3343e92252f 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -22,5 +22,5 @@ impl
vec_monad for Vec { } fn main() { ["hi"].bind(|x| [x] ); - //~^ ERROR type `[&str, ..1]` does not implement any method in scope named `bind` + //~^ ERROR type `[&str; 1]` does not implement any method in scope named `bind` } diff --git a/src/test/compile-fail/issue-4517.rs b/src/test/compile-fail/issue-4517.rs index f61ed35fca3..1c5fd9be1bd 100644 --- a/src/test/compile-fail/issue-4517.rs +++ b/src/test/compile-fail/issue-4517.rs @@ -11,8 +11,8 @@ fn bar(int_param: int) {} fn main() { - let foo: [u8, ..4] = [1u8, ..4u]; + let foo: [u8; 4] = [1u8; 4u]; bar(foo); - //~^ ERROR mismatched types: expected `int`, found `[u8, ..4]` + //~^ ERROR mismatched types: expected `int`, found `[u8; 4]` // (expected int, found vector) } diff --git a/src/test/compile-fail/lint-uppercase-variables.rs b/src/test/compile-fail/lint-uppercase-variables.rs index eb5c475e7ef..19373c806f1 100644 --- a/src/test/compile-fail/lint-uppercase-variables.rs +++ b/src/test/compile-fail/lint-uppercase-variables.rs @@ -29,7 +29,7 @@ fn main() { println!("{}", Test); let mut f = File::open(&Path::new("something.txt")); - let mut buff = [0u8, ..16]; + let mut buff = [0u8; 16]; match f.read(&mut buff) { Ok(cnt) => println!("read this many bytes: {}", cnt), Err(IoError{ kind: EndOfFile, .. }) => println!("Got end of file: {}", EndOfFile.to_string()), diff --git a/src/test/compile-fail/move-fragments-9.rs b/src/test/compile-fail/move-fragments-9.rs index ce05087f659..0b095ff6f82 100644 --- a/src/test/compile-fail/move-fragments-9.rs +++ b/src/test/compile-fail/move-fragments-9.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test moving array structures, e.g. `[T, ..3]` as well as moving +// Test moving array structures, e.g. `[T; 3]` as well as moving // elements in and out of such arrays. // // Note also that the `test_move_array_then_overwrite` tests represent @@ -18,14 +18,14 @@ pub struct D { d: int } impl Drop for D { fn drop(&mut self) { } } #[rustc_move_fragments] -pub fn test_move_array_via_return(a: [D, ..3]) -> [D, ..3] { +pub fn test_move_array_via_return(a: [D; 3]) -> [D; 3] { //~^ ERROR assigned_leaf_path: `$(local a)` //~| ERROR moved_leaf_path: `$(local a)` return a; } #[rustc_move_fragments] -pub fn test_move_array_into_recv(a: [D, ..3], recv: &mut [D, ..3]) { +pub fn test_move_array_into_recv(a: [D; 3], recv: &mut [D; 3]) { //~^ ERROR parent_of_fragments: `$(local recv)` //~| ERROR assigned_leaf_path: `$(local a)` //~| ERROR moved_leaf_path: `$(local a)` @@ -34,7 +34,7 @@ pub fn test_move_array_into_recv(a: [D, ..3], recv: &mut [D, ..3]) { } #[rustc_move_fragments] -pub fn test_extract_array_elem(a: [D, ..3], i: uint) -> D { +pub fn test_extract_array_elem(a: [D; 3], i: uint) -> D { //~^ ERROR parent_of_fragments: `$(local a)` //~| ERROR assigned_leaf_path: `$(local i)` //~| ERROR moved_leaf_path: `$(local a).[]` @@ -43,7 +43,7 @@ pub fn test_extract_array_elem(a: [D, ..3], i: uint) -> D { } #[rustc_move_fragments] -pub fn test_overwrite_array_elem(mut a: [D, ..3], i: uint, d: D) { +pub fn test_overwrite_array_elem(mut a: [D; 3], i: uint, d: D) { //~^ ERROR parent_of_fragments: `$(local mut a)` //~| ERROR assigned_leaf_path: `$(local i)` //~| ERROR assigned_leaf_path: `$(local d)` @@ -59,7 +59,7 @@ pub fn test_overwrite_array_elem(mut a: [D, ..3], i: uint, d: D) { // See RFC PR 320 for more discussion. #[rustc_move_fragments] -pub fn test_move_array_then_overwrite_elem1(mut a: [D, ..3], i: uint, recv: &mut [D, ..3], d: D) { +pub fn test_move_array_then_overwrite_elem1(mut a: [D; 3], i: uint, recv: &mut [D; 3], d: D) { //~^ ERROR parent_of_fragments: `$(local mut a)` //~| ERROR parent_of_fragments: `$(local recv)` //~| ERROR assigned_leaf_path: `$(local recv).*` @@ -76,8 +76,8 @@ pub fn test_move_array_then_overwrite_elem1(mut a: [D, ..3], i: uint, recv: &mut } #[rustc_move_fragments] -pub fn test_move_array_then_overwrite_elem2(mut a: [D, ..3], i: uint, j: uint, - recv: &mut [D, ..3], d1: D, d2: D) { +pub fn test_move_array_then_overwrite_elem2(mut a: [D; 3], i: uint, j: uint, + recv: &mut [D; 3], d1: D, d2: D) { //~^^ ERROR parent_of_fragments: `$(local mut a)` //~| ERROR parent_of_fragments: `$(local recv)` //~| ERROR assigned_leaf_path: `$(local recv).*` diff --git a/src/test/compile-fail/moves-based-on-type-exprs.rs b/src/test/compile-fail/moves-based-on-type-exprs.rs index 678808f166c..d8d84e558a9 100644 --- a/src/test/compile-fail/moves-based-on-type-exprs.rs +++ b/src/test/compile-fail/moves-based-on-type-exprs.rs @@ -89,7 +89,7 @@ fn f100() { fn f110() { let x = vec!("hi".to_string()); - let _y = [x.into_iter().next().unwrap(), ..1]; + let _y = [x.into_iter().next().unwrap(); 1]; touch(&x); //~ ERROR use of moved value: `x` } diff --git a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs index 3ccce591ee7..a1dc2ab2041 100644 --- a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs @@ -11,6 +11,6 @@ enum State { ST_NULL, ST_WHITESPACE } fn main() { - [State::ST_NULL, ..(State::ST_WHITESPACE as uint)]; + [State::ST_NULL; (State::ST_WHITESPACE as uint)]; //~^ ERROR expected constant integer for repeat count, found non-constant expression } diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs index 91551941c06..85d734ddaf2 100644 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs @@ -12,7 +12,7 @@ fn main() { fn bar(n: int) { - let _x: [int, ..n]; + let _x: [int; n]; //~^ ERROR expected constant expr for array length: non-constant path in constant expr } } diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs index 299e9d3dced..2e063e5237c 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs @@ -12,6 +12,6 @@ fn main() { fn bar(n: uint) { - let _x = [0, ..n]; //~ ERROR expected constant integer for repeat count, found variable + let _x = [0; n]; //~ ERROR expected constant integer for repeat count, found variable } } diff --git a/src/test/compile-fail/non-exhaustive-pattern-witness.rs b/src/test/compile-fail/non-exhaustive-pattern-witness.rs index 6e1c3db1014..d35e3ad3c55 100644 --- a/src/test/compile-fail/non-exhaustive-pattern-witness.rs +++ b/src/test/compile-fail/non-exhaustive-pattern-witness.rs @@ -12,7 +12,7 @@ struct Foo { first: bool, - second: Option<[uint, ..4]> + second: Option<[uint; 4]> } enum Color { diff --git a/src/test/compile-fail/packed-struct-generic-transmute.rs b/src/test/compile-fail/packed-struct-generic-transmute.rs index d699f69864e..5c0aba42b96 100644 --- a/src/test/compile-fail/packed-struct-generic-transmute.rs +++ b/src/test/compile-fail/packed-struct-generic-transmute.rs @@ -33,7 +33,7 @@ struct Oof { fn main() { let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 }; unsafe { - let oof: Oof<[u8, .. 5], i32> = mem::transmute(foo); + let oof: Oof<[u8; 5], i32> = mem::transmute(foo); println!("{} {}", oof.rab[], oof.zab); } } diff --git a/src/test/compile-fail/removed-syntax-fixed-vec.rs b/src/test/compile-fail/removed-syntax-fixed-vec.rs index fe49d1f4a8d..0a8420c19c3 100644 --- a/src/test/compile-fail/removed-syntax-fixed-vec.rs +++ b/src/test/compile-fail/removed-syntax-fixed-vec.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type v = [int * 3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `*` +type v = [int * 3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, `;`, or `]`, found `*` diff --git a/src/test/compile-fail/removed-syntax-mut-vec-expr.rs b/src/test/compile-fail/removed-syntax-mut-vec-expr.rs index 437f871f8ea..30302bbd16e 100644 --- a/src/test/compile-fail/removed-syntax-mut-vec-expr.rs +++ b/src/test/compile-fail/removed-syntax-mut-vec-expr.rs @@ -11,5 +11,5 @@ fn f() { let v = [mut 1, 2, 3, 4]; //~^ ERROR expected identifier, found keyword `mut` - //~^^ ERROR expected one of `!`, `,`, `.`, `::`, `]`, `{`, or an operator, found `1` + //~^^ ERROR expected one of `!`, `,`, `.`, `::`, `;`, `]`, `{`, or an operator, found `1` } diff --git a/src/test/compile-fail/removed-syntax-mut-vec-ty.rs b/src/test/compile-fail/removed-syntax-mut-vec-ty.rs index af469fadf98..9c6056bd72a 100644 --- a/src/test/compile-fail/removed-syntax-mut-vec-ty.rs +++ b/src/test/compile-fail/removed-syntax-mut-vec-ty.rs @@ -10,4 +10,4 @@ type v = [mut int]; //~^ ERROR expected identifier, found keyword `mut` - //~^^ ERROR expected one of `(`, `+`, `,`, `::`, or `]`, found `int` + //~^^ ERROR expected one of `(`, `+`, `,`, `::`, `;`, or `]`, found `int` diff --git a/src/test/compile-fail/repeat-to-run-dtor-twice.rs b/src/test/compile-fail/repeat-to-run-dtor-twice.rs index 8fdf586b3d1..d3126cf44d1 100644 --- a/src/test/compile-fail/repeat-to-run-dtor-twice.rs +++ b/src/test/compile-fail/repeat-to-run-dtor-twice.rs @@ -24,6 +24,6 @@ impl Drop for Foo { fn main() { let a = Foo { x: 3 }; - let _ = [ a, ..5 ]; + let _ = [ a; 5 ]; //~^ ERROR the trait `core::kinds::Copy` is not implemented for the type `Foo` } diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs index 38fbb426fb1..3b0ef0c293a 100644 --- a/src/test/compile-fail/repeat_count.rs +++ b/src/test/compile-fail/repeat_count.rs @@ -12,18 +12,18 @@ fn main() { let n = 1; - let a = [0, ..n]; //~ ERROR expected constant integer for repeat count, found variable - let b = [0, ..()]; + let a = [0; n]; //~ ERROR expected constant integer for repeat count, found variable + let b = [0; ()]; //~^ ERROR expected constant integer for repeat count, found non-constant expression //~^^ ERROR: expected `uint`, found `()` - let c = [0, ..true]; //~ ERROR expected positive integer for repeat count, found boolean + let c = [0; true]; //~ ERROR expected positive integer for repeat count, found boolean //~^ ERROR: expected `uint`, found `bool` - let d = [0, ..0.5]; //~ ERROR expected positive integer for repeat count, found float + let d = [0; 0.5]; //~ ERROR expected positive integer for repeat count, found float //~^ ERROR: expected `uint`, found `_` - let e = [0, .."foo"]; //~ ERROR expected positive integer for repeat count, found string + let e = [0; "foo"]; //~ ERROR expected positive integer for repeat count, found string //~^ ERROR: expected `uint`, found `&'static str` - let f = [0, ..-4]; + let f = [0; -4]; //~^ ERROR expected positive integer for repeat count, found negative integer - let f = [0u, ..-1]; + let f = [0u; -1]; //~^ ERROR expected positive integer for repeat count, found negative integer } diff --git a/src/test/compile-fail/static-vec-repeat-not-constant.rs b/src/test/compile-fail/static-vec-repeat-not-constant.rs index 03be2cc8f0f..ff84ed5bf0c 100644 --- a/src/test/compile-fail/static-vec-repeat-not-constant.rs +++ b/src/test/compile-fail/static-vec-repeat-not-constant.rs @@ -10,7 +10,7 @@ fn foo() -> int { 23 } -static a: [int, ..2] = [foo(), ..2]; +static a: [int; 2] = [foo(); 2]; //~^ ERROR: function calls in constants are limited to struct and enum constructors fn main() {} diff --git a/src/test/compile-fail/trailing-comma-array-repeat.rs b/src/test/compile-fail/trailing-comma-array-repeat.rs deleted file mode 100644 index dadd6571583..00000000000 --- a/src/test/compile-fail/trailing-comma-array-repeat.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 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. - -fn main() { - let [_, ..,] = [(), ()]; //~ ERROR unexpected token: `]` -} diff --git a/src/test/compile-fail/transmute-type-parameters.rs b/src/test/compile-fail/transmute-type-parameters.rs index 53391a0e894..2286c0e75bd 100644 --- a/src/test/compile-fail/transmute-type-parameters.rs +++ b/src/test/compile-fail/transmute-type-parameters.rs @@ -20,7 +20,7 @@ unsafe fn g(x: (T, int)) { let _: int = transmute(x); //~ ERROR cannot transmute } -unsafe fn h(x: [T, ..10]) { +unsafe fn h(x: [T; 10]) { let _: int = transmute(x); //~ ERROR cannot transmute } diff --git a/src/test/compile-fail/vector-cast-weirdness.rs b/src/test/compile-fail/vector-cast-weirdness.rs index e096e5eb436..c5109ce473e 100644 --- a/src/test/compile-fail/vector-cast-weirdness.rs +++ b/src/test/compile-fail/vector-cast-weirdness.rs @@ -12,20 +12,20 @@ // presence of the `_` type shorthand notation. struct X { - y: [u8, ..2], + y: [u8; 2], } fn main() { let x1 = X { y: [0, 0] }; let p1: *const u8 = &x1.y as *const _; //~ ERROR mismatched types - let t1: *const [u8, ..2] = &x1.y as *const _; - let h1: *const [u8, ..2] = &x1.y as *const [u8, ..2]; + let t1: *const [u8; 2] = &x1.y as *const _; + let h1: *const [u8; 2] = &x1.y as *const [u8; 2]; let mut x1 = X { y: [0, 0] }; let p1: *mut u8 = &mut x1.y as *mut _; //~ ERROR mismatched types - let t1: *mut [u8, ..2] = &mut x1.y as *mut _; - let h1: *mut [u8, ..2] = &mut x1.y as *mut [u8, ..2]; + let t1: *mut [u8; 2] = &mut x1.y as *mut _; + let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2]; } diff --git a/src/test/debuginfo/evec-in-struct.rs b/src/test/debuginfo/evec-in-struct.rs index aab9c446a9e..786868f6b89 100644 --- a/src/test/debuginfo/evec-in-struct.rs +++ b/src/test/debuginfo/evec-in-struct.rs @@ -53,28 +53,28 @@ #![allow(unused_variables)] struct NoPadding1 { - x: [u32, ..3], + x: [u32; 3], y: i32, - z: [f32, ..2] + z: [f32; 2] } struct NoPadding2 { - x: [u32, ..3], - y: [[u32, ..2], ..2] + x: [u32; 3], + y: [[u32; 2]; 2] } struct StructInternalPadding { - x: [i16, ..2], - y: [i64, ..2] + x: [i16; 2], + y: [i64; 2] } struct SingleVec { - x: [i16, ..5] + x: [i16; 5] } struct StructPaddedAtEnd { - x: [i64, ..2], - y: [i16, ..2] + x: [i64; 2], + y: [i16; 2] } fn main() { diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs index a1f34aea0f2..41dee642fea 100644 --- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs +++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs @@ -450,7 +450,7 @@ fn main() { sentinel(); val - }, ..10]; + }; 10]; zzz(); // #break sentinel(); @@ -491,7 +491,7 @@ fn main() { sentinel(); // index expression - let a_vector = [10i, ..20]; + let a_vector = [10i; 20]; let _ = a_vector[{ zzz(); // #break sentinel(); diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index 032b8b1fa26..8cc0fdabfc2 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -143,7 +143,7 @@ fn main() { value: 2, }; - let vec_unique: [UniqueNode, ..1] = [UniqueNode { + let vec_unique: [UniqueNode; 1] = [UniqueNode { next: Val { val: box UniqueNode { next: Empty, diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index d72b080409e..286c44667c5 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -99,10 +99,10 @@ // VECTORS // gdb-command:whatis fixed_size_vec1 -// gdb-check:type = struct ([type-names::Struct1, ..3], i16) +// gdb-check:type = struct ([type-names::Struct1; 3], i16) // gdb-command:whatis fixed_size_vec2 -// gdb-check:type = struct ([uint, ..3], i16) +// gdb-check:type = struct ([uint; 3], i16) // gdb-command:whatis slice1 // gdb-check:type = struct &[uint] diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs index fd422a90e63..00c93653cf4 100644 --- a/src/test/debuginfo/vec.rs +++ b/src/test/debuginfo/vec.rs @@ -30,7 +30,7 @@ #![allow(unused_variables)] -static mut VECT: [i32, ..3] = [1, 2, 3]; +static mut VECT: [i32; 3] = [1, 2, 3]; fn main() { let a = [1i, 2, 3]; diff --git a/src/test/pretty/blank-lines.rs b/src/test/pretty/blank-lines.rs index 24eb5337d25..1774edd3f76 100644 --- a/src/test/pretty/blank-lines.rs +++ b/src/test/pretty/blank-lines.rs @@ -9,7 +9,7 @@ // except according to those terms. // pp-exact -fn f() -> [int, ..3] { +fn f() -> [int; 3] { let picard = 0; let data = 1; diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index b5ea9bd4b89..974af1e6f3e 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -21,26 +21,26 @@ use std::prelude::*; // #4264 fixed-length vector types -pub fn foo(_: [int, ..(3 as uint)]) { } +pub fn foo(_: [int; (3 as uint)]) { } pub fn bar() { const FOO: uint = ((5u as uint) - (4u as uint) as uint); - let _: [(), ..(FOO as uint)] = ([(() as ())] as [(), ..1]); + let _: [(); (FOO as uint)] = ([(() as ())] as [(); 1]); - let _: [(), ..(1u as uint)] = ([(() as ())] as [(), ..1]); + let _: [(); (1u as uint)] = ([(() as ())] as [(); 1]); let _ = - (((&((([(1i as int), (2 as int), (3 as int)] as [int, ..3])) as - [int, ..3]) as &[int, ..3]) as *const _ as *const [int, ..3]) - as *const [int, ..(3u as uint)] as *const [int, ..3]); + (((&((([(1i as int), (2 as int), (3 as int)] as [int; 3])) as + [int; 3]) as &[int; 3]) as *const _ as *const [int; 3]) as + *const [int; (3u as uint)] as *const [int; 3]); (match (() as ()) { () => { #[inline] #[allow(dead_code)] static __STATIC_FMTSTR: &'static [&'static str] = - (&([("test" as &'static str)] as [&'static str, ..1]) as - &'static [&'static str, ..1]); + (&([("test" as &'static str)] as [&'static str; 1]) as + &'static [&'static str; 1]); @@ -57,9 +57,9 @@ pub fn bar() { &'static [&'static str]), (&([] as - [core::fmt::Argument<'_>, ..0]) + [core::fmt::Argument<'_>; 0]) as - &[core::fmt::Argument<'_>, ..0])) + &[core::fmt::Argument<'_>; 0])) as core::fmt::Arguments<'_>) as @@ -68,18 +68,17 @@ pub fn bar() { } } as collections::string::String); } -pub type Foo = [int, ..(3u as uint)]; +pub type Foo = [int; (3u as uint)]; pub struct Bar { - pub x: [int, ..(3u as uint)], + pub x: [int; (3u as uint)], } -pub struct TupleBar([int, ..(4u as uint)]); -pub enum Baz { BazVariant([int, ..(5u as uint)]), } +pub struct TupleBar([int; (4u as uint)]); +pub enum Baz { BazVariant([int; (5u as uint)]), } pub fn id(x: T) -> T { (x as T) } pub fn use_id() { let _ = - ((id::<[int, ..(3u as uint)]> as - fn([int, ..3]) -> [int, ..3])(([(1 as int), (2 as int), - (3 as int)] as [int, ..3])) as - [int, ..3]); + ((id::<[int; (3u as uint)]> as + fn([int; 3]) -> [int; 3])(([(1 as int), (2 as int), (3 as int)] + as [int; 3])) as [int; 3]); } fn main() { } diff --git a/src/test/run-make/no-stack-check/attr.rs b/src/test/run-make/no-stack-check/attr.rs index ef2db932b41..7d0fc2d7fe5 100644 --- a/src/test/run-make/no-stack-check/attr.rs +++ b/src/test/run-make/no-stack-check/attr.rs @@ -20,6 +20,6 @@ extern { #[no_stack_check] pub unsafe fn foo() { // Make sure we use the stack - let x: [u8, ..50] = [0, ..50]; + let x: [u8; 50] = [0; 50]; black_box(x.as_ptr()); } diff --git a/src/test/run-make/no-stack-check/flag.rs b/src/test/run-make/no-stack-check/flag.rs index ee0364001e1..2b6e7240d6f 100644 --- a/src/test/run-make/no-stack-check/flag.rs +++ b/src/test/run-make/no-stack-check/flag.rs @@ -19,6 +19,6 @@ extern { pub unsafe fn foo() { // Make sure we use the stack - let x: [u8, ..50] = [0, ..50]; + let x: [u8; 50] = [0; 50]; black_box(x.as_ptr()); } diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs index cab98204b17..fd112034f40 100644 --- a/src/test/run-make/target-specs/foo.rs +++ b/src/test/run-make/target-specs/foo.rs @@ -21,7 +21,7 @@ trait Sized { } fn start(_main: *const u8, _argc: int, _argv: *const *const u8) -> int { 0 } extern { - fn _foo() -> [u8, ..16]; + fn _foo() -> [u8; 16]; } fn _main() { diff --git a/src/test/run-pass/cast-in-array-size.rs b/src/test/run-pass/cast-in-array-size.rs index aaffb013ad8..717ca3ff9fe 100644 --- a/src/test/run-pass/cast-in-array-size.rs +++ b/src/test/run-pass/cast-in-array-size.rs @@ -13,8 +13,8 @@ const SIZE: int = 25; fn main() { - let _a: [bool, ..1 as uint]; - let _b: [int, ..SIZE as uint] = [1, ..SIZE as uint]; - let _c: [bool, ..'\n' as uint] = [true, ..'\n' as uint]; - let _d: [bool, ..true as uint] = [true, ..true as uint]; + let _a: [bool; 1 as uint]; + let _b: [int; SIZE as uint] = [1; SIZE as uint]; + let _c: [bool; '\n' as uint] = [true; '\n' as uint]; + let _d: [bool; true as uint] = [true; true as uint]; } diff --git a/src/test/run-pass/check-static-slice.rs b/src/test/run-pass/check-static-slice.rs index 60daedec4c7..6e2cfedf9ec 100644 --- a/src/test/run-pass/check-static-slice.rs +++ b/src/test/run-pass/check-static-slice.rs @@ -11,11 +11,11 @@ // Check that the various ways of getting to a reference to a vec (both sized // and unsized) work properly. -const aa: [int, ..3] = [1, 2, 3]; -const ab: &'static [int, ..3] = &aa; +const aa: [int; 3] = [1, 2, 3]; +const ab: &'static [int; 3] = &aa; const ac: &'static [int] = ab; const ad: &'static [int] = &aa; -const ae: &'static [int, ..3] = &[1, 2, 3]; +const ae: &'static [int; 3] = &[1, 2, 3]; const af: &'static [int] = &[1, 2, 3]; static ca: int = aa[0]; diff --git a/src/test/run-pass/const-autoderef.rs b/src/test/run-pass/const-autoderef.rs index e80ed7c984b..71312fb3878 100644 --- a/src/test/run-pass/const-autoderef.rs +++ b/src/test/run-pass/const-autoderef.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static A: [u8, ..1] = ['h' as u8]; +static A: [u8; 1] = ['h' as u8]; static B: u8 = (&A)[0]; -static C: &'static &'static &'static &'static [u8, ..1] = & & & &A; +static C: &'static &'static &'static &'static [u8; 1] = & & & &A; static D: u8 = (&C)[0]; pub fn main() { diff --git a/src/test/run-pass/const-enum-vec-index.rs b/src/test/run-pass/const-enum-vec-index.rs index fef6c8624cf..4c8124d28a2 100644 --- a/src/test/run-pass/const-enum-vec-index.rs +++ b/src/test/run-pass/const-enum-vec-index.rs @@ -12,7 +12,7 @@ enum E { V1(int), V0 } const C: &'static [E] = &[E::V0, E::V1(0xDEADBEE)]; static C0: E = C[0]; static C1: E = C[1]; -const D: &'static [E, ..2] = &[E::V0, E::V1(0xDEADBEE)]; +const D: &'static [E; 2] = &[E::V0, E::V1(0xDEADBEE)]; static D0: E = C[0]; static D1: E = C[1]; diff --git a/src/test/run-pass/const-enum-vector.rs b/src/test/run-pass/const-enum-vector.rs index 83687f8775b..6eb5c2dab38 100644 --- a/src/test/run-pass/const-enum-vector.rs +++ b/src/test/run-pass/const-enum-vector.rs @@ -9,7 +9,7 @@ // except according to those terms. enum E { V1(int), V0 } -static C: [E, ..3] = [E::V0, E::V1(0xDEADBEE), E::V0]; +static C: [E; 3] = [E::V0, E::V1(0xDEADBEE), E::V0]; pub fn main() { match C[1] { diff --git a/src/test/run-pass/const-expr-in-fixed-length-vec.rs b/src/test/run-pass/const-expr-in-fixed-length-vec.rs index 317a54e927f..6317c2eec18 100644 --- a/src/test/run-pass/const-expr-in-fixed-length-vec.rs +++ b/src/test/run-pass/const-expr-in-fixed-length-vec.rs @@ -14,6 +14,6 @@ pub fn main() { const FOO: uint = 2; - let _v: [int, ..FOO*3]; + let _v: [int; FOO*3]; } diff --git a/src/test/run-pass/const-expr-in-vec-repeat.rs b/src/test/run-pass/const-expr-in-vec-repeat.rs index 54386b33dd9..d692f3a87e4 100644 --- a/src/test/run-pass/const-expr-in-vec-repeat.rs +++ b/src/test/run-pass/const-expr-in-vec-repeat.rs @@ -13,6 +13,6 @@ pub fn main() { const FOO: uint = 2; - let _v = [0i, ..FOO*3*2/2]; + let _v = [0i; FOO*3*2/2]; } diff --git a/src/test/run-pass/const-fields-and-indexing.rs b/src/test/run-pass/const-fields-and-indexing.rs index 49b244a162b..0819e0becbf 100644 --- a/src/test/run-pass/const-fields-and-indexing.rs +++ b/src/test/run-pass/const-fields-and-indexing.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const x : [int, ..4] = [1,2,3,4]; +const x : [int; 4] = [1,2,3,4]; static p : int = x[2]; const y : &'static [int] = &[1,2,3,4]; static q : int = y[2]; diff --git a/src/test/run-pass/const-region-ptrs-noncopy.rs b/src/test/run-pass/const-region-ptrs-noncopy.rs index 5e417efb4b5..e8081005d4a 100644 --- a/src/test/run-pass/const-region-ptrs-noncopy.rs +++ b/src/test/run-pass/const-region-ptrs-noncopy.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type Big = [u64, ..8]; +type Big = [u64; 8]; struct Pair<'a> { a: int, b: &'a Big } const x: &'static Big = &([13, 14, 10, 13, 11, 14, 14, 15]); const y: &'static Pair<'static> = &Pair {a: 15, b: x}; diff --git a/src/test/run-pass/const-str-ptr.rs b/src/test/run-pass/const-str-ptr.rs index 47d59eca263..d6f0296619a 100644 --- a/src/test/run-pass/const-str-ptr.rs +++ b/src/test/run-pass/const-str-ptr.rs @@ -10,8 +10,8 @@ use std::{str, string}; -const A: [u8, ..2] = ['h' as u8, 'i' as u8]; -const B: &'static [u8, ..2] = &A; +const A: [u8; 2] = ['h' as u8, 'i' as u8]; +const B: &'static [u8; 2] = &A; const C: *const u8 = B as *const u8; pub fn main() { diff --git a/src/test/run-pass/const-vecs-and-slices.rs b/src/test/run-pass/const-vecs-and-slices.rs index 1a2a3e36e87..26874b9f9d5 100644 --- a/src/test/run-pass/const-vecs-and-slices.rs +++ b/src/test/run-pass/const-vecs-and-slices.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static x : [int, ..4] = [1,2,3,4]; +static x : [int; 4] = [1,2,3,4]; static y : &'static [int] = &[1,2,3,4]; -static z : &'static [int, ..4] = &[1,2,3,4]; +static z : &'static [int; 4] = &[1,2,3,4]; static zz : &'static [int] = &[1,2,3,4]; pub fn main() { diff --git a/src/test/run-pass/dst-struct.rs b/src/test/run-pass/dst-struct.rs index bf5b300f7cf..3644ca81d56 100644 --- a/src/test/run-pass/dst-struct.rs +++ b/src/test/run-pass/dst-struct.rs @@ -120,7 +120,7 @@ pub fn main() { assert!((*f2)[1] == 2); // Nested Box. - let f1 : Box> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + let f1 : Box> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; foo(&*f1); let f2 : Box> = f1; foo(&*f2); diff --git a/src/test/run-pass/enum-vec-initializer.rs b/src/test/run-pass/enum-vec-initializer.rs index 0256420ac4c..d436916c279 100644 --- a/src/test/run-pass/enum-vec-initializer.rs +++ b/src/test/run-pass/enum-vec-initializer.rs @@ -16,9 +16,9 @@ const BAR:uint = Flopsy::Bunny as uint; const BAR2:uint = BAR; pub fn main() { - let _v = [0i, .. Flopsy::Bunny as uint]; - let _v = [0i, .. BAR]; - let _v = [0i, .. BAR2]; + let _v = [0i; Flopsy::Bunny as uint]; + let _v = [0i; BAR]; + let _v = [0i; BAR2]; const BAR3:uint = BAR2; - let _v = [0i, .. BAR3]; + let _v = [0i; BAR3]; } diff --git a/src/test/run-pass/evec-internal.rs b/src/test/run-pass/evec-internal.rs index 36b5f86aeda..28b5f781b5c 100644 --- a/src/test/run-pass/evec-internal.rs +++ b/src/test/run-pass/evec-internal.rs @@ -13,16 +13,16 @@ // Doesn't work; needs a design decision. pub fn main() { - let x : [int, ..5] = [1,2,3,4,5]; - let _y : [int, ..5] = [1,2,3,4,5]; + let x : [int; 5] = [1,2,3,4,5]; + let _y : [int; 5] = [1,2,3,4,5]; let mut z = [1,2,3,4,5]; z = x; assert_eq!(z[0], 1); assert_eq!(z[4], 5); - let a : [int, ..5] = [1,1,1,1,1]; - let b : [int, ..5] = [2,2,2,2,2]; - let c : [int, ..5] = [2,2,2,2,3]; + let a : [int; 5] = [1,1,1,1,1]; + let b : [int; 5] = [2,2,2,2,2]; + let c : [int; 5] = [2,2,2,2,3]; log(debug, a); diff --git a/src/test/run-pass/huge-largest-array.rs b/src/test/run-pass/huge-largest-array.rs index d494e0bf40d..e24731546ed 100644 --- a/src/test/run-pass/huge-largest-array.rs +++ b/src/test/run-pass/huge-largest-array.rs @@ -12,10 +12,10 @@ use std::mem::size_of; #[cfg(target_word_size = "32")] pub fn main() { - assert_eq!(size_of::<[u8, ..(1 << 31) - 1]>(), (1 << 31) - 1); + assert_eq!(size_of::<[u8; (1 << 31) - 1]>(), (1 << 31) - 1); } #[cfg(target_word_size = "64")] pub fn main() { - assert_eq!(size_of::<[u8, ..(1 << 47) - 1]>(), (1 << 47) - 1); + assert_eq!(size_of::<[u8; (1 << 47) - 1]>(), (1 << 47) - 1); } diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs index ea138311f19..549a70f19e3 100644 --- a/src/test/run-pass/issue-11205.rs +++ b/src/test/run-pass/issue-11205.rs @@ -12,22 +12,22 @@ trait Foo {} impl Foo for int {} -fn foo(_: [&Foo, ..2]) {} +fn foo(_: [&Foo; 2]) {} fn foos(_: &[&Foo]) {} fn foog(_: &[T], _: &[T]) {} -fn bar(_: [Box, ..2]) {} +fn bar(_: [Box; 2]) {} fn bars(_: &[Box]) {} fn main() { - let x: [&Foo, ..2] = [&1i, &2i]; + let x: [&Foo; 2] = [&1i, &2i]; foo(x); foo([&1i, &2i]); let r = &1i; - let x: [&Foo, ..2] = [r, ..2]; + let x: [&Foo; 2] = [r; 2]; foo(x); - foo([&1i, ..2]); + foo([&1i; 2]); let x: &[&Foo] = &[&1i, &2i]; foos(x); @@ -37,7 +37,7 @@ fn main() { let r = &1i; foog(x, &[r]); - let x: [Box, ..2] = [box 1i, box 2i]; + let x: [Box; 2] = [box 1i, box 2i]; bar(x); bar([box 1i, box 2i]); @@ -49,16 +49,16 @@ fn main() { foog(x, &[box 1i]); struct T<'a> { - t: [&'a (Foo+'a), ..2] + t: [&'a (Foo+'a); 2] } let _n = T { t: [&1i, &2i] }; let r = &1i; let _n = T { - t: [r, ..2] + t: [r; 2] }; - let x: [&Foo, ..2] = [&1i, &2i]; + let x: [&Foo; 2] = [&1i, &2i]; let _n = T { t: x }; @@ -70,11 +70,11 @@ fn main() { t: &[&1i, &2i] }; let r = &1i; - let r: [&Foo, ..2] = [r, ..2]; + let r: [&Foo; 2] = [r; 2]; let _n = F { t: &r }; - let x: [&Foo, ..2] = [&1i, &2i]; + let x: [&Foo; 2] = [&1i, &2i]; let _n = F { t: &x }; @@ -85,7 +85,7 @@ fn main() { let _n = M { t: &[box 1i, box 2i] }; - let x: [Box, ..2] = [box 1i, box 2i]; + let x: [Box; 2] = [box 1i, box 2i]; let _n = M { t: &x }; diff --git a/src/test/run-pass/issue-13259-windows-tcb-trash.rs b/src/test/run-pass/issue-13259-windows-tcb-trash.rs index 0e42bdbd6ad..329ab7c921d 100644 --- a/src/test/run-pass/issue-13259-windows-tcb-trash.rs +++ b/src/test/run-pass/issue-13259-windows-tcb-trash.rs @@ -27,7 +27,7 @@ mod imp { } pub fn test() { - let mut buf: [u16, ..50] = [0, ..50]; + let mut buf: [u16; 50] = [0; 50]; let ret = unsafe { FormatMessageW(0x1000, 0 as *mut c_void, 1, 0x400, buf.as_mut_ptr(), buf.len() as u32, 0 as *const c_void) diff --git a/src/test/run-pass/issue-13763.rs b/src/test/run-pass/issue-13763.rs index 8b2b732415e..81b6892b0f9 100644 --- a/src/test/run-pass/issue-13763.rs +++ b/src/test/run-pass/issue-13763.rs @@ -12,9 +12,9 @@ use std::u8; const NUM: uint = u8::BITS as uint; -struct MyStruct { nums: [uint, ..8] } +struct MyStruct { nums: [uint; 8] } fn main() { - let _s = MyStruct { nums: [0, ..NUM] }; + let _s = MyStruct { nums: [0; NUM] }; } diff --git a/src/test/run-pass/issue-13837.rs b/src/test/run-pass/issue-13837.rs index 221115a0869..f62a45277b2 100644 --- a/src/test/run-pass/issue-13837.rs +++ b/src/test/run-pass/issue-13837.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static TEST_VALUE : *const [int, ..2] = 0x1234 as *const [int, ..2]; +static TEST_VALUE : *const [int; 2] = 0x1234 as *const [int; 2]; fn main() {} diff --git a/src/test/run-pass/issue-14940.rs b/src/test/run-pass/issue-14940.rs index cef09af1fcf..d815620c969 100644 --- a/src/test/run-pass/issue-14940.rs +++ b/src/test/run-pass/issue-14940.rs @@ -15,7 +15,7 @@ fn main() { let args = os::args(); if args.len() > 1 { let mut out = stdio::stdout(); - out.write(&['a' as u8, ..128 * 1024]).unwrap(); + out.write(&['a' as u8; 128 * 1024]).unwrap(); } else { let out = Command::new(args[0].as_slice()).arg("child").output(); let out = out.unwrap(); diff --git a/src/test/run-pass/issue-15673.rs b/src/test/run-pass/issue-15673.rs index 051d98aa1d8..e66788a2c00 100644 --- a/src/test/run-pass/issue-15673.rs +++ b/src/test/run-pass/issue-15673.rs @@ -10,6 +10,6 @@ use std::iter::AdditiveIterator; fn main() { - let x: [u64, ..3] = [1, 2, 3]; + let x: [u64; 3] = [1, 2, 3]; assert_eq!(6, range(0, 3).map(|i| x[i]).sum()); } diff --git a/src/test/run-pass/issue-17302.rs b/src/test/run-pass/issue-17302.rs index 50583c7d127..b2abf2d2b1a 100644 --- a/src/test/run-pass/issue-17302.rs +++ b/src/test/run-pass/issue-17302.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static mut DROPPED: [bool, ..2] = [false, false]; +static mut DROPPED: [bool; 2] = [false, false]; struct A(uint); struct Foo { _a: A, _b: int } diff --git a/src/test/run-pass/issue-17877.rs b/src/test/run-pass/issue-17877.rs index 51db2f05959..827e6a10abd 100644 --- a/src/test/run-pass/issue-17877.rs +++ b/src/test/run-pass/issue-17877.rs @@ -9,11 +9,11 @@ // except according to those terms. fn main() { - assert_eq!(match [0u8, ..1024] { + assert_eq!(match [0u8; 1024] { _ => 42u, }, 42u); - assert_eq!(match [0u8, ..1024] { + assert_eq!(match [0u8; 1024] { [1, _..] => 0u, [0, _..] => 1u, _ => 2u diff --git a/src/test/run-pass/issue-18425.rs b/src/test/run-pass/issue-18425.rs index 6bb244bf88f..f61530c7418 100644 --- a/src/test/run-pass/issue-18425.rs +++ b/src/test/run-pass/issue-18425.rs @@ -12,5 +12,5 @@ // expression with a count of 1 and a non-Copy element type. fn main() { - let _ = [box 1u, ..1]; + let _ = [box 1u; 1]; } diff --git a/src/test/run-pass/issue-19244.rs b/src/test/run-pass/issue-19244.rs index d42bda6cd5d..3ee5ce9bff9 100644 --- a/src/test/run-pass/issue-19244.rs +++ b/src/test/run-pass/issue-19244.rs @@ -13,8 +13,8 @@ const STRUCT: MyStruct = MyStruct { field: 42 }; const TUP: (uint,) = (43,); fn main() { - let a = [0i, ..STRUCT.field]; - let b = [0i, ..TUP.0]; + let a = [0i; STRUCT.field]; + let b = [0i; TUP.0]; assert!(a.len() == 42); assert!(b.len() == 43); diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index 1dc1587ff2f..f87eb46d553 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -63,7 +63,7 @@ fn read_board_grid(mut input: rdr) -> Vec> { let mut input: &mut io::Reader = &mut input; let mut grid = Vec::new(); - let mut line = [0, ..10]; + let mut line = [0; 10]; input.read(&mut line); let mut row = Vec::new(); for c in line.iter() { diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs index 53157ce7546..8a39676ca17 100644 --- a/src/test/run-pass/issue-3656.rs +++ b/src/test/run-pass/issue-3656.rs @@ -16,7 +16,7 @@ extern crate libc; use libc::{c_uint, uint32_t, c_void}; pub struct KEYGEN { - hash_algorithm: [c_uint, ..2], + hash_algorithm: [c_uint; 2], count: uint32_t, salt: *const c_void, salt_size: uint32_t, diff --git a/src/test/run-pass/issue-4387.rs b/src/test/run-pass/issue-4387.rs index 447bf3b4b26..43948ef4a45 100644 --- a/src/test/run-pass/issue-4387.rs +++ b/src/test/run-pass/issue-4387.rs @@ -9,5 +9,5 @@ // except according to those terms. pub fn main() { - let _foo = [0i, ..2*4]; + let _foo = [0i; 2*4]; } diff --git a/src/test/run-pass/issue-5688.rs b/src/test/run-pass/issue-5688.rs index 0a13e001fab..7c8940aafbf 100644 --- a/src/test/run-pass/issue-5688.rs +++ b/src/test/run-pass/issue-5688.rs @@ -13,7 +13,7 @@ ...should print &[1, 2, 3] but instead prints something like &[4492532864, 24]. It is pretty evident that the compiler messed up -with the representation of [int, ..n] and [int] somehow, or at least +with the representation of [int; n] and [int] somehow, or at least failed to typecheck correctly. */ diff --git a/src/test/run-pass/issue-7784.rs b/src/test/run-pass/issue-7784.rs index 666847517ef..b936eb322fc 100644 --- a/src/test/run-pass/issue-7784.rs +++ b/src/test/run-pass/issue-7784.rs @@ -10,10 +10,10 @@ #![feature(advanced_slice_patterns)] -fn foo + Clone>([x, y, z]: [T, ..3]) -> (T, T, T) { +fn foo + Clone>([x, y, z]: [T; 3]) -> (T, T, T) { (x.clone(), x.clone() + y.clone(), x + y + z) } -fn bar(a: &'static str, b: &'static str) -> [&'static str, ..4] { +fn bar(a: &'static str, b: &'static str) -> [&'static str; 4] { [a, b, b, a] } diff --git a/src/test/run-pass/issue-9942.rs b/src/test/run-pass/issue-9942.rs index b9410ffdb43..321e22cd19c 100644 --- a/src/test/run-pass/issue-9942.rs +++ b/src/test/run-pass/issue-9942.rs @@ -9,5 +9,5 @@ // except according to those terms. pub fn main() { - const S: uint = 23 as uint; [0i, ..S]; () + const S: uint = 23 as uint; [0i; S]; () } diff --git a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs index 4c124d85eee..ecd7c0458f7 100644 --- a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs +++ b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs @@ -15,5 +15,5 @@ macro_rules! four ( ); fn main() { - let _x: [u16, ..four!()]; + let _x: [u16; four!()]; } diff --git a/src/test/run-pass/match-arm-statics.rs b/src/test/run-pass/match-arm-statics.rs index 400aab64b4c..db512adc011 100644 --- a/src/test/run-pass/match-arm-statics.rs +++ b/src/test/run-pass/match-arm-statics.rs @@ -64,7 +64,7 @@ fn issue_6533() { } fn issue_13626() { - const VAL: [u8, ..1] = [0]; + const VAL: [u8; 1] = [0]; match [1] { VAL => unreachable!(), _ => () diff --git a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs index 00319d57f8d..9ae7f49c75a 100644 --- a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs +++ b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs @@ -38,7 +38,7 @@ impl<'a> MyWriter for &'a mut [u8] { } fn main() { - let mut buf = [0_u8, .. 6]; + let mut buf = [0_u8; 6]; { let mut writer = buf.as_mut_slice(); diff --git a/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs b/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs index 986236fb6f9..fbecb6851b6 100644 --- a/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs +++ b/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs @@ -28,7 +28,7 @@ impl B for *const [T] { } fn main() { - let x: [int, ..4] = [1,2,3,4]; + let x: [int; 4] = [1,2,3,4]; let xptr = x.as_slice() as *const _; xptr.foo(); } diff --git a/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs b/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs index ef0bc75c326..bf926a6c48a 100644 --- a/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs +++ b/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs @@ -9,13 +9,13 @@ // except according to those terms. fn test1() { - let mut ints = [0i, ..32]; + let mut ints = [0i; 32]; ints[0] += 1; assert_eq!(ints[0], 1); } fn test2() { - let mut ints = [0i, ..32]; + let mut ints = [0i; 32]; for i in ints.iter_mut() { *i += 22; } for i in ints.iter() { assert!(*i == 22); } } diff --git a/src/test/run-pass/new-style-fixed-length-vec.rs b/src/test/run-pass/new-style-fixed-length-vec.rs index a689fb0cf7c..e06461daed0 100644 --- a/src/test/run-pass/new-style-fixed-length-vec.rs +++ b/src/test/run-pass/new-style-fixed-length-vec.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static FOO: [int, ..3] = [1, 2, 3]; +static FOO: [int; 3] = [1, 2, 3]; pub fn main() { println!("{} {} {}", FOO[0], FOO[1], FOO[2]); diff --git a/src/test/run-pass/nullable-pointer-iotareduction.rs b/src/test/run-pass/nullable-pointer-iotareduction.rs index da1ad094df6..2660de619e9 100644 --- a/src/test/run-pass/nullable-pointer-iotareduction.rs +++ b/src/test/run-pass/nullable-pointer-iotareduction.rs @@ -20,7 +20,7 @@ use std::{option, mem}; // trying to get assert failure messages that at least identify which case // failed. -enum E { Thing(int, T), Nothing((), ((), ()), [i8, ..0]) } +enum E { Thing(int, T), Nothing((), ((), ()), [i8; 0]) } impl E { fn is_none(&self) -> bool { match *self { @@ -54,7 +54,7 @@ macro_rules! check_fancy { check_fancy!($e: $T, |ptr| assert!(*ptr == $e)); }}; ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{ - assert!(E::Nothing::<$T>((), ((), ()), [23i8, ..0]).is_none()); + assert!(E::Nothing::<$T>((), ((), ()), [23i8; 0]).is_none()); let e = $e; let t_ = E::Thing::<$T>(23, e); match t_.get_ref() { diff --git a/src/test/run-pass/nullable-pointer-size.rs b/src/test/run-pass/nullable-pointer-size.rs index 5708310abad..afc22be38b8 100644 --- a/src/test/run-pass/nullable-pointer-size.rs +++ b/src/test/run-pass/nullable-pointer-size.rs @@ -12,7 +12,7 @@ use std::mem; -enum E { Thing(int, T), Nothing((), ((), ()), [i8, ..0]) } +enum E { Thing(int, T), Nothing((), ((), ()), [i8; 0]) } struct S(int, T); // These are macros so we get useful assert messages. diff --git a/src/test/run-pass/order-drop-with-match.rs b/src/test/run-pass/order-drop-with-match.rs index 9a76beac9e5..a866be43a05 100644 --- a/src/test/run-pass/order-drop-with-match.rs +++ b/src/test/run-pass/order-drop-with-match.rs @@ -14,7 +14,7 @@ // in ORDER matching up to when it ran. // Correct order is: matched, inner, outer -static mut ORDER: [uint, ..3] = [0, 0, 0]; +static mut ORDER: [uint; 3] = [0, 0, 0]; static mut INDEX: uint = 0; struct A; diff --git a/src/test/run-pass/out-of-stack-new-thread-no-split.rs b/src/test/run-pass/out-of-stack-new-thread-no-split.rs index 419d9b5d824..674d0dc86da 100644 --- a/src/test/run-pass/out-of-stack-new-thread-no-split.rs +++ b/src/test/run-pass/out-of-stack-new-thread-no-split.rs @@ -27,7 +27,7 @@ pub fn black_box(dummy: T) { unsafe { asm!("" : : "r"(&dummy)) } } #[no_stack_check] fn recurse() { - let buf = [0i, ..10]; + let buf = [0i; 10]; black_box(buf); recurse(); } diff --git a/src/test/run-pass/out-of-stack-no-split.rs b/src/test/run-pass/out-of-stack-no-split.rs index ecb93cc6f8c..79926776abf 100644 --- a/src/test/run-pass/out-of-stack-no-split.rs +++ b/src/test/run-pass/out-of-stack-no-split.rs @@ -28,7 +28,7 @@ pub fn black_box(dummy: T) { unsafe { asm!("" : : "r"(&dummy)) } } #[no_stack_check] fn recurse() { - let buf = [0i, ..10]; + let buf = [0i; 10]; black_box(buf); recurse(); } diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index 81e75ba2cd5..1594cca89e5 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -22,7 +22,7 @@ use std::os; pub fn black_box(dummy: T) { unsafe { asm!("" : : "r"(&dummy)) } } fn silent_recurse() { - let buf = [0i, ..1000]; + let buf = [0i; 1000]; black_box(buf); silent_recurse(); } diff --git a/src/test/run-pass/packed-struct-generic-layout.rs b/src/test/run-pass/packed-struct-generic-layout.rs index 999e4aeeb59..004a3022018 100644 --- a/src/test/run-pass/packed-struct-generic-layout.rs +++ b/src/test/run-pass/packed-struct-generic-layout.rs @@ -20,7 +20,7 @@ struct S { pub fn main() { unsafe { let s = S { a: 0xff_ff_ff_ffu32, b: 1, c: 0xaa_aa_aa_aa as i32 }; - let transd : [u8, .. 9] = mem::transmute(s); + let transd : [u8; 9] = mem::transmute(s); // Don't worry about endianness, the numbers are palindromic. assert!(transd == [0xff, 0xff, 0xff, 0xff, @@ -29,7 +29,7 @@ pub fn main() { let s = S { a: 1u8, b: 2u8, c: 0b10000001_10000001 as i16}; - let transd : [u8, .. 4] = mem::transmute(s); + let transd : [u8; 4] = mem::transmute(s); // Again, no endianness problems. assert!(transd == [1, 2, 0b10000001, 0b10000001]); diff --git a/src/test/run-pass/packed-struct-layout.rs b/src/test/run-pass/packed-struct-layout.rs index b4fbf0820cd..9e94502a92a 100644 --- a/src/test/run-pass/packed-struct-layout.rs +++ b/src/test/run-pass/packed-struct-layout.rs @@ -13,7 +13,7 @@ use std::mem; #[repr(packed)] struct S4 { a: u8, - b: [u8, .. 3], + b: [u8; 3], } #[repr(packed)] @@ -25,11 +25,11 @@ struct S5 { pub fn main() { unsafe { let s4 = S4 { a: 1, b: [2,3,4] }; - let transd : [u8, .. 4] = mem::transmute(s4); + let transd : [u8; 4] = mem::transmute(s4); assert!(transd == [1, 2, 3, 4]); let s5 = S5 { a: 1, b: 0xff_00_00_ff }; - let transd : [u8, .. 5] = mem::transmute(s5); + let transd : [u8; 5] = mem::transmute(s5); // Don't worry about endianness, the u32 is palindromic. assert!(transd == [1, 0xff, 0, 0, 0xff]); } diff --git a/src/test/run-pass/packed-struct-size.rs b/src/test/run-pass/packed-struct-size.rs index 9472fd4ce38..846d51e2e7e 100644 --- a/src/test/run-pass/packed-struct-size.rs +++ b/src/test/run-pass/packed-struct-size.rs @@ -14,7 +14,7 @@ use std::mem; #[repr(packed)] struct S4 { a: u8, - b: [u8, .. 3], + b: [u8; 3], } #[repr(packed)] diff --git a/src/test/run-pass/packed-struct-vec.rs b/src/test/run-pass/packed-struct-vec.rs index 59bb5678b69..d2121aa7752 100644 --- a/src/test/run-pass/packed-struct-vec.rs +++ b/src/test/run-pass/packed-struct-vec.rs @@ -22,9 +22,9 @@ struct Foo { impl Copy for Foo {} pub fn main() { - let foos = [Foo { bar: 1, baz: 2 }, .. 10]; + let foos = [Foo { bar: 1, baz: 2 }; 10]; - assert_eq!(mem::size_of::<[Foo, .. 10]>(), 90); + assert_eq!(mem::size_of::<[Foo; 10]>(), 90); for i in range(0u, 10) { assert_eq!(foos[i], Foo { bar: 1, baz: 2}); diff --git a/src/test/run-pass/packed-tuple-struct-layout.rs b/src/test/run-pass/packed-tuple-struct-layout.rs index 5fb43503ccb..c41d678b0f5 100644 --- a/src/test/run-pass/packed-tuple-struct-layout.rs +++ b/src/test/run-pass/packed-tuple-struct-layout.rs @@ -11,7 +11,7 @@ use std::mem; #[repr(packed)] -struct S4(u8,[u8, .. 3]); +struct S4(u8,[u8; 3]); #[repr(packed)] struct S5(u8,u32); @@ -19,11 +19,11 @@ struct S5(u8,u32); pub fn main() { unsafe { let s4 = S4(1, [2,3,4]); - let transd : [u8, .. 4] = mem::transmute(s4); + let transd : [u8; 4] = mem::transmute(s4); assert!(transd == [1, 2, 3, 4]); let s5 = S5(1, 0xff_00_00_ff); - let transd : [u8, .. 5] = mem::transmute(s5); + let transd : [u8; 5] = mem::transmute(s5); // Don't worry about endianness, the u32 is palindromic. assert!(transd == [1, 0xff, 0, 0, 0xff]); } diff --git a/src/test/run-pass/packed-tuple-struct-size.rs b/src/test/run-pass/packed-tuple-struct-size.rs index 8967b07ca88..a0b88ea53c5 100644 --- a/src/test/run-pass/packed-tuple-struct-size.rs +++ b/src/test/run-pass/packed-tuple-struct-size.rs @@ -12,7 +12,7 @@ use std::mem; #[repr(packed)] -struct S4(u8,[u8, .. 3]); +struct S4(u8,[u8; 3]); #[repr(packed)] struct S5(u8, u32); diff --git a/src/test/run-pass/regions-dependent-addr-of.rs b/src/test/run-pass/regions-dependent-addr-of.rs index 79f8ca48882..41396ef01be 100644 --- a/src/test/run-pass/regions-dependent-addr-of.rs +++ b/src/test/run-pass/regions-dependent-addr-of.rs @@ -18,7 +18,7 @@ struct A { struct B { v1: int, - v2: [int, ..3], + v2: [int; 3], v3: Vec , v4: C, v5: Box, diff --git a/src/test/run-pass/repeat-expr-in-static.rs b/src/test/run-pass/repeat-expr-in-static.rs index 9955673bb0b..a53f1da4ce6 100644 --- a/src/test/run-pass/repeat-expr-in-static.rs +++ b/src/test/run-pass/repeat-expr-in-static.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static FOO: [int, ..4] = [32, ..4]; -static BAR: [int, ..4] = [32, 32, 32, 32]; +static FOO: [int; 4] = [32; 4]; +static BAR: [int; 4] = [32, 32, 32, 32]; pub fn main() { assert!(FOO == BAR); diff --git a/src/test/run-pass/repeated-vector-syntax.rs b/src/test/run-pass/repeated-vector-syntax.rs index 9c369c0d770..0781822cb74 100644 --- a/src/test/run-pass/repeated-vector-syntax.rs +++ b/src/test/run-pass/repeated-vector-syntax.rs @@ -11,8 +11,8 @@ #![feature(slicing_syntax)] pub fn main() { - let x = [ [true], ..512 ]; - let y = [ 0i, ..1 ]; + let x = [ [true]; 512 ]; + let y = [ 0i; 1 ]; print!("["); for xi in x.iter() { diff --git a/src/test/run-pass/uninit-empty-types.rs b/src/test/run-pass/uninit-empty-types.rs index 005205353fc..c2bd738b8a4 100644 --- a/src/test/run-pass/uninit-empty-types.rs +++ b/src/test/run-pass/uninit-empty-types.rs @@ -18,6 +18,6 @@ struct Foo; pub fn main() { unsafe { let _x: Foo = mem::uninitialized(); - let _x: [Foo, ..2] = mem::uninitialized(); + let _x: [Foo; 2] = mem::uninitialized(); } } diff --git a/src/test/run-pass/unsized3.rs b/src/test/run-pass/unsized3.rs index e5e6ce6e76b..271f5817c9e 100644 --- a/src/test/run-pass/unsized3.rs +++ b/src/test/run-pass/unsized3.rs @@ -60,7 +60,7 @@ pub fn main() { unsafe { struct Foo_ { - f: [T, ..3] + f: [T; 3] } let data = box Foo_{f: [1i32, 2, 3] }; @@ -72,7 +72,7 @@ pub fn main() { struct Baz_ { f1: uint, - f2: [u8, ..5], + f2: [u8; 5], } let data = box Baz_{ f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index aa71de2123c..f8eef988561 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -19,7 +19,7 @@ extern { } unsafe fn check(expected: &str, f: |*mut c_char| -> T) { - let mut x = [0 as c_char, ..50]; + let mut x = [0 as c_char; 50]; f(&mut x[0] as *mut c_char); let res = CString::new(&x[0], false); assert_eq!(expected, res.as_str().unwrap()); diff --git a/src/test/run-pass/vec-dst.rs b/src/test/run-pass/vec-dst.rs index d8bf0a5c627..4a36231e72b 100644 --- a/src/test/run-pass/vec-dst.rs +++ b/src/test/run-pass/vec-dst.rs @@ -9,9 +9,9 @@ // except according to those terms. pub fn main() { - // Tests for indexing into box/& [T, ..n] - let x: [int, ..3] = [1, 2, 3]; - let mut x: Box<[int, ..3]> = box x; + // Tests for indexing into box/& [T; n] + let x: [int; 3] = [1, 2, 3]; + let mut x: Box<[int; 3]> = box x; assert!(x[0] == 1); assert!(x[1] == 2); assert!(x[2] == 3); @@ -20,8 +20,8 @@ pub fn main() { assert!(x[1] == 45); assert!(x[2] == 3); - let mut x: [int, ..3] = [1, 2, 3]; - let x: &mut [int, ..3] = &mut x; + let mut x: [int; 3] = [1, 2, 3]; + let x: &mut [int; 3] = &mut x; assert!(x[0] == 1); assert!(x[1] == 2); assert!(x[2] == 3); diff --git a/src/test/run-pass/vec-fixed-length.rs b/src/test/run-pass/vec-fixed-length.rs index 05a7388b5e2..20e1becd008 100644 --- a/src/test/run-pass/vec-fixed-length.rs +++ b/src/test/run-pass/vec-fixed-length.rs @@ -11,17 +11,17 @@ use std::mem::size_of; pub fn main() { - let x: [int, ..4] = [1, 2, 3, 4]; + let x: [int; 4] = [1, 2, 3, 4]; assert_eq!(x[0], 1); assert_eq!(x[1], 2); assert_eq!(x[2], 3); assert_eq!(x[3], 4); - assert_eq!(size_of::<[u8, ..4]>(), 4u); + assert_eq!(size_of::<[u8; 4]>(), 4u); // FIXME #10183 // FIXME #18069 //if cfg!(target_word_size = "64") { - // assert_eq!(size_of::<[u8, ..(1 << 32)]>(), (1u << 32)); + // assert_eq!(size_of::<[u8; (1 << 32)]>(), (1u << 32)); //} } diff --git a/src/test/run-pass/vec-repeat-with-cast.rs b/src/test/run-pass/vec-repeat-with-cast.rs index 18ccd8c96ab..97a443cb3b8 100644 --- a/src/test/run-pass/vec-repeat-with-cast.rs +++ b/src/test/run-pass/vec-repeat-with-cast.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn main() { let _a = [0i, ..1 as uint]; } +pub fn main() { let _a = [0i; 1 as uint]; } diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index c969e66957c..fe89c7532ee 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -14,7 +14,7 @@ use std::rand::{task_rng, Rng, Rand}; const REPEATS: uint = 5; const MAX_LEN: uint = 32; -static drop_counts: [AtomicUint, .. MAX_LEN] = +static drop_counts: [AtomicUint; MAX_LEN] = // FIXME #5244: AtomicUint is not Copy. [ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, -- cgit 1.4.1-3-g733a5 From e0cac488ac6ca16507da390429565b7879f76bb4 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 20 Dec 2014 02:29:19 -0800 Subject: Add parser support for generalized where clauses Implement support in the parser for generalized where clauses, as well as the conversion of ast::WherePredicates to ty::Predicate in `collect.rs`. --- src/librustc/middle/privacy.rs | 1 + src/librustc/middle/resolve_lifetime.rs | 23 +++- src/librustc_resolve/lib.rs | 19 +--- src/librustc_typeck/astconv.rs | 10 +- src/librustc_typeck/collect.rs | 108 +++++++++--------- src/librustdoc/clean/mod.rs | 7 +- src/librustdoc/html/format.rs | 2 +- src/libsyntax/ast.rs | 13 ++- src/libsyntax/ext/deriving/generic/mod.rs | 10 +- src/libsyntax/fold.rs | 15 ++- src/libsyntax/parse/parser.rs | 121 ++++++++++++--------- src/libsyntax/print/pprust.rs | 11 +- src/libsyntax/visit.rs | 11 +- .../region-lifetime-bounds-on-fns-where-clause.rs | 39 +++++++ ...ause-constraints-are-local-for-inherent-impl.rs | 28 +++++ ...-clause-constraints-are-local-for-trait-impl.rs | 33 ++++++ .../where-clause-method-substituion.rs | 30 +++++ .../where-clauses-method-unsatisfied.rs | 30 +++++ .../compile-fail/where-clauses-not-parameter.rs | 13 ++- src/test/pretty/where-clauses.rs | 15 +++ .../run-pass/where-clause-early-bound-lifetimes.rs | 23 ++++ .../run-pass/where-clause-method-substituion.rs | 30 +++++ src/test/run-pass/where-clause-region-outlives.rs | 17 +++ src/test/run-pass/where-clauses-method.rs | 29 +++++ src/test/run-pass/where-clauses-not-parameter.rs | 17 +++ 25 files changed, 505 insertions(+), 150 deletions(-) create mode 100644 src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs create mode 100644 src/test/compile-fail/where-clause-constraints-are-local-for-inherent-impl.rs create mode 100644 src/test/compile-fail/where-clause-constraints-are-local-for-trait-impl.rs create mode 100644 src/test/compile-fail/where-clause-method-substituion.rs create mode 100644 src/test/compile-fail/where-clauses-method-unsatisfied.rs create mode 100644 src/test/pretty/where-clauses.rs create mode 100644 src/test/run-pass/where-clause-early-bound-lifetimes.rs create mode 100644 src/test/run-pass/where-clause-method-substituion.rs create mode 100644 src/test/run-pass/where-clause-region-outlives.rs create mode 100644 src/test/run-pass/where-clauses-method.rs create mode 100644 src/test/run-pass/where-clauses-not-parameter.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 8c566dd288e..7c931700f83 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -1505,6 +1505,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { self.check_ty_param_bound(bound_pred.span, bound) } } + &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { self.visit_ty(&*eq_pred.ty); } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index c8f53df6727..d0fb4f64a6c 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -206,13 +206,19 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } for predicate in generics.where_clause.predicates.iter() { match predicate { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ ident, + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ ref bounded_ty, ref bounds, - span, .. }) => { - self.visit_ident(span, ident); + self.visit_ty(&**bounded_ty); visit::walk_ty_param_bounds_helper(self, bounds); } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bound, + .. }) => { + + self.visit_lifetime_ref(lifetime); + self.visit_lifetime_ref(bound); + } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id, ref path, ref ty, @@ -545,9 +551,18 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec { } for predicate in generics.where_clause.predicates.iter() { match predicate { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounds, ..}) => { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounds, + ref bounded_ty, + ..}) => { + collector.visit_ty(&**bounded_ty); visit::walk_ty_param_bounds_helper(&mut collector, bounds); } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bound, + ..}) => { + collector.visit_lifetime_ref(lifetime); + collector.visit_lifetime_ref(bound); + } &ast::WherePredicate::EqPredicate(_) => unimplemented!() } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e1708be30d9..99f0a6cdfc3 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4360,27 +4360,14 @@ impl<'a> Resolver<'a> { for predicate in where_clause.predicates.iter() { match predicate { &ast::WherePredicate::BoundPredicate(ref bound_pred) => { - match self.resolve_identifier(bound_pred.ident, - TypeNS, - true, - bound_pred.span) { - Some((def @ DefTyParam(..), last_private)) => { - self.record_def(bound_pred.id, (def, last_private)); - } - _ => { - self.resolve_error( - bound_pred.span, - format!("undeclared type parameter `{}`", - token::get_ident( - bound_pred.ident)).as_slice()); - } - } + self.resolve_type(&*bound_pred.bounded_ty); for bound in bound_pred.bounds.iter() { - self.resolve_type_parameter_bound(bound_pred.id, bound, + self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound, TraitBoundingTypeParameter); } } + &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) { Some((def @ DefTyParam(..), last_private)) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4f4bebabead..175763c874e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1437,11 +1437,8 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( ast_bounds: &[ast::TyParamBound]) -> ty::ExistentialBounds { - let ast_bound_refs: Vec<&ast::TyParamBound> = - ast_bounds.iter().collect(); - let partitioned_bounds = - partition_bounds(this.tcx(), span, ast_bound_refs.as_slice()); + partition_bounds(this.tcx(), span, ast_bounds); conv_existential_bounds_from_partitioned_bounds( this, rscope, span, principal_trait_ref, partitioned_bounds) @@ -1455,7 +1452,6 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>( -> Ty<'tcx> where AC: AstConv<'tcx>, RS:RegionScope { - let ast_bounds: Vec<&ast::TyParamBound> = ast_bounds.iter().collect(); let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]); let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) { @@ -1620,14 +1616,14 @@ pub struct PartitionedBounds<'a> { /// general trait bounds, and region bounds. pub fn partition_bounds<'a>(tcx: &ty::ctxt, _span: Span, - ast_bounds: &'a [&ast::TyParamBound]) + ast_bounds: &'a [ast::TyParamBound]) -> PartitionedBounds<'a> { let mut builtin_bounds = ty::empty_builtin_bounds(); let mut region_bounds = Vec::new(); let mut trait_bounds = Vec::new(); let mut trait_def_ids = DefIdMap::new(); - for &ast_bound in ast_bounds.iter() { + for ast_bound in ast_bounds.iter() { match *ast_bound { ast::TraitTyParamBound(ref b) => { match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4612acb04b2..11c89f248b2 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1364,8 +1364,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, self_param_ty, bounds.as_slice(), unbound, - it.span, - &generics.where_clause); + it.span); let substs = mk_item_substs(ccx, &ty_generics); let trait_def = Rc::new(ty::TraitDef { @@ -1619,7 +1618,6 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, subst::AssocSpace, &associated_type.ty_param, generics.types.len(subst::AssocSpace), - &ast_generics.where_clause, Some(local_def(trait_id))); ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id, def.clone()); @@ -1774,7 +1772,6 @@ fn ty_generics<'tcx,AC>(this: &AC, space, param, i, - where_clause, None); debug!("ty_generics: def for type param: {}, {}", def.repr(this.tcx()), @@ -1798,6 +1795,52 @@ fn ty_generics<'tcx,AC>(this: &AC, // into the predicates list. This is currently kind of non-DRY. create_predicates(this.tcx(), &mut result, space); + // Add the bounds not associated with a type parameter + for predicate in where_clause.predicates.iter() { + match predicate { + &ast::WherePredicate::BoundPredicate(ref bound_pred) => { + let ty = ast_ty_to_ty(this, &ExplicitRscope, &*bound_pred.bounded_ty); + + for bound in bound_pred.bounds.iter() { + match bound { + &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref) => { + let trait_ref = astconv::instantiate_poly_trait_ref( + this, + &ExplicitRscope, + //@jroesch: for now trait_ref, poly_trait_ref? + poly_trait_ref, + Some(ty), + AllowEqConstraints::Allow + ); + + result.predicates.push(space, ty::Predicate::Trait(trait_ref)); + } + + &ast::TyParamBound::RegionTyParamBound(ref lifetime) => { + let region = ast_region_to_region(this.tcx(), lifetime); + let pred = ty::Binder(ty::OutlivesPredicate(ty, region)); + result.predicates.push(space, ty::Predicate::TypeOutlives(pred)) + } + } + } + } + + &ast::WherePredicate::RegionPredicate(ref region_pred) => { + let r1 = ast_region_to_region(this.tcx(), ®ion_pred.lifetime); + let r2 = ast_region_to_region(this.tcx(), ®ion_pred.bound); + let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); + result.predicates.push(space, ty::Predicate::RegionOutlives(pred)) + } + + &ast::WherePredicate::EqPredicate(ref eq_pred) => { + // FIXME(#20041) + this.tcx().sess.span_bug(eq_pred.span, + "Equality constraints are not yet \ + implemented (#20041)") + } + } + } + return result; fn create_type_parameters_for_associated_types<'tcx, AC>( @@ -1915,7 +1958,6 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, space: subst::ParamSpace, param: &ast::TyParam, index: uint, - where_clause: &ast::WhereClause, associated_with: Option) -> ty::TypeParameterDef<'tcx> where AC: AstConv<'tcx> @@ -1931,8 +1973,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, param_ty, param.bounds.as_slice(), ¶m.unbound, - param.span, - where_clause); + param.span); let default = match param.default { None => None, Some(ref path) => { @@ -1977,15 +2018,13 @@ fn compute_bounds<'tcx,AC>(this: &AC, param_ty: ty::ParamTy, ast_bounds: &[ast::TyParamBound], unbound: &Option, - span: Span, - where_clause: &ast::WhereClause) + span: Span) -> ty::ParamBounds<'tcx> where AC: AstConv<'tcx> { let mut param_bounds = conv_param_bounds(this, span, param_ty, - ast_bounds, - where_clause); + ast_bounds); add_unsized_bound(this, @@ -2031,16 +2070,14 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>, fn conv_param_bounds<'tcx,AC>(this: &AC, span: Span, param_ty: ty::ParamTy, - ast_bounds: &[ast::TyParamBound], - where_clause: &ast::WhereClause) + ast_bounds: &[ast::TyParamBound]) -> ty::ParamBounds<'tcx> - where AC: AstConv<'tcx> { - let all_bounds = - merge_param_bounds(this.tcx(), param_ty, ast_bounds, where_clause); + where AC: AstConv<'tcx> +{ let astconv::PartitionedBounds { builtin_bounds, trait_bounds, region_bounds } = - astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice()); + astconv::partition_bounds(this.tcx(), span, ast_bounds.as_slice()); let trait_bounds: Vec> = trait_bounds.into_iter() .map(|bound| { @@ -2062,43 +2099,6 @@ fn conv_param_bounds<'tcx,AC>(this: &AC, } } -/// Merges the bounds declared on a type parameter with those found from where clauses into a -/// single list. -fn merge_param_bounds<'a>(tcx: &ty::ctxt, - param_ty: ty::ParamTy, - ast_bounds: &'a [ast::TyParamBound], - where_clause: &'a ast::WhereClause) - -> Vec<&'a ast::TyParamBound> { - let mut result = Vec::new(); - - for ast_bound in ast_bounds.iter() { - result.push(ast_bound); - } - - for predicate in where_clause.predicates.iter() { - match predicate { - &ast::WherePredicate::BoundPredicate(ref bound_pred) => { - let predicate_param_id = - tcx.def_map - .borrow() - .get(&bound_pred.id) - .expect("merge_param_bounds(): resolve didn't resolve the \ - type parameter identifier in a `where` clause") - .def_id(); - if param_ty.def_id != predicate_param_id { - continue - } - for bound in bound_pred.bounds.iter() { - result.push(bound); - } - } - &ast::WherePredicate::EqPredicate(_) => panic!("not implemented") - } - } - - result -} - pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, decl: &ast::FnDecl, def_id: ast::DefId, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ed923202795..3e8bf9bd4fd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -693,7 +693,7 @@ impl Clean> for ty::Region { #[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct WherePredicate { - pub name: String, + pub ty: Type, pub bounds: Vec } @@ -702,11 +702,12 @@ impl Clean for ast::WherePredicate { match *self { ast::WherePredicate::BoundPredicate(ref wbp) => { WherePredicate { - name: wbp.ident.clean(cx), + ty: wbp.bounded_ty.clean(cx), bounds: wbp.bounds.clean(cx) } } - ast::WherePredicate::EqPredicate(_) => { + // FIXME(#20048) + _ => { unimplemented!(); } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5572bcb6aa8..e01cbbc812b 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -129,7 +129,7 @@ impl<'a> fmt::Show for WhereClause<'a> { try!(f.write(", ".as_bytes())); } let bounds = pred.bounds.as_slice(); - try!(write!(f, "{}: {}", pred.name, TyParamBounds(bounds))); + try!(write!(f, "{}: {}", pred.ty, TyParamBounds(bounds))); } Ok(()) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index be8f32bc4d5..13ea5da66c8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -415,17 +415,26 @@ pub struct WhereClause { #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum WherePredicate { BoundPredicate(WhereBoundPredicate), + RegionPredicate(WhereRegionPredicate), EqPredicate(WhereEqPredicate) } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct WhereBoundPredicate { - pub id: NodeId, pub span: Span, - pub ident: Ident, + pub bounded_ty: P, pub bounds: OwnedSlice, } +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct WhereRegionPredicate { + pub span: Span, + pub lifetime: Lifetime, + pub bound: Lifetime +} + +impl Copy for WhereRegionPredicate {} + #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct WhereEqPredicate { pub id: NodeId, diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index b31758e2d2a..c40ccaa31a5 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -426,12 +426,18 @@ impl<'a> TraitDef<'a> { match *clause { ast::WherePredicate::BoundPredicate(ref wb) => { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - id: ast::DUMMY_NODE_ID, span: self.span, - ident: wb.ident, + bounded_ty: wb.bounded_ty.clone(), bounds: OwnedSlice::from_vec(wb.bounds.iter().map(|b| b.clone()).collect()) }) } + ast::WherePredicate::RegionPredicate(ref rb) => { + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + span: self.span, + lifetime: rb.lifetime, + bound: rb.bound + }) + } ast::WherePredicate::EqPredicate(ref we) => { ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 10860ee5e01..dd1e8b73f36 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -814,17 +814,24 @@ pub fn noop_fold_where_predicate( fld: &mut T) -> WherePredicate { match pred { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{id, - ident, + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{bounded_ty, bounds, span}) => { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - id: fld.new_id(id), - ident: fld.fold_ident(ident), + bounded_ty: fld.fold_ty(bounded_ty), bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), span: fld.new_span(span) }) } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{lifetime, + bound, + span}) => { + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + span: fld.new_span(span), + lifetime: fld.fold_lifetime(lifetime), + bound: fld.fold_lifetime(bound) + }) + } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, path, ty, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3ad224b93ce..64bcf7dbdd1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1497,9 +1497,6 @@ impl<'a> Parser<'a> { } /// Parse a type. - /// - /// The second parameter specifies whether the `+` binary operator is - /// allowed in the type grammar. pub fn parse_ty(&mut self) -> P { maybe_whole!(no_clone self, NtTy); @@ -4179,6 +4176,10 @@ impl<'a> Parser<'a> { } /// Parses an optional `where` clause and places it in `generics`. + /// + /// ``` + /// where T : Trait + 'b, 'a : 'b + /// ``` fn parse_where_clause(&mut self, generics: &mut ast::Generics) { if !self.eat_keyword(keywords::Where) { return @@ -4187,58 +4188,80 @@ impl<'a> Parser<'a> { let mut parsed_something = false; loop { let lo = self.span.lo; - let path = match self.token { - token::Ident(..) => self.parse_path(NoTypesAllowed), - _ => break, - }; + match self.token { + token::OpenDelim(token::Brace) => { + break + } - if self.eat(&token::Colon) { - let bounds = self.parse_ty_param_bounds(); - let hi = self.span.hi; - let span = mk_sp(lo, hi); + token::Lifetime(..) => { + let bounded_lifetime = + self.parse_lifetime(); - if bounds.len() == 0 { - self.span_err(span, - "each predicate in a `where` clause must have \ - at least one bound in it"); + self.eat(&token::Colon); + + // FIXME(#20049) + let bounding_lifetime = + self.parse_lifetime(); + + let hi = self.span.hi; + let span = mk_sp(lo, hi); + + generics.where_clause.predicates.push(ast::WherePredicate::RegionPredicate( + ast::WhereRegionPredicate { + span: span, + lifetime: bounded_lifetime, + bound: bounding_lifetime + } + )); + + parsed_something = true; } - let ident = match ast_util::path_to_ident(&path) { - Some(ident) => ident, - None => { - self.span_err(path.span, "expected a single identifier \ - in bound where clause"); - break; - } - }; + _ => { + let bounded_ty = self.parse_ty(); - generics.where_clause.predicates.push( - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - id: ast::DUMMY_NODE_ID, - span: span, - ident: ident, - bounds: bounds, - })); - parsed_something = true; - } else if self.eat(&token::Eq) { - let ty = self.parse_ty(); - let hi = self.span.hi; - let span = mk_sp(lo, hi); - generics.where_clause.predicates.push( - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - id: ast::DUMMY_NODE_ID, - span: span, - path: path, - ty: ty, - })); - parsed_something = true; - // FIXME(#18433) - self.span_err(span, "equality constraints are not yet supported in where clauses"); - } else { - let last_span = self.last_span; - self.span_err(last_span, + if self.eat(&token::Colon) { + let bounds = self.parse_ty_param_bounds(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); + + if bounds.len() == 0 { + self.span_err(span, + "each predicate in a `where` clause must have \ + at least one bound in it"); + } + + generics.where_clause.predicates.push(ast::WherePredicate::BoundPredicate( + ast::WhereBoundPredicate { + span: span, + bounded_ty: bounded_ty, + bounds: bounds, + })); + + parsed_something = true; + } else if self.eat(&token::Eq) { + // let ty = self.parse_ty(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); + // generics.where_clause.predicates.push( + // ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + // id: ast::DUMMY_NODE_ID, + // span: span, + // path: panic!("NYI"), //bounded_ty, + // ty: ty, + // })); + // parsed_something = true; + // // FIXME(#18433) + self.span_err(span, + "equality constraints are not yet supported \ + in where clauses (#20041)"); + } else { + let last_span = self.last_span; + self.span_err(last_span, "unexpected token in `where` clause"); - } + } + } + }; if !self.eat(&token::Comma) { break diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d2cc0cba317..d619a386664 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2437,12 +2437,19 @@ impl<'a> State<'a> { } match predicate { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ident, + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounded_ty, ref bounds, ..}) => { - try!(self.print_ident(ident)); + try!(self.print_type(&**bounded_ty)); try!(self.print_bounds(":", bounds.as_slice())); } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bound, + ..}) => { + try!(self.print_lifetime(lifetime)); + try!(word(&mut self.s, ":")); + try!(self.print_lifetime(bound)); + } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { try!(self.print_path(path, false)); try!(space(&mut self.s)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index b89e9a59349..c2a7a0316c7 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -583,13 +583,18 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics walk_lifetime_decls_helper(visitor, &generics.lifetimes); for predicate in generics.where_clause.predicates.iter() { match predicate { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{span, - ident, + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounded_ty, ref bounds, ..}) => { - visitor.visit_ident(span, ident); + visitor.visit_ty(&**bounded_ty); walk_ty_param_bounds_helper(visitor, bounds); } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bound, + ..}) => { + visitor.visit_lifetime_ref(lifetime); + visitor.visit_lifetime_ref(bound); + } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, ref path, ref ty, diff --git a/src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs b/src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs new file mode 100644 index 00000000000..381144f2599 --- /dev/null +++ b/src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs @@ -0,0 +1,39 @@ +// Copyright 2014 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. + +fn a<'a, 'b>(x: &mut &'a int, y: &mut &'b int) where 'b: 'a { + // Note: this is legal because of the `'b:'a` declaration. + *x = *y; +} + +fn b<'a, 'b>(x: &mut &'a int, y: &mut &'b int) { + // Illegal now because there is no `'b:'a` declaration. + *x = *y; //~ ERROR mismatched types +} + +fn c<'a,'b>(x: &mut &'a int, y: &mut &'b int) { + // Here we try to call `foo` but do not know that `'a` and `'b` are + // related as required. + a(x, y); //~ ERROR cannot infer +} + +fn d() { + // 'a and 'b are early bound in the function `a` because they appear + // inconstraints: + let _: fn(&mut &int, &mut &int) = a; //~ ERROR mismatched types +} + +fn e() { + // 'a and 'b are late bound in the function `b` because there are + // no constraints: + let _: fn(&mut &int, &mut &int) = b; +} + +fn main() { } diff --git a/src/test/compile-fail/where-clause-constraints-are-local-for-inherent-impl.rs b/src/test/compile-fail/where-clause-constraints-are-local-for-inherent-impl.rs new file mode 100644 index 00000000000..8d72e260a18 --- /dev/null +++ b/src/test/compile-fail/where-clause-constraints-are-local-for-inherent-impl.rs @@ -0,0 +1,28 @@ +// Copyright 2014 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. + +fn require_copy(x: T) {} + +struct Foo { x: T } + +// Ensure constraints are only attached to methods locally +impl Foo { + fn needs_copy(self) where T: Copy { + require_copy(self.x); + + } + + fn fails_copy(self) { + require_copy(self.x); + //~^ ERROR the trait `core::kinds::Copy` is not implemented for the type `T` + } +} + +fn main() {} diff --git a/src/test/compile-fail/where-clause-constraints-are-local-for-trait-impl.rs b/src/test/compile-fail/where-clause-constraints-are-local-for-trait-impl.rs new file mode 100644 index 00000000000..096b53a1ea6 --- /dev/null +++ b/src/test/compile-fail/where-clause-constraints-are-local-for-trait-impl.rs @@ -0,0 +1,33 @@ +// Copyright 2014 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. + +fn require_copy(x: T) {} + +struct Bar { x: T } + +trait Foo { + fn needs_copy(self) where T: Copy; + fn fails_copy(self); +} + +// Ensure constraints are only attached to methods locally +impl Foo for Bar { + fn needs_copy(self) where T: Copy { + require_copy(self.x); + + } + + fn fails_copy(self) { + require_copy(self.x); + //~^ ERROR the trait `core::kinds::Copy` is not implemented for the type `T` + } +} + +fn main() {} diff --git a/src/test/compile-fail/where-clause-method-substituion.rs b/src/test/compile-fail/where-clause-method-substituion.rs new file mode 100644 index 00000000000..2fe7ab9577b --- /dev/null +++ b/src/test/compile-fail/where-clause-method-substituion.rs @@ -0,0 +1,30 @@ +// Copyright 2014 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 {} + +trait Bar { + fn method(&self) where A: Foo; +} + +struct S; +struct X; + +// Remove this impl causing the below resolution to fail // impl Foo for X {} + +impl Bar for int { + fn method(&self) where X: Foo { + } +} + +fn main() { + 1.method::(); + //~^ ERROR the trait `Foo<_>` is not implemented for the type `X` +} \ No newline at end of file diff --git a/src/test/compile-fail/where-clauses-method-unsatisfied.rs b/src/test/compile-fail/where-clauses-method-unsatisfied.rs new file mode 100644 index 00000000000..a74095bcdf1 --- /dev/null +++ b/src/test/compile-fail/where-clauses-method-unsatisfied.rs @@ -0,0 +1,30 @@ +// Copyright 2014 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. + +// Test that a where clause attached to a method allows us to add +// additional constraints to a parameter out of scope. + +struct Foo { + value: T +} + +struct Bar; // does not implement Eq + +impl Foo { + fn equals(&self, u: &Foo) -> bool where T : Eq { + self.value == u.value + } +} + +fn main() { + let x = Foo { value: Bar }; + x.equals(&x); + //~^ ERROR the trait `core::cmp::Eq` is not not implemented +} diff --git a/src/test/compile-fail/where-clauses-not-parameter.rs b/src/test/compile-fail/where-clauses-not-parameter.rs index 2817aa16e8e..9e81703787f 100644 --- a/src/test/compile-fail/where-clauses-not-parameter.rs +++ b/src/test/compile-fail/where-clauses-not-parameter.rs @@ -8,10 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn equal(_: &T, _: &T) -> bool where int : Eq { - //~^ ERROR undeclared type parameter +struct A; + +trait U {} + +// impl U for A {} + +fn equal(_: &T, _: &T) -> bool where A : U { + true } fn main() { + equal(&0i, &0i); + //~^ ERROR the trait `U` is not implemented for the type `A` } - diff --git a/src/test/pretty/where-clauses.rs b/src/test/pretty/where-clauses.rs new file mode 100644 index 00000000000..6703c35234b --- /dev/null +++ b/src/test/pretty/where-clauses.rs @@ -0,0 +1,15 @@ +// 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. + +// pp-exact + +fn f int where T : 'a, 'a: 'b, T: Eq { + 0 +} diff --git a/src/test/run-pass/where-clause-early-bound-lifetimes.rs b/src/test/run-pass/where-clause-early-bound-lifetimes.rs new file mode 100644 index 00000000000..cade99b83a2 --- /dev/null +++ b/src/test/run-pass/where-clause-early-bound-lifetimes.rs @@ -0,0 +1,23 @@ +// Copyright 2014 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 TheTrait { } + +impl TheTrait for &'static int { } + +fn foo<'a,T>(_: &'a T) where &'a T : TheTrait { } + +fn bar(_: &'static T) where &'static T : TheTrait { } + +fn main() { + static x: int = 1; + foo(&x); + bar(&x); +} diff --git a/src/test/run-pass/where-clause-method-substituion.rs b/src/test/run-pass/where-clause-method-substituion.rs new file mode 100644 index 00000000000..b391df8500b --- /dev/null +++ b/src/test/run-pass/where-clause-method-substituion.rs @@ -0,0 +1,30 @@ +// Copyright 2014 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 {} + +trait Bar { + fn method(&self) where A: Foo; +} + +struct S; +struct X; + +impl Foo for X {} + +impl Bar for int { + fn method(&self) where X: Foo { + } +} + +fn main() { + 1.method::(); +} + diff --git a/src/test/run-pass/where-clause-region-outlives.rs b/src/test/run-pass/where-clause-region-outlives.rs new file mode 100644 index 00000000000..1ecb4b6c2dc --- /dev/null +++ b/src/test/run-pass/where-clause-region-outlives.rs @@ -0,0 +1,17 @@ +// Copyright 2014 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. + +struct A<'a, 'b> where 'a : 'b { x: &'a int, y: &'b int } + +fn main() { + let x = 1i; + let y = 1i; + let a = A { x: &x, y: &y }; +} diff --git a/src/test/run-pass/where-clauses-method.rs b/src/test/run-pass/where-clauses-method.rs new file mode 100644 index 00000000000..2b87bcd4b39 --- /dev/null +++ b/src/test/run-pass/where-clauses-method.rs @@ -0,0 +1,29 @@ +// Copyright 2014 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. + +// Test that a where clause attached to a method allows us to add +// additional constraints to a parameter out of scope. + +struct Foo { + value: T +} + +impl Foo { + fn equals(&self, u: &Foo) -> bool where T : Eq { + self.value == u.value + } +} + +fn main() { + let x = Foo { value: 1i }; + let y = Foo { value: 2i }; + println!("{}", x.equals(&x)); + println!("{}", x.equals(&y)); +} diff --git a/src/test/run-pass/where-clauses-not-parameter.rs b/src/test/run-pass/where-clauses-not-parameter.rs new file mode 100644 index 00000000000..bc5fc388ca1 --- /dev/null +++ b/src/test/run-pass/where-clauses-not-parameter.rs @@ -0,0 +1,17 @@ +// Copyright 2014 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. + +fn equal(_: &T, _: &T) -> bool where int : Eq { + true +} + +fn main() { + equal(&0i, &0i); +} -- cgit 1.4.1-3-g733a5 From d87b308b67ab070d67ab66062b33f64e5bc621e4 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 20 Dec 2014 02:48:43 -0800 Subject: Add support for multiple region bounds in where clauses --- src/librustc/middle/resolve_lifetime.rs | 13 ++++--- src/librustc_typeck/collect.rs | 8 +++-- src/libsyntax/ast.rs | 4 +-- src/libsyntax/ext/deriving/generic/mod.rs | 2 +- src/libsyntax/fold.rs | 4 +-- src/libsyntax/parse/parser.rs | 7 ++-- src/libsyntax/print/pprust.rs | 11 ++++-- src/libsyntax/visit.rs | 7 ++-- ...multiple-lifetime-bounds-on-fns-where-clause.rs | 41 ++++++++++++++++++++++ .../where-clause-method-substituion.rs | 4 +-- .../where-clauses-method-unsatisfied.rs | 2 +- 11 files changed, 79 insertions(+), 24 deletions(-) create mode 100644 src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index d0fb4f64a6c..be191801626 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -213,11 +213,13 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { visit::walk_ty_param_bounds_helper(self, bounds); } &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, - ref bound, + ref bounds, .. }) => { self.visit_lifetime_ref(lifetime); - self.visit_lifetime_ref(bound); + for bound in bounds.iter() { + self.visit_lifetime_ref(bound); + } } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id, ref path, @@ -558,10 +560,13 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec { visit::walk_ty_param_bounds_helper(&mut collector, bounds); } &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, - ref bound, + ref bounds, ..}) => { collector.visit_lifetime_ref(lifetime); - collector.visit_lifetime_ref(bound); + + for bound in bounds.iter() { + collector.visit_lifetime_ref(bound); + } } &ast::WherePredicate::EqPredicate(_) => unimplemented!() } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 11c89f248b2..3f59b50337f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1827,9 +1827,11 @@ fn ty_generics<'tcx,AC>(this: &AC, &ast::WherePredicate::RegionPredicate(ref region_pred) => { let r1 = ast_region_to_region(this.tcx(), ®ion_pred.lifetime); - let r2 = ast_region_to_region(this.tcx(), ®ion_pred.bound); - let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); - result.predicates.push(space, ty::Predicate::RegionOutlives(pred)) + for bound in region_pred.bounds.iter() { + let r2 = ast_region_to_region(this.tcx(), bound); + let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); + result.predicates.push(space, ty::Predicate::RegionOutlives(pred)) + } } &ast::WherePredicate::EqPredicate(ref eq_pred) => { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 13ea5da66c8..440e11e385f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -430,11 +430,9 @@ pub struct WhereBoundPredicate { pub struct WhereRegionPredicate { pub span: Span, pub lifetime: Lifetime, - pub bound: Lifetime + pub bounds: Vec, } -impl Copy for WhereRegionPredicate {} - #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct WhereEqPredicate { pub id: NodeId, diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index c40ccaa31a5..d8de3d2db97 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -435,7 +435,7 @@ impl<'a> TraitDef<'a> { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { span: self.span, lifetime: rb.lifetime, - bound: rb.bound + bounds: rb.bounds.iter().map(|b| b.clone()).collect() }) } ast::WherePredicate::EqPredicate(ref we) => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index dd1e8b73f36..86df5883864 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -824,12 +824,12 @@ pub fn noop_fold_where_predicate( }) } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{lifetime, - bound, + bounds, span}) => { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { span: fld.new_span(span), lifetime: fld.fold_lifetime(lifetime), - bound: fld.fold_lifetime(bound) + bounds: bounds.move_map(|bound| fld.fold_lifetime(bound)) }) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 64bcf7dbdd1..f8b47e0405f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4199,9 +4199,8 @@ impl<'a> Parser<'a> { self.eat(&token::Colon); - // FIXME(#20049) - let bounding_lifetime = - self.parse_lifetime(); + let bounds = + self.parse_lifetimes(token::BinOp(token::Plus)); let hi = self.span.hi; let span = mk_sp(lo, hi); @@ -4210,7 +4209,7 @@ impl<'a> Parser<'a> { ast::WhereRegionPredicate { span: span, lifetime: bounded_lifetime, - bound: bounding_lifetime + bounds: bounds } )); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d619a386664..f27a476dbdd 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2444,11 +2444,18 @@ impl<'a> State<'a> { try!(self.print_bounds(":", bounds.as_slice())); } &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, - ref bound, + ref bounds, ..}) => { try!(self.print_lifetime(lifetime)); try!(word(&mut self.s, ":")); - try!(self.print_lifetime(bound)); + + for (i, bound) in bounds.iter().enumerate() { + try!(self.print_lifetime(bound)); + + if i != 0 { + try!(word(&mut self.s, ":")); + } + } } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { try!(self.print_path(path, false)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index c2a7a0316c7..9938feb171e 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -590,10 +590,13 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics walk_ty_param_bounds_helper(visitor, bounds); } &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, - ref bound, + ref bounds, ..}) => { visitor.visit_lifetime_ref(lifetime); - visitor.visit_lifetime_ref(bound); + + for bound in bounds.iter() { + visitor.visit_lifetime_ref(bound); + } } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, ref path, diff --git a/src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs new file mode 100644 index 00000000000..a03911e1d0e --- /dev/null +++ b/src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -0,0 +1,41 @@ +// Copyright 2014 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. + +fn a<'a, 'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) where 'b: 'a + 'c { + // Note: this is legal because of the `'b:'a` declaration. + *x = *y; + *z = *y; +} + +fn b<'a, 'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) { + // Illegal now because there is no `'b:'a` declaration. + *x = *y; //~ ERROR mismatched types + *z = *y; //~ ERROR mismatched types +} + +fn c<'a,'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) { + // Here we try to call `foo` but do not know that `'a` and `'b` are + // related as required. + a(x, y, z); //~ ERROR cannot infer +} + +fn d() { + // 'a and 'b are early bound in the function `a` because they appear + // inconstraints: + let _: fn(&mut &int, &mut &int, &mut &int) = a; //~ ERROR mismatched types +} + +fn e() { + // 'a and 'b are late bound in the function `b` because there are + // no constraints: + let _: fn(&mut &int, &mut &int, &mut &int) = b; +} + +fn main() { } diff --git a/src/test/compile-fail/where-clause-method-substituion.rs b/src/test/compile-fail/where-clause-method-substituion.rs index 2fe7ab9577b..40d2df45488 100644 --- a/src/test/compile-fail/where-clause-method-substituion.rs +++ b/src/test/compile-fail/where-clause-method-substituion.rs @@ -26,5 +26,5 @@ impl Bar for int { fn main() { 1.method::(); - //~^ ERROR the trait `Foo<_>` is not implemented for the type `X` -} \ No newline at end of file + //~^ ERROR the trait `Foo` is not implemented for the type `X` +} diff --git a/src/test/compile-fail/where-clauses-method-unsatisfied.rs b/src/test/compile-fail/where-clauses-method-unsatisfied.rs index a74095bcdf1..e5b54582e4e 100644 --- a/src/test/compile-fail/where-clauses-method-unsatisfied.rs +++ b/src/test/compile-fail/where-clauses-method-unsatisfied.rs @@ -26,5 +26,5 @@ impl Foo { fn main() { let x = Foo { value: Bar }; x.equals(&x); - //~^ ERROR the trait `core::cmp::Eq` is not not implemented + //~^ ERROR the trait `core::cmp::Eq` is not implemented for the type `Bar` } -- cgit 1.4.1-3-g733a5 From 082bfde412176249dc7328e771a2a15d202824cf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 10 Dec 2014 19:46:38 -0800 Subject: Fallout of std::str stabilization --- src/compiletest/compiletest.rs | 6 +- src/compiletest/header.rs | 6 +- src/compiletest/runtest.rs | 2 +- src/doc/guide.md | 24 +- src/doc/reference.md | 2 +- src/libcollections/lib.rs | 4 +- src/libcollections/str.rs | 123 ++++++---- src/libcollections/string.rs | 22 +- src/libcore/option.rs | 6 +- src/libcore/result.rs | 2 +- src/libcore/str.rs | 36 ++- src/libcoretest/lib.rs | 1 + src/libcoretest/str.rs | 2 +- src/libfmt_macros/lib.rs | 21 +- src/libgetopts/lib.rs | 61 +++-- src/libgraphviz/lib.rs | 14 +- src/liblog/directive.rs | 2 +- src/liblog/lib.rs | 8 +- src/libregex/parse.rs | 57 +++-- src/libregex/re.rs | 28 +-- src/librustc/lint/builtin.rs | 54 ++--- src/librustc/lint/context.rs | 56 ++--- src/librustc/metadata/creader.rs | 40 ++-- src/librustc/metadata/csearch.rs | 2 +- src/librustc/metadata/decoder.rs | 6 +- src/librustc/metadata/encoder.rs | 88 +++---- src/librustc/metadata/loader.rs | 36 +-- src/librustc/metadata/tydecode.rs | 12 +- src/librustc/middle/astconv_util.rs | 2 +- src/librustc/middle/astencode.rs | 6 +- src/librustc/middle/cfg/construct.rs | 6 +- src/librustc/middle/cfg/graphviz.rs | 5 +- src/librustc/middle/check_loop.rs | 6 +- src/librustc/middle/check_match.rs | 18 +- src/librustc/middle/check_static.rs | 6 +- src/librustc/middle/check_static_recursion.rs | 2 +- src/librustc/middle/const_eval.rs | 8 +- src/librustc/middle/dataflow.rs | 6 +- src/librustc/middle/dependency_format.rs | 6 +- src/librustc/middle/expr_use_visitor.rs | 8 +- src/librustc/middle/infer/combine.rs | 4 +- src/librustc/middle/infer/error_reporting.rs | 74 +++--- src/librustc/middle/infer/higher_ranked/mod.rs | 4 +- src/librustc/middle/infer/mod.rs | 2 +- .../middle/infer/region_inference/graphviz.rs | 2 +- src/librustc/middle/infer/region_inference/mod.rs | 16 +- src/librustc/middle/liveness.rs | 12 +- src/librustc/middle/mem_categorization.rs | 8 +- src/librustc/middle/privacy.rs | 12 +- src/librustc/middle/reachable.rs | 10 +- src/librustc/middle/resolve_lifetime.rs | 6 +- src/librustc/middle/subst.rs | 4 +- src/librustc/middle/traits/coherence.rs | 2 +- src/librustc/middle/traits/select.rs | 15 +- src/librustc/middle/ty.rs | 68 +++--- src/librustc/plugin/load.rs | 6 +- src/librustc/session/config.rs | 58 ++--- src/librustc/session/mod.rs | 4 +- src/librustc/util/common.rs | 3 +- src/librustc/util/ppaux.rs | 24 +- src/librustc_back/archive.rs | 42 ++-- src/librustc_back/rpath.rs | 16 +- src/librustc_back/svh.rs | 4 +- src/librustc_back/target/mod.rs | 4 +- src/librustc_borrowck/borrowck/check_loans.rs | 42 ++-- src/librustc_borrowck/borrowck/fragments.rs | 38 +-- src/librustc_borrowck/borrowck/gather_loans/mod.rs | 2 +- .../borrowck/gather_loans/move_error.rs | 8 +- src/librustc_borrowck/borrowck/mod.rs | 38 +-- src/librustc_borrowck/graphviz.rs | 4 +- src/librustc_driver/driver.rs | 30 +-- src/librustc_driver/lib.rs | 28 +-- src/librustc_driver/pretty.rs | 30 +-- src/librustc_resolve/lib.rs | 126 +++++----- src/librustc_trans/back/link.rs | 128 +++++----- src/librustc_trans/back/lto.rs | 20 +- src/librustc_trans/back/write.rs | 88 +++---- src/librustc_trans/save/mod.rs | 146 ++++++------ src/librustc_trans/save/recorder.rs | 22 +- src/librustc_trans/save/span_utils.rs | 4 +- src/librustc_trans/trans/_match.rs | 36 +-- src/librustc_trans/trans/adt.rs | 58 ++--- src/librustc_trans/trans/asm.rs | 14 +- src/librustc_trans/trans/base.rs | 104 ++++----- src/librustc_trans/trans/builder.rs | 8 +- src/librustc_trans/trans/cabi.rs | 4 +- src/librustc_trans/trans/callee.rs | 12 +- src/librustc_trans/trans/cleanup.rs | 10 +- src/librustc_trans/trans/closure.rs | 22 +- src/librustc_trans/trans/common.rs | 14 +- src/librustc_trans/trans/consts.rs | 44 ++-- src/librustc_trans/trans/context.rs | 6 +- src/librustc_trans/trans/controlflow.rs | 14 +- src/librustc_trans/trans/datum.rs | 2 +- src/librustc_trans/trans/debuginfo.rs | 138 +++++------ src/librustc_trans/trans/expr.rs | 50 ++-- src/librustc_trans/trans/foreign.rs | 30 +-- src/librustc_trans/trans/glue.rs | 14 +- src/librustc_trans/trans/intrinsic.rs | 2 +- src/librustc_trans/trans/meth.rs | 10 +- src/librustc_trans/trans/monomorphize.rs | 22 +- src/librustc_trans/trans/type_.rs | 2 +- src/librustc_trans/trans/type_of.rs | 14 +- src/librustc_typeck/astconv.rs | 32 +-- src/librustc_typeck/check/method/mod.rs | 6 +- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/mod.rs | 62 ++--- src/librustc_typeck/check/regionck.rs | 14 +- src/librustc_typeck/check/regionmanip.rs | 2 +- src/librustc_typeck/check/vtable.rs | 12 +- src/librustc_typeck/coherence/mod.rs | 4 +- src/librustc_typeck/collect.rs | 40 ++-- src/librustc_typeck/lib.rs | 7 +- src/librustc_typeck/variance.rs | 8 +- src/librustdoc/externalfiles.rs | 2 +- src/librustdoc/html/format.rs | 10 +- src/librustdoc/html/highlight.rs | 2 +- src/librustdoc/html/render.rs | 8 +- src/librustdoc/passes.rs | 6 +- src/libserialize/json.rs | 192 +++++++-------- src/libserialize/lib.rs | 1 + src/libserialize/serialize.rs | 4 +- src/libstd/ascii.rs | 2 +- src/libstd/c_str.rs | 2 +- src/libstd/dynamic_lib.rs | 2 +- src/libstd/failure.rs | 2 +- src/libstd/io/mod.rs | 7 +- src/libstd/io/net/ip.rs | 2 +- src/libstd/io/process.rs | 4 +- src/libstd/io/stdio.rs | 2 +- src/libstd/num/strconv.rs | 2 +- src/libstd/os.rs | 12 +- src/libstd/path/mod.rs | 19 +- src/libstd/path/posix.rs | 5 +- src/libstd/path/windows.rs | 144 ++++++------ src/libstd/prelude.rs | 4 +- src/libstd/rt/backtrace.rs | 3 +- src/libstd/rt/mod.rs | 2 +- src/libstd/rt/unwind.rs | 2 +- src/libstd/rt/util.rs | 23 +- src/libstd/sys/common/backtrace.rs | 11 +- src/libstd/sys/windows/backtrace.rs | 2 +- src/libstd/sys/windows/fs.rs | 3 +- src/libstd/sys/windows/os.rs | 4 +- src/libstd/sys/windows/process.rs | 2 +- src/libstd/sys/windows/tty.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/ast_map/mod.rs | 38 +-- src/libsyntax/ast_util.rs | 14 +- src/libsyntax/attr.rs | 13 +- src/libsyntax/codemap.rs | 12 +- src/libsyntax/diagnostic.rs | 38 +-- src/libsyntax/diagnostics/plugin.rs | 6 +- src/libsyntax/ext/asm.rs | 3 +- src/libsyntax/ext/base.rs | 10 +- src/libsyntax/ext/build.rs | 3 +- src/libsyntax/ext/concat.rs | 8 +- src/libsyntax/ext/concat_idents.rs | 2 +- src/libsyntax/ext/deriving/bounds.rs | 3 +- src/libsyntax/ext/deriving/clone.rs | 9 +- src/libsyntax/ext/deriving/decodable.rs | 2 +- src/libsyntax/ext/deriving/encodable.rs | 3 +- src/libsyntax/ext/deriving/generic/mod.rs | 46 ++-- src/libsyntax/ext/deriving/mod.rs | 2 +- src/libsyntax/ext/deriving/show.rs | 2 +- src/libsyntax/ext/env.rs | 8 +- src/libsyntax/ext/expand.rs | 57 +++-- src/libsyntax/ext/format.rs | 27 ++- src/libsyntax/ext/quote.rs | 6 +- src/libsyntax/ext/source_util.rs | 16 +- src/libsyntax/ext/tt/macro_parser.rs | 21 +- src/libsyntax/ext/tt/macro_rules.rs | 12 +- src/libsyntax/ext/tt/transcribe.rs | 4 +- src/libsyntax/feature_gate.rs | 10 +- src/libsyntax/parse/attr.rs | 3 +- src/libsyntax/parse/lexer/comments.rs | 16 +- src/libsyntax/parse/lexer/mod.rs | 18 +- src/libsyntax/parse/mod.rs | 54 ++--- src/libsyntax/parse/obsolete.rs | 4 +- src/libsyntax/parse/parser.rs | 148 ++++++------ src/libsyntax/parse/token.rs | 24 +- src/libsyntax/print/pp.rs | 6 +- src/libsyntax/print/pprust.rs | 259 +++++++++++---------- src/libsyntax/std_inject.rs | 8 +- src/libsyntax/test.rs | 26 +-- src/libsyntax/util/interner.rs | 30 ++- src/libterm/terminfo/mod.rs | 2 +- src/libterm/terminfo/searcher.rs | 4 +- src/libtest/lib.rs | 8 +- src/libunicode/u_str.rs | 111 +-------- src/test/run-pass/issue-19340-1.rs | 2 +- src/test/run-pass/issue-19340-2.rs | 2 +- src/test/run-pass/issue-19367.rs | 8 +- 193 files changed, 2142 insertions(+), 2229 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 59be0152d58..bdbfbfd7c89 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -152,7 +152,7 @@ pub fn parse_config(args: Vec ) -> Config { matches.opt_str("ratchet-metrics").map(|s| Path::new(s)), ratchet_noise_percent: matches.opt_str("ratchet-noise-percent") - .and_then(|s| from_str::(s.as_slice())), + .and_then(|s| s.as_slice().parse::()), runtool: matches.opt_str("runtool"), host_rustcflags: matches.opt_str("host-rustcflags"), target_rustcflags: matches.opt_str("target-rustcflags"), @@ -190,9 +190,7 @@ pub fn log_config(config: &Config) { logv(c, format!("filter: {}", opt_str(&config.filter .as_ref() - .map(|re| { - re.to_string().into_string() - })))); + .map(|re| re.to_string())))); logv(c, format!("runtool: {}", opt_str(&config.runtool))); logv(c, format!("host-rustcflags: {}", opt_str(&config.host_rustcflags))); diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 60ef76528e8..27be6c6d835 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -351,8 +351,8 @@ pub fn gdb_version_to_int(version_string: &str) -> int { panic!("{}", error_string); } - let major: int = from_str(components[0]).expect(error_string); - let minor: int = from_str(components[1]).expect(error_string); + let major: int = components[0].parse().expect(error_string); + let minor: int = components[1].parse().expect(error_string); return major * 1000 + minor; } @@ -362,6 +362,6 @@ pub fn lldb_version_to_int(version_string: &str) -> int { "Encountered LLDB version string with unexpected format: {}", version_string); let error_string = error_string.as_slice(); - let major: int = from_str(version_string).expect(error_string); + let major: int = version_string.parse().expect(error_string); return major; } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 567734b0dab..bf72250c470 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -1361,7 +1361,7 @@ fn split_maybe_args(argstr: &Option) -> Vec { s.as_slice() .split(' ') .filter_map(|s| { - if s.is_whitespace() { + if s.chars().all(|c| c.is_whitespace()) { None } else { Some(s.to_string()) diff --git a/src/doc/guide.md b/src/doc/guide.md index 1cd100e1598..3963ce6b85d 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -2257,10 +2257,10 @@ a function for that: let input = io::stdin().read_line() .ok() .expect("Failed to read line"); -let input_num: Option = from_str(input.as_slice()); +let input_num: Option = input.parse(); ``` -The `from_str` function takes in a `&str` value and converts it into something. +The `parse` function takes in a `&str` value and converts it into something. We tell it what kind of something with a type hint. Remember our type hint with `random()`? It looked like this: @@ -2279,8 +2279,8 @@ In this case, we say `x` is a `uint` explicitly, so Rust is able to properly tell `random()` what to generate. In a similar fashion, both of these work: ```{rust,ignore} -let input_num = from_str::("5"); // input_num: Option -let input_num: Option = from_str("5"); // input_num: Option +let input_num = "5".parse::(); // input_num: Option +let input_num: Option = "5".parse(); // input_num: Option ``` Anyway, with us now converting our input to a number, our code looks like this: @@ -2301,7 +2301,7 @@ fn main() { let input = io::stdin().read_line() .ok() .expect("Failed to read line"); - let input_num: Option = from_str(input.as_slice()); + let input_num: Option = input.parse(); println!("You guessed: {}", input_num); @@ -2350,7 +2350,7 @@ fn main() { let input = io::stdin().read_line() .ok() .expect("Failed to read line"); - let input_num: Option = from_str(input.as_slice()); + let input_num: Option = input.parse(); let num = match input_num { Some(num) => num, @@ -2395,7 +2395,7 @@ Uh, what? But we did! ... actually, we didn't. See, when you get a line of input from `stdin()`, you get all the input. Including the `\n` character from you pressing Enter. -Therefore, `from_str()` sees the string `"5\n"` and says "nope, that's not a +Therefore, `parse()` sees the string `"5\n"` and says "nope, that's not a number; there's non-number stuff in there!" Luckily for us, `&str`s have an easy method we can use defined on them: `trim()`. One small modification, and our code looks like this: @@ -2416,7 +2416,7 @@ fn main() { let input = io::stdin().read_line() .ok() .expect("Failed to read line"); - let input_num: Option = from_str(input.as_slice().trim()); + let input_num: Option = input.trim().parse(); let num = match input_num { Some(num) => num, @@ -2491,7 +2491,7 @@ fn main() { let input = io::stdin().read_line() .ok() .expect("Failed to read line"); - let input_num: Option = from_str(input.as_slice().trim()); + let input_num: Option = input.trim().parse(); let num = match input_num { Some(num) => num, @@ -2566,7 +2566,7 @@ fn main() { let input = io::stdin().read_line() .ok() .expect("Failed to read line"); - let input_num: Option = from_str(input.as_slice().trim()); + let input_num: Option = input.trim().parse(); let num = match input_num { Some(num) => num, @@ -2621,7 +2621,7 @@ fn main() { let input = io::stdin().read_line() .ok() .expect("Failed to read line"); - let input_num: Option = from_str(input.as_slice().trim()); + let input_num: Option = input.trim().parse(); let num = match input_num { Some(num) => num, @@ -2697,7 +2697,7 @@ fn main() { let input = io::stdin().read_line() .ok() .expect("Failed to read line"); - let input_num: Option = from_str(input.as_slice().trim()); + let input_num: Option = input.trim().parse(); let num = match input_num { Some(num) => num, diff --git a/src/doc/reference.md b/src/doc/reference.md index 722230d3755..97184d53498 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3177,7 +3177,7 @@ Some examples of call expressions: # fn add(x: int, y: int) -> int { 0 } let x: int = add(1, 2); -let pi: Option = from_str("3.14"); +let pi: Option = "3.14".parse(); ``` ### Lambda expressions diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 75d179319f7..363d30abd03 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -121,7 +121,7 @@ mod prelude { // in core and collections (may differ). pub use slice::{PartialEqSliceExt, OrdSliceExt}; pub use slice::{AsSlice, SliceExt}; - pub use str::{from_str, Str, StrPrelude}; + pub use str::{from_str, Str}; // from other crates. pub use alloc::boxed::Box; @@ -129,7 +129,7 @@ mod prelude { // from collections. pub use slice::{CloneSliceExt, VectorVector}; - pub use str::{IntoMaybeOwned, UnicodeStrPrelude, StrAllocating, StrVector}; + pub use str::{IntoMaybeOwned, StrVector}; pub use string::{String, ToString}; pub use vec::Vec; } diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 8c9346639b3..5feae5e558e 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -55,25 +55,31 @@ use self::MaybeOwned::*; use self::RecompositionState::*; use self::DecompositionType::*; -use core::prelude::*; - use core::borrow::{BorrowFrom, Cow, ToOwned}; -use core::cmp::{mod, Equiv, PartialEq, Eq, PartialOrd, Ord, Ordering}; +use core::char::Char; +use core::clone::Clone; +use core::cmp::{Equiv, PartialEq, Eq, PartialOrd, Ord, Ordering}; +use core::cmp; use core::default::Default; use core::fmt; use core::hash; use core::iter::AdditiveIterator; use core::iter::{mod, range, Iterator, IteratorExt}; +use core::kinds::Sized; +use core::ops; +use core::option::Option::{mod, Some, None}; +use core::slice::AsSlice; use core::str as core_str; use unicode::str::{UnicodeStr, Utf16Encoder}; use ring_buf::RingBuf; -use string::{String, ToString}; +use slice::SliceExt; +use string::String; use unicode; use vec::Vec; pub use core::str::{from_utf8, CharEq, Chars, CharIndices}; -pub use core::str::{Bytes, CharSplits}; +pub use core::str::{Bytes, CharSplits, is_utf8}; pub use core::str::{CharSplitsN, Lines, LinesAny, MatchIndices, StrSplits}; pub use core::str::{CharRange}; pub use core::str::{FromStr, from_str, Utf8Error}; @@ -408,6 +414,7 @@ impl<'a> Iterator for Utf16Units<'a> { /// # Examples /// /// ```rust +/// # #![allow(deprecated)] /// use std::str; /// let string = "orange"; /// let new_string = str::replace(string, "or", "str"); @@ -441,7 +448,7 @@ Section: MaybeOwned /// A string type that can hold either a `String` or a `&str`. /// This can be useful as an optimization when an allocation is sometimes /// needed but not always. -#[deprecated = "use stding::string::CowString"] +#[deprecated = "use std::string::CowString"] pub enum MaybeOwned<'a> { /// A borrowed string. Slice(&'a str), @@ -650,7 +657,11 @@ impl BorrowFrom for str { #[unstable = "trait is unstable"] impl ToOwned for str { - fn to_owned(&self) -> String { self.to_string() } + fn to_owned(&self) -> String { + unsafe { + String::from_utf8_unchecked(self.as_bytes().to_owned()) + } + } } /// Unsafe string operations. @@ -673,7 +684,7 @@ Section: Trait implementations */ /// Any string that can be represented as a slice. -pub trait StrExt for Sized?: Slice { +pub trait StrExt for Sized?: ops::Slice { /// Escapes each char in `s` with `char::escape_default`. #[unstable = "return type may change to be an iterator"] fn escape_default(&self) -> String { @@ -724,7 +735,7 @@ pub trait StrExt for Sized?: Slice { } /// Given a string, makes a new string with repeated copies of it. - #[deprecated = "user repeat(self).take(n).collect() instead"] + #[deprecated = "use repeat(self).take(n).collect() instead"] fn repeat(&self, nn: uint) -> String { iter::repeat(self[]).take(nn).collect() } @@ -766,7 +777,7 @@ pub trait StrExt for Sized?: Slice { /// Returns an iterator over the string in Unicode Normalization Form D /// (canonical decomposition). #[inline] - #[unstable = "this functionality may only be provided by libunicode"] + #[unstable = "this functionality may be moved to libunicode"] fn nfd_chars<'a>(&'a self) -> Decompositions<'a> { Decompositions { iter: self[].chars(), @@ -779,7 +790,7 @@ pub trait StrExt for Sized?: Slice { /// Returns an iterator over the string in Unicode Normalization Form KD /// (compatibility decomposition). #[inline] - #[unstable = "this functionality may only be provided by libunicode"] + #[unstable = "this functionality may be moved to libunicode"] fn nfkd_chars<'a>(&'a self) -> Decompositions<'a> { Decompositions { iter: self[].chars(), @@ -792,7 +803,7 @@ pub trait StrExt for Sized?: Slice { /// An Iterator over the string in Unicode Normalization Form C /// (canonical decomposition followed by canonical composition). #[inline] - #[unstable = "this functionality may only be provided by libunicode"] + #[unstable = "this functionality may be moved to libunicode"] fn nfc_chars<'a>(&'a self) -> Recompositions<'a> { Recompositions { iter: self.nfd_chars(), @@ -806,7 +817,7 @@ pub trait StrExt for Sized?: Slice { /// An Iterator over the string in Unicode Normalization Form KC /// (compatibility decomposition followed by canonical composition). #[inline] - #[unstable = "this functionality may only be provided by libunicode"] + #[unstable = "this functionality may be moved to libunicode"] fn nfkc_chars<'a>(&'a self) -> Recompositions<'a> { Recompositions { iter: self.nfkd_chars(), @@ -891,7 +902,7 @@ pub trait StrExt for Sized?: Slice { /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); /// - /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); + /// let v: Vec<&str> = "abc1def2ghi".split(|&: c: char| c.is_numeric()).collect(); /// assert_eq!(v, vec!["abc", "def", "ghi"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); @@ -915,7 +926,7 @@ pub trait StrExt for Sized?: Slice { /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect(); /// assert_eq!(v, vec!["Mary", "had", "a little lambda"]); /// - /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect(); + /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |&: c: char| c.is_numeric()).collect(); /// assert_eq!(v, vec!["abc", "def2ghi"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect(); @@ -950,7 +961,7 @@ pub trait StrExt for Sized?: Slice { /// let v: Vec<&str> = "Mary had a little lamb".split(' ').rev().collect(); /// assert_eq!(v, vec!["lamb", "little", "a", "had", "Mary"]); /// - /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).rev().collect(); + /// let v: Vec<&str> = "abc1def2ghi".split(|&: c: char| c.is_numeric()).rev().collect(); /// assert_eq!(v, vec!["ghi", "def", "abc"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect(); @@ -971,7 +982,7 @@ pub trait StrExt for Sized?: Slice { /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect(); /// assert_eq!(v, vec!["lamb", "little", "Mary had a"]); /// - /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect(); + /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |&: c: char| c.is_numeric()).collect(); /// assert_eq!(v, vec!["ghi", "abc1def"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect(); @@ -1071,10 +1082,11 @@ pub trait StrExt for Sized?: Slice { /// # Example /// /// ```rust + /// # #![allow(deprecated)] /// // composed forms of `ö` and `é` /// let c = "Löwe 老虎 Léopard"; // German, Simplified Chinese, French /// // decomposed forms of `ö` and `é` - /// let d = "Lo\u0308we 老虎 Le\u0301opard"; + /// let d = "Lo\u{0308}we 老虎 Le\u{0301}opard"; /// /// assert_eq!(c.char_len(), 15); /// assert_eq!(d.char_len(), 17); @@ -1225,10 +1237,10 @@ pub trait StrExt for Sized?: Slice { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar") + /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar"); /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_chars(x), "foo1bar") - /// assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_numeric()), "foo1bar") + /// assert_eq!("12foo1bar12".trim_chars(x), "foo1bar"); + /// assert_eq!("123foo1bar123".trim_chars(|&: c: char| c.is_numeric()), "foo1bar"); /// ``` #[unstable = "awaiting pattern/matcher stabilization"] fn trim_chars(&self, to_trim: C) -> &str { @@ -1244,10 +1256,10 @@ pub trait StrExt for Sized?: Slice { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11") + /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11"); /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_left_chars(x), "foo1bar12") - /// assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_numeric()), "foo1bar123") + /// assert_eq!("12foo1bar12".trim_left_chars(x), "foo1bar12"); + /// assert_eq!("123foo1bar123".trim_left_chars(|&: c: char| c.is_numeric()), "foo1bar123"); /// ``` #[unstable = "awaiting pattern/matcher stabilization"] fn trim_left_chars(&self, to_trim: C) -> &str { @@ -1263,10 +1275,10 @@ pub trait StrExt for Sized?: Slice { /// # Example /// /// ```rust - /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar") + /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar"); /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_right_chars(x), "12foo1bar") - /// assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_numeric()), "123foo1bar") + /// assert_eq!("12foo1bar12".trim_right_chars(x), "12foo1bar"); + /// assert_eq!("123foo1bar123".trim_right_chars(|&: c: char| c.is_numeric()), "123foo1bar"); /// ``` #[unstable = "awaiting pattern/matcher stabilization"] fn trim_right_chars(&self, to_trim: C) -> &str { @@ -1434,7 +1446,7 @@ pub trait StrExt for Sized?: Slice { /// assert_eq!(s.find('é'), Some(14)); /// /// // the first space - /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5)); + /// assert_eq!(s.find(|&: c: char| c.is_whitespace()), Some(5)); /// /// // neither are found /// let x: &[_] = &['1', '2']; @@ -1462,7 +1474,7 @@ pub trait StrExt for Sized?: Slice { /// assert_eq!(s.rfind('é'), Some(14)); /// /// // the second space - /// assert_eq!(s.rfind(|c: char| c.is_whitespace()), Some(12)); + /// assert_eq!(s.rfind(|&: c: char| c.is_whitespace()), Some(12)); /// /// // searches for an occurrence of either `1` or `2`, but neither are found /// let x: &[_] = &['1', '2']; @@ -1609,8 +1621,8 @@ pub trait StrExt for Sized?: Slice { /// # Example /// /// ```rust - /// let gr1 = "a\u0310e\u0301o\u0308\u0332".graphemes(true).collect::>(); - /// let b: &[_] = &["a\u0310", "e\u0301", "o\u0308\u0332"]; + /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::>(); + /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"]; /// assert_eq!(gr1.as_slice(), b); /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::>(); /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"]; @@ -1659,6 +1671,7 @@ pub trait StrExt for Sized?: Slice { /// # Example /// /// ```rust + /// # #![allow(deprecated)] /// assert!(" \t\n".is_whitespace()); /// assert!("".is_whitespace()); /// @@ -1677,6 +1690,7 @@ pub trait StrExt for Sized?: Slice { /// # Example /// /// ```rust + /// # #![allow(deprecated)] /// assert!("Löwe老虎Léopard123".is_alphanumeric()); /// assert!("".is_alphanumeric()); /// @@ -1718,25 +1732,39 @@ pub trait StrExt for Sized?: Slice { fn trim_right(&self) -> &str { UnicodeStr::trim_right(self[]) } + + /// Deprecated, call `.to_owned()` instead from the `std::borrow::ToOwned` + /// trait. + #[deprecated = "call `.to_owned()` on `std::borrow::ToOwned` instead"] + fn into_string(&self) -> String { + self[].to_owned() + } } impl StrExt for str {} #[cfg(test)] mod tests { - use prelude::*; - use core::default::Default; - use core::iter::AdditiveIterator; - use super::{eq_slice, from_utf8, is_utf8, is_utf16, raw}; - use super::truncate_utf16_at_nul; + use std::iter::AdditiveIterator; + use std::iter::range; + use std::default::Default; + use std::char::Char; + use std::clone::Clone; + use std::cmp::{Ord, PartialOrd, Equiv}; + use std::cmp::Ordering::{Equal, Greater, Less}; + use std::option::Option::{mod, Some, None}; + use std::result::Result::{Ok, Err}; + use std::ptr::RawPtr; + use std::iter::{Iterator, IteratorExt, DoubleEndedIteratorExt}; + + use super::*; use super::MaybeOwned::{Owned, Slice}; + use std::slice::{AsSlice, SliceExt}; + use string::{String, ToString}; + use vec::Vec; + use slice::CloneSliceExt; - #[test] - fn test_eq_slice() { - assert!((eq_slice("foobar".slice(0, 3), "foo"))); - assert!((eq_slice("barfoo".slice(3, 6), "foo"))); - assert!((!eq_slice("foo1", "foo2"))); - } + use unicode::char::UnicodeChar; #[test] fn test_le() { @@ -2267,6 +2295,7 @@ mod tests { #[test] fn test_is_utf16() { + use unicode::str::is_utf16; macro_rules! pos ( ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } }); // non-surrogates @@ -3229,13 +3258,13 @@ mod tests { #[test] fn test_str_from_utf8() { let xs = b"hello"; - assert_eq!(from_utf8(xs), Some("hello")); + assert_eq!(from_utf8(xs), Ok("hello")); let xs = "ศไทย中华Việt Nam".as_bytes(); - assert_eq!(from_utf8(xs), Some("ศไทย中华Việt Nam")); + assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam")); let xs = b"hello\xFF"; - assert_eq!(from_utf8(xs), None); + assert_eq!(from_utf8(xs), Err(Utf8Error::TooShort)); } #[test] @@ -3284,8 +3313,8 @@ mod tests { #[test] fn test_maybe_owned_into_string() { - assert_eq!(Slice("abcde").into_string(), String::from_str("abcde")); - assert_eq!(Owned(String::from_str("abcde")).into_string(), + assert_eq!(Slice("abcde").to_string(), String::from_str("abcde")); + assert_eq!(Owned(String::from_str("abcde")).to_string(), String::from_str("abcde")); } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 0e2b514d92d..6c2659b13f7 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -26,7 +26,7 @@ use unicode::str as unicode_str; use unicode::str::Utf16Item; use slice::CloneSliceExt; -use str::{mod, CharRange, FromStr, StrExt, Owned, Utf8Error}; +use str::{mod, CharRange, FromStr, Utf8Error}; use vec::{DerefVec, Vec, as_vec}; /// A growable string stored as a UTF-8 encoded buffer. @@ -94,13 +94,16 @@ impl String { /// # Examples /// /// ```rust + /// # #![allow(deprecated)] + /// use std::str::Utf8Error; + /// /// let hello_vec = vec![104, 101, 108, 108, 111]; /// let s = String::from_utf8(hello_vec); /// assert_eq!(s, Ok("hello".to_string())); /// /// let invalid_vec = vec![240, 144, 128]; /// let s = String::from_utf8(invalid_vec); - /// assert_eq!(s, Err(vec![240, 144, 128])); + /// assert_eq!(s, Err((vec![240, 144, 128], Utf8Error::TooShort))); /// ``` #[inline] #[unstable = "error type may change"] @@ -833,7 +836,7 @@ impl Default for String { #[experimental = "waiting on Show stabilization"] impl fmt::Show for String { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - (*self).fmt(f) + (**self).fmt(f) } } @@ -841,7 +844,7 @@ impl fmt::Show for String { impl hash::Hash for String { #[inline] fn hash(&self, hasher: &mut H) { - (*self).hash(hasher) + (**self).hash(hasher) } } @@ -1026,6 +1029,7 @@ mod tests { use prelude::*; use test::Bencher; + use str::{StrExt, Utf8Error}; use str; use super::as_string; @@ -1044,14 +1048,16 @@ mod tests { #[test] fn test_from_utf8() { let xs = b"hello".to_vec(); - assert_eq!(String::from_utf8(xs), Ok(String::from_str("hello"))); + assert_eq!(String::from_utf8(xs), + Ok(String::from_str("hello"))); let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); - assert_eq!(String::from_utf8(xs), Ok(String::from_str("ศไทย中华Việt Nam"))); + assert_eq!(String::from_utf8(xs), + Ok(String::from_str("ศไทย中华Việt Nam"))); let xs = b"hello\xFF".to_vec(); assert_eq!(String::from_utf8(xs), - Err(b"hello\xFF".to_vec())); + Err((b"hello\xFF".to_vec(), Utf8Error::TooShort))); } #[test] @@ -1141,7 +1147,7 @@ mod tests { let s_as_utf16 = s.utf16_units().collect::>(); let u_as_string = String::from_utf16(u.as_slice()).unwrap(); - assert!(str::is_utf16(u.as_slice())); + assert!(::unicode::str::is_utf16(u.as_slice())); assert_eq!(s_as_utf16, u); assert_eq!(u_as_string, s); diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 8adbba8b94b..d831a57893b 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -718,15 +718,15 @@ impl Option { /// # Example /// /// Convert a string to an integer, turning poorly-formed strings - /// into 0 (the default value for integers). `from_str` converts + /// into 0 (the default value for integers). `parse` converts /// a string to any other type that implements `FromStr`, returning /// `None` on error. /// /// ``` /// let good_year_from_input = "1909"; /// let bad_year_from_input = "190blarg"; - /// let good_year = from_str(good_year_from_input).unwrap_or_default(); - /// let bad_year = from_str(bad_year_from_input).unwrap_or_default(); + /// let good_year = good_year_from_input.parse().unwrap_or_default(); + /// let bad_year = bad_year_from_input.parse().unwrap_or_default(); /// /// assert_eq!(1909i, good_year); /// assert_eq!(0i, bad_year); diff --git a/src/libcore/result.rs b/src/libcore/result.rs index b59734a7d98..8014b4dc89d 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -458,7 +458,7 @@ impl Result { /// let line: IoResult = buffer.read_line(); /// // Convert the string line to a number using `map` and `from_str` /// let val: IoResult = line.map(|line| { - /// from_str::(line.as_slice().trim_right()).unwrap_or(0) + /// line.as_slice().trim_right().parse::().unwrap_or(0) /// }); /// // Add the value if there were no errors, otherwise add 0 /// sum += val.ok().unwrap_or(0); diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 60d4262a9b1..bfccc1e3f73 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -18,14 +18,13 @@ use self::Searcher::{Naive, TwoWay, TwoWayLong}; -use char::{mod, Char}; use clone::Clone; use cmp::{mod, Eq}; use default::Default; use iter::range; use iter::{DoubleEndedIteratorExt, ExactSizeIterator}; use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator}; -use kinds::{Copy, Sized}; +use kinds::Sized; use mem; use num::Int; use ops::{Fn, FnMut}; @@ -60,9 +59,9 @@ impl FromStr for bool { /// # Examples /// /// ```rust - /// assert_eq!(from_str::("true"), Some(true)); - /// assert_eq!(from_str::("false"), Some(false)); - /// assert_eq!(from_str::("not even a boolean"), None); + /// assert_eq!("true".parse(), Some(true)); + /// assert_eq!("false".parse(), Some(false)); + /// assert_eq!("not even a boolean".parse::(), None); /// ``` #[inline] fn from_str(s: &str) -> Option { @@ -79,6 +78,7 @@ Section: Creating a string */ /// Errors which can occur when attempting to interpret a byte slice as a `str`. +#[deriving(Copy, Eq, PartialEq, Clone)] pub enum Utf8Error { /// An invalid byte was detected at the byte offset given. /// @@ -334,6 +334,7 @@ impl<'a> DoubleEndedIterator<(uint, char)> for CharIndices<'a> { /// External iterator for a string's bytes. /// Use with the `std::iter` module. #[stable] +#[deriving(Clone)] pub struct Bytes<'a> { inner: Map<&'a u8, u8, slice::Items<'a, u8>, BytesFn>, } @@ -946,24 +947,7 @@ pub fn is_utf8(v: &[u8]) -> bool { run_utf8_validation_iterator(&mut v.iter()).is_ok() } -/// Return a slice of `v` ending at (and not including) the first NUL -/// (0). -/// -/// # Example -/// -/// ```rust -/// use std::str; -/// -/// // "abcd" -/// let mut v = ['a' as u16, 'b' as u16, 'c' as u16, 'd' as u16]; -/// // no NULs so no change -/// assert_eq!(str::truncate_utf16_at_nul(&v), v.as_slice()); -/// -/// // "ab\0d" -/// v[2] = 0; -/// let b: &[_] = &['a' as u16, 'b' as u16]; -/// assert_eq!(str::truncate_utf16_at_nul(&v), b); -/// ``` +/// Deprecated function #[deprecated = "this function will be removed"] pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { match v.iter().position(|c| *c == 0) { @@ -1595,6 +1579,8 @@ impl<'a> Default for &'a str { impl<'a> Iterator<&'a str> for Lines<'a> { #[inline] fn next(&mut self) -> Option<&'a str> { self.inner.next() } + #[inline] + fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } impl<'a> DoubleEndedIterator<&'a str> for Lines<'a> { #[inline] @@ -1603,6 +1589,8 @@ impl<'a> DoubleEndedIterator<&'a str> for Lines<'a> { impl<'a> Iterator<&'a str> for LinesAny<'a> { #[inline] fn next(&mut self) -> Option<&'a str> { self.inner.next() } + #[inline] + fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } impl<'a> DoubleEndedIterator<&'a str> for LinesAny<'a> { #[inline] @@ -1611,6 +1599,8 @@ impl<'a> DoubleEndedIterator<&'a str> for LinesAny<'a> { impl<'a> Iterator for Bytes<'a> { #[inline] fn next(&mut self) -> Option { self.inner.next() } + #[inline] + fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } impl<'a> DoubleEndedIterator for Bytes<'a> { #[inline] diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 05d862d7bc7..44029ebb7fa 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -13,6 +13,7 @@ extern crate core; extern crate test; extern crate libc; +extern crate unicode; mod any; mod atomic; diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index 763fcccdbfd..63d6e14a4a6 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -117,7 +117,7 @@ fn test_rev_split_char_iterator_no_trailing() { #[test] fn test_utf16_code_units() { - use core::str::Utf16Encoder; + use unicode::str::Utf16Encoder; assert_eq!(Utf16Encoder::new(vec!['é', '\U0001F4A9'].into_iter()).collect::>(), vec![0xE9, 0xD83D, 0xDCA9]) } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 106e467c169..c284fb7c9e3 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -23,7 +23,8 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(macro_rules, globs)] +#![feature(macro_rules, globs, slicing_syntax)] + pub use self::Piece::*; pub use self::Position::*; pub use self::Alignment::*; @@ -136,7 +137,7 @@ pub enum Count<'a> { /// necessary there's probably lots of room for improvement performance-wise. pub struct Parser<'a> { input: &'a str, - cur: str::CharOffsets<'a>, + cur: str::CharIndices<'a>, /// Error messages accumulated during parsing pub errors: Vec, } @@ -208,13 +209,11 @@ impl<'a> Parser<'a> { self.cur.next(); } Some((_, other)) => { - self.err(format!("expected `{}`, found `{}`", - c, - other).as_slice()); + self.err(format!("expected `{}`, found `{}`", c, other)[]); } None => { self.err(format!("expected `{}` but string was terminated", - c).as_slice()); + c)[]); } } } @@ -237,12 +236,12 @@ impl<'a> Parser<'a> { // we may not consume the character, so clone the iterator match self.cur.clone().next() { Some((pos, '}')) | Some((pos, '{')) => { - return self.input.slice(start, pos); + return self.input[start..pos]; } Some(..) => { self.cur.next(); } None => { self.cur.next(); - return self.input.slice(start, self.input.len()); + return self.input[start..self.input.len()]; } } } @@ -282,7 +281,7 @@ impl<'a> Parser<'a> { flags: 0, precision: CountImplied, width: CountImplied, - ty: self.input.slice(0, 0), + ty: self.input[0..0], }; if !self.consume(':') { return spec } @@ -391,7 +390,7 @@ impl<'a> Parser<'a> { self.cur.next(); pos } - Some(..) | None => { return self.input.slice(0, 0); } + Some(..) | None => { return self.input[0..0]; } }; let mut end; loop { @@ -403,7 +402,7 @@ impl<'a> Parser<'a> { None => { end = self.input.len(); break } } } - self.input.slice(start, end) + self.input[start..end] } /// Optionally parses an integer at the current position. This doesn't deal diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index e362c67cc50..0426f269376 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -85,7 +85,7 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(globs, phase)] +#![feature(globs, phase, slicing_syntax)] #![feature(unboxed_closures)] #![deny(missing_docs)] @@ -101,9 +101,8 @@ use self::Whitespace::*; use self::LengthLimit::*; use std::fmt; -use std::result::Result::{Err, Ok}; +use std::iter::repeat; use std::result; -use std::string::String; /// Name of an option. Either a string or a single char. #[deriving(Clone, PartialEq, Eq)] @@ -282,7 +281,7 @@ impl OptGroup { impl Matches { fn opt_vals(&self, nm: &str) -> Vec { - match find_opt(self.opts.as_slice(), Name::from_str(nm)) { + match find_opt(self.opts[], Name::from_str(nm)) { Some(id) => self.vals[id].clone(), None => panic!("No option '{}' defined", nm) } @@ -310,8 +309,7 @@ impl Matches { /// Returns true if any of several options were matched. pub fn opts_present(&self, names: &[String]) -> bool { for nm in names.iter() { - match find_opt(self.opts.as_slice(), - Name::from_str(nm.as_slice())) { + match find_opt(self.opts.as_slice(), Name::from_str(nm[])) { Some(id) if !self.vals[id].is_empty() => return true, _ => (), }; @@ -322,7 +320,7 @@ impl Matches { /// Returns the string argument supplied to one of several matching options or `None`. pub fn opts_str(&self, names: &[String]) -> Option { for nm in names.iter() { - match self.opt_val(nm.as_slice()) { + match self.opt_val(nm[]) { Some(Val(ref s)) => return Some(s.clone()), _ => () } @@ -587,7 +585,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { while i < l { let cur = args[i].clone(); let curlen = cur.len(); - if !is_arg(cur.as_slice()) { + if !is_arg(cur[]) { free.push(cur); } else if cur == "--" { let mut j = i + 1; @@ -597,7 +595,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { let mut names; let mut i_arg = None; if cur.as_bytes()[1] == b'-' { - let tail = cur.slice(2, curlen); + let tail = cur[2..curlen]; let tail_eq: Vec<&str> = tail.split('=').collect(); if tail_eq.len() <= 1 { names = vec!(Long(tail.to_string())); @@ -633,7 +631,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { }; if arg_follows && range.next < curlen { - i_arg = Some(cur.slice(range.next, curlen).to_string()); + i_arg = Some(cur[range.next..curlen].to_string()); break; } @@ -660,7 +658,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { .push(Val((i_arg.clone()) .unwrap())); } else if name_pos < names.len() || i + 1 == l || - is_arg(args[i + 1].as_slice()) { + is_arg(args[i + 1][]) { vals[optid].push(Given); } else { i += 1; @@ -702,7 +700,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { /// Derive a usage message from a set of long options. pub fn usage(brief: &str, opts: &[OptGroup]) -> String { - let desc_sep = format!("\n{}", " ".repeat(24)); + let desc_sep = format!("\n{}", repeat(" ").take(24).collect::()); let rows = opts.iter().map(|optref| { let OptGroup{short_name, @@ -712,14 +710,14 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { hasarg, ..} = (*optref).clone(); - let mut row = " ".repeat(4); + let mut row = repeat(" ").take(4).collect::(); // short option match short_name.len() { 0 => {} 1 => { row.push('-'); - row.push_str(short_name.as_slice()); + row.push_str(short_name[]); row.push(' '); } _ => panic!("the short name should only be 1 ascii char long"), @@ -730,7 +728,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { 0 => {} _ => { row.push_str("--"); - row.push_str(long_name.as_slice()); + row.push_str(long_name[]); row.push(' '); } } @@ -738,23 +736,23 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { // arg match hasarg { No => {} - Yes => row.push_str(hint.as_slice()), + Yes => row.push_str(hint[]), Maybe => { row.push('['); - row.push_str(hint.as_slice()); + row.push_str(hint[]); row.push(']'); } } // FIXME: #5516 should be graphemes not codepoints // here we just need to indent the start of the description - let rowlen = row.char_len(); + let rowlen = row.chars().count(); if rowlen < 24 { for _ in range(0, 24 - rowlen) { row.push(' '); } } else { - row.push_str(desc_sep.as_slice()) + row.push_str(desc_sep[]); } // Normalize desc to contain words separated by one space character @@ -766,16 +764,14 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { // FIXME: #5516 should be graphemes not codepoints let mut desc_rows = Vec::new(); - each_split_within(desc_normalized_whitespace.as_slice(), - 54, - |substr| { + each_split_within(desc_normalized_whitespace[], 54, |substr| { desc_rows.push(substr.to_string()); true }); // FIXME: #5516 should be graphemes not codepoints // wrapped description - row.push_str(desc_rows.connect(desc_sep.as_slice()).as_slice()); + row.push_str(desc_rows.connect(desc_sep[])[]); row }); @@ -794,10 +790,10 @@ fn format_option(opt: &OptGroup) -> String { // Use short_name is possible, but fallback to long_name. if opt.short_name.len() > 0 { line.push('-'); - line.push_str(opt.short_name.as_slice()); + line.push_str(opt.short_name[]); } else { line.push_str("--"); - line.push_str(opt.long_name.as_slice()); + line.push_str(opt.long_name[]); } if opt.hasarg != No { @@ -805,7 +801,7 @@ fn format_option(opt: &OptGroup) -> String { if opt.hasarg == Maybe { line.push('['); } - line.push_str(opt.hint.as_slice()); + line.push_str(opt.hint[]); if opt.hasarg == Maybe { line.push(']'); } @@ -827,8 +823,7 @@ pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> String { line.push_str(opts.iter() .map(format_option) .collect::>() - .connect(" ") - .as_slice()); + .connect(" ")[]); line } @@ -891,9 +886,9 @@ fn each_split_within(ss: &str, lim: uint, mut it: F) -> bool where (B, Cr, UnderLim) => { B } (B, Cr, OverLim) if (i - last_start + 1) > lim => panic!("word starting with {} longer than limit!", - ss.slice(last_start, i + 1)), + ss[last_start..i + 1]), (B, Cr, OverLim) => { - *cont = it(ss.slice(slice_start, last_end)); + *cont = it(ss[slice_start..last_end]); slice_start = last_start; B } @@ -903,7 +898,7 @@ fn each_split_within(ss: &str, lim: uint, mut it: F) -> bool where } (B, Ws, OverLim) => { last_end = i; - *cont = it(ss.slice(slice_start, last_end)); + *cont = it(ss[slice_start..last_end]); A } @@ -912,14 +907,14 @@ fn each_split_within(ss: &str, lim: uint, mut it: F) -> bool where B } (C, Cr, OverLim) => { - *cont = it(ss.slice(slice_start, last_end)); + *cont = it(ss[slice_start..last_end]); slice_start = i; last_start = i; last_end = i; B } (C, Ws, OverLim) => { - *cont = it(ss.slice(slice_start, last_end)); + *cont = it(ss[slice_start..last_end]); A } (C, Ws, UnderLim) => { diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 34e19aa4a03..ce3df1090bd 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -448,8 +448,8 @@ impl<'a> LabelText<'a> { /// Renders text as string suitable for a label in a .dot file. pub fn escape(&self) -> String { match self { - &LabelStr(ref s) => (&**s).escape_default(), - &EscStr(ref s) => LabelText::escape_str(s.as_slice()), + &LabelStr(ref s) => s.escape_default(), + &EscStr(ref s) => LabelText::escape_str(s[]), } } @@ -475,10 +475,10 @@ impl<'a> LabelText<'a> { /// Puts `suffix` on a line below this label, with a blank line separator. pub fn suffix_line(self, suffix: LabelText) -> LabelText<'static> { - let mut prefix = self.pre_escaped_content().into_string(); + let mut prefix = self.pre_escaped_content().into_owned(); let suffix = suffix.pre_escaped_content(); prefix.push_str(r"\n\n"); - prefix.push_str(suffix.as_slice()); + prefix.push_str(suffix[]); EscStr(prefix.into_cow()) } } @@ -671,7 +671,7 @@ mod tests { impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph { fn graph_id(&'a self) -> Id<'a> { - Id::new(self.name.as_slice()).unwrap() + Id::new(self.name[]).unwrap() } fn node_id(&'a self, n: &Node) -> Id<'a> { id_name(n) @@ -735,7 +735,7 @@ mod tests { fn test_input(g: LabelledGraph) -> IoResult { let mut writer = Vec::new(); render(&g, &mut writer).unwrap(); - (&mut writer.as_slice()).read_to_string() + (&mut writer[]).read_to_string() } // All of the tests use raw-strings as the format for the expected outputs, @@ -847,7 +847,7 @@ r#"digraph hasse_diagram { edge(1, 3, ";"), edge(2, 3, ";" ))); render(&g, &mut writer).unwrap(); - let r = (&mut writer.as_slice()).read_to_string(); + let r = (&mut writer[]).read_to_string(); assert_eq!(r.unwrap(), r#"digraph syntax_tree { diff --git a/src/liblog/directive.rs b/src/liblog/directive.rs index d1db0ec89a1..2b25a64affe 100644 --- a/src/liblog/directive.rs +++ b/src/liblog/directive.rs @@ -23,7 +23,7 @@ pub static LOG_LEVEL_NAMES: [&'static str, ..4] = ["ERROR", "WARN", "INFO", /// Parse an individual log level that is either a number or a symbolic log level fn parse_log_level(level: &str) -> Option { - from_str::(level).or_else(|| { + level.parse::().or_else(|| { let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level)); pos.map(|p| p as u32 + 1) }).map(|p| cmp::min(p, ::MAX_LOG_LEVEL)) diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 2bf9af90271..bc655c219f3 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -164,7 +164,7 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(macro_rules, unboxed_closures)] +#![feature(macro_rules, unboxed_closures, slicing_syntax)] #![deny(missing_docs)] extern crate regex; @@ -280,7 +280,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) { // Test the literal string from args against the current filter, if there // is one. match unsafe { FILTER.as_ref() } { - Some(filter) if !filter.is_match(args.to_string().as_slice()) => return, + Some(filter) if !filter.is_match(args.to_string()[]) => return, _ => {} } @@ -375,7 +375,7 @@ fn enabled(level: u32, // Search for the longest match, the vector is assumed to be pre-sorted. for directive in iter.rev() { match directive.name { - Some(ref name) if !module.starts_with(name.as_slice()) => {}, + Some(ref name) if !module.starts_with(name[]) => {}, Some(..) | None => { return level <= directive.level } @@ -390,7 +390,7 @@ fn enabled(level: u32, /// `Once` primitive (and this function is called from that primitive). fn init() { let (mut directives, filter) = match os::getenv("RUST_LOG") { - Some(spec) => directive::parse_logging_spec(spec.as_slice()), + Some(spec) => directive::parse_logging_spec(spec[]), None => (Vec::new(), None), }; diff --git a/src/libregex/parse.rs b/src/libregex/parse.rs index 78558a32266..0cd8df73c37 100644 --- a/src/libregex/parse.rs +++ b/src/libregex/parse.rs @@ -286,7 +286,7 @@ impl<'a> Parser<'a> { true => Ok(()), false => { self.err(format!("Expected {} but got EOF.", - expected).as_slice()) + expected)[]) } } } @@ -295,10 +295,10 @@ impl<'a> Parser<'a> { match self.next_char() { true if self.cur() == expected => Ok(()), true => self.err(format!("Expected '{}' but got '{}'.", - expected, self.cur()).as_slice()), + expected, self.cur())[]), false => { self.err(format!("Expected '{}' but got EOF.", - expected).as_slice()) + expected)[]) } } } @@ -443,14 +443,14 @@ impl<'a> Parser<'a> { Literal(c3, _) => c2 = c3, // allow literal escapes below ast => return self.err(format!("Expected a literal, but got {}.", - ast).as_slice()), + ast)[]), } } if c2 < c { return self.err(format!("Invalid character class \ range '{}-{}'", c, - c2).as_slice()) + c2)[]) } ranges.push((c, self.cur())) } else { @@ -488,7 +488,7 @@ impl<'a> Parser<'a> { FLAG_EMPTY }; let name = self.slice(name_start, closer - 1); - match find_class(ASCII_CLASSES, name.as_slice()) { + match find_class(ASCII_CLASSES, name[]) { None => None, Some(ranges) => { self.chari = closer; @@ -513,7 +513,7 @@ impl<'a> Parser<'a> { return self.err(format!("No closing brace for counted \ repetition starting at position \ {}.", - start).as_slice()) + start)[]) } }; self.chari = closer; @@ -524,7 +524,7 @@ impl<'a> Parser<'a> { // Parse the min and max values from the regex. let (mut min, mut max): (uint, Option); if !inner.contains(",") { - min = try!(self.parse_uint(inner.as_slice())); + min = try!(self.parse_uint(inner[])); max = Some(min); } else { let pieces: Vec<&str> = inner.splitn(1, ',').collect(); @@ -546,19 +546,19 @@ impl<'a> Parser<'a> { if min > MAX_REPEAT { return self.err(format!( "{} exceeds maximum allowed repetitions ({})", - min, MAX_REPEAT).as_slice()); + min, MAX_REPEAT)[]); } if max.is_some() { let m = max.unwrap(); if m > MAX_REPEAT { return self.err(format!( "{} exceeds maximum allowed repetitions ({})", - m, MAX_REPEAT).as_slice()); + m, MAX_REPEAT)[]); } if m < min { return self.err(format!( "Max repetitions ({}) cannot be smaller than min \ - repetitions ({}).", m, min).as_slice()); + repetitions ({}).", m, min)[]); } } @@ -622,8 +622,7 @@ impl<'a> Parser<'a> { Ok(AstClass(ranges, flags)) } _ => { - self.err(format!("Invalid escape sequence '\\\\{}'", - c).as_slice()) + self.err(format!("Invalid escape sequence '\\\\{}'", c)[]) } } } @@ -643,7 +642,7 @@ impl<'a> Parser<'a> { Some(i) => i, None => return self.err(format!( "Missing '}}' for unclosed '{{' at position {}", - self.chari).as_slice()), + self.chari)[]), }; if closer - self.chari + 1 == 0 { return self.err("No Unicode class name found.") @@ -657,10 +656,10 @@ impl<'a> Parser<'a> { name = self.slice(self.chari + 1, self.chari + 2); self.chari += 1; } - match find_class(UNICODE_CLASSES, name.as_slice()) { + match find_class(UNICODE_CLASSES, name[]) { None => { return self.err(format!("Could not find Unicode class '{}'", - name).as_slice()) + name)[]) } Some(ranges) => { Ok(AstClass(ranges, negated | (self.flags & FLAG_NOCASE))) @@ -683,11 +682,11 @@ impl<'a> Parser<'a> { } } let s = self.slice(start, end); - match num::from_str_radix::(s.as_slice(), 8) { + match num::from_str_radix::(s[], 8) { Some(n) => Ok(Literal(try!(self.char_from_u32(n)), FLAG_EMPTY)), None => { self.err(format!("Could not parse '{}' as octal number.", - s).as_slice()) + s)[]) } } } @@ -705,12 +704,12 @@ impl<'a> Parser<'a> { None => { return self.err(format!("Missing '}}' for unclosed \ '{{' at position {}", - start).as_slice()) + start)[]) } Some(i) => i, }; self.chari = closer; - self.parse_hex_digits(self.slice(start, closer).as_slice()) + self.parse_hex_digits(self.slice(start, closer)[]) } // Parses a two-digit hex number. @@ -730,8 +729,7 @@ impl<'a> Parser<'a> { match num::from_str_radix::(s, 16) { Some(n) => Ok(Literal(try!(self.char_from_u32(n)), FLAG_EMPTY)), None => { - self.err(format!("Could not parse '{}' as hex number.", - s).as_slice()) + self.err(format!("Could not parse '{}' as hex number.", s)[]) } } } @@ -757,7 +755,7 @@ impl<'a> Parser<'a> { } if self.names.contains(&name) { return self.err(format!("Duplicate capture group name '{}'.", - name).as_slice()) + name)[]) } self.names.push(name.clone()); self.chari = closer; @@ -791,7 +789,7 @@ impl<'a> Parser<'a> { if sign < 0 { return self.err(format!( "Cannot negate flags twice in '{}'.", - self.slice(start, self.chari + 1)).as_slice()) + self.slice(start, self.chari + 1))[]) } sign = -1; saw_flag = false; @@ -802,7 +800,7 @@ impl<'a> Parser<'a> { if !saw_flag { return self.err(format!( "A valid flag does not follow negation in '{}'", - self.slice(start, self.chari + 1)).as_slice()) + self.slice(start, self.chari + 1))[]) } flags = flags ^ flags; } @@ -814,7 +812,7 @@ impl<'a> Parser<'a> { return Ok(()) } _ => return self.err(format!( - "Unrecognized flag '{}'.", self.cur()).as_slice()), + "Unrecognized flag '{}'.", self.cur())[]), } } } @@ -908,11 +906,11 @@ impl<'a> Parser<'a> { } fn parse_uint(&self, s: &str) -> Result { - match from_str::(s) { + match s.parse::() { Some(i) => Ok(i), None => { self.err(format!("Expected an unsigned integer but got '{}'.", - s).as_slice()) + s)[]) } } } @@ -922,8 +920,7 @@ impl<'a> Parser<'a> { Some(c) => Ok(c), None => { self.err(format!("Could not decode '{}' to unicode \ - character.", - n).as_slice()) + character.", n)[]) } } } diff --git a/src/libregex/re.rs b/src/libregex/re.rs index 151587e423a..4e23e92c77e 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -417,7 +417,7 @@ impl Regex { /// # extern crate regex; #[phase(plugin)] extern crate regex_macros; /// # fn main() { /// let re = regex!("[^01]+"); - /// assert_eq!(re.replace("1078910", "").as_slice(), "1010"); + /// assert_eq!(re.replace("1078910", ""), "1010"); /// # } /// ``` /// @@ -435,7 +435,7 @@ impl Regex { /// let result = re.replace("Springsteen, Bruce", |&: caps: &Captures| { /// format!("{} {}", caps.at(2).unwrap_or(""), caps.at(1).unwrap_or("")) /// }); - /// assert_eq!(result.as_slice(), "Bruce Springsteen"); + /// assert_eq!(result, "Bruce Springsteen"); /// # } /// ``` /// @@ -450,7 +450,7 @@ impl Regex { /// # fn main() { /// let re = regex!(r"(?P[^,\s]+),\s+(?P\S+)"); /// let result = re.replace("Springsteen, Bruce", "$first $last"); - /// assert_eq!(result.as_slice(), "Bruce Springsteen"); + /// assert_eq!(result, "Bruce Springsteen"); /// # } /// ``` /// @@ -469,7 +469,7 @@ impl Regex { /// /// let re = regex!(r"(?P[^,\s]+),\s+(\S+)"); /// let result = re.replace("Springsteen, Bruce", NoExpand("$2 $last")); - /// assert_eq!(result.as_slice(), "$2 $last"); + /// assert_eq!(result, "$2 $last"); /// # } /// ``` pub fn replace(&self, text: &str, rep: R) -> String { @@ -505,19 +505,19 @@ impl Regex { } let (s, e) = cap.pos(0).unwrap(); // captures only reports matches - new.push_str(text.slice(last_match, s)); - new.push_str(rep.reg_replace(&cap).as_slice()); + new.push_str(text[last_match..s]); + new.push_str(rep.reg_replace(&cap)[]); last_match = e; } - new.push_str(text.slice(last_match, text.len())); + new.push_str(text[last_match..text.len()]); return new; } /// Returns the original string of this regex. pub fn as_str<'a>(&'a self) -> &'a str { match *self { - Dynamic(ExDynamic { ref original, .. }) => original.as_slice(), - Native(ExNative { ref original, .. }) => original.as_slice(), + Dynamic(ExDynamic { ref original, .. }) => original[], + Native(ExNative { ref original, .. }) => original[], } } @@ -608,13 +608,13 @@ impl<'r, 't> Iterator<&'t str> for RegexSplits<'r, 't> { if self.last >= text.len() { None } else { - let s = text.slice(self.last, text.len()); + let s = text[self.last..text.len()]; self.last = text.len(); Some(s) } } Some((s, e)) => { - let matched = text.slice(self.last, s); + let matched = text[self.last..s]; self.last = e; Some(matched) } @@ -642,7 +642,7 @@ impl<'r, 't> Iterator<&'t str> for RegexSplitsN<'r, 't> { } else { self.cur += 1; if self.cur >= self.limit { - Some(text.slice(self.splits.last, text.len())) + Some(text[self.splits.last..text.len()]) } else { self.splits.next() } @@ -769,13 +769,13 @@ impl<'t> Captures<'t> { let pre = refs.at(1).unwrap_or(""); let name = refs.at(2).unwrap_or(""); format!("{}{}", pre, - match from_str::(name.as_slice()) { + match name.parse::() { None => self.name(name).unwrap_or("").to_string(), Some(i) => self.at(i).unwrap_or("").to_string(), }) }); let re = Regex::new(r"\$\$").unwrap(); - re.replace_all(text.as_slice(), NoExpand("$")) + re.replace_all(text[], NoExpand("$")) } /// Returns the number of captured groups. diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index fddd49c8d88..0fd69ea25bc 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -250,10 +250,12 @@ impl LintPass for TypeLimits { let (min, max) = float_ty_range(t); let lit_val: f64 = match lit.node { ast::LitFloat(ref v, _) | - ast::LitFloatUnsuffixed(ref v) => match from_str(v.get()) { - Some(f) => f, - None => return - }, + ast::LitFloatUnsuffixed(ref v) => { + match v.parse() { + Some(f) => f, + None => return + } + } _ => panic!() }; if lit_val < min || lit_val > max { @@ -507,7 +509,7 @@ impl BoxPointers { if n_uniq > 0 { let s = ty_to_string(cx.tcx, ty); let m = format!("type uses owned (Box type) pointers: {}", s); - cx.span_lint(BOX_POINTERS, span, m.as_slice()); + cx.span_lint(BOX_POINTERS, span, m[]); } } } @@ -587,7 +589,7 @@ impl LintPass for RawPointerDeriving { } fn check_item(&mut self, cx: &Context, item: &ast::Item) { - if !attr::contains_name(item.attrs.as_slice(), "automatically_derived") { + if !attr::contains_name(item.attrs[], "automatically_derived") { return } let did = match item.node { @@ -766,11 +768,11 @@ impl LintPass for UnusedResults { ty::ty_enum(did, _) => { if ast_util::is_local(did) { if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) { - warned |= check_must_use(cx, it.attrs.as_slice(), s.span); + warned |= check_must_use(cx, it.attrs[], s.span); } } else { csearch::get_item_attrs(&cx.sess().cstore, did, |attrs| { - warned |= check_must_use(cx, attrs.as_slice(), s.span); + warned |= check_must_use(cx, attrs[], s.span); }); } } @@ -792,7 +794,7 @@ impl LintPass for UnusedResults { msg.push_str(s.get()); } } - cx.span_lint(UNUSED_MUST_USE, sp, msg.as_slice()); + cx.span_lint(UNUSED_MUST_USE, sp, msg[]); return true; } } @@ -838,7 +840,7 @@ impl NonCamelCaseTypes { } else { format!("{} `{}` should have a camel case name such as `{}`", sort, s, c) }; - cx.span_lint(NON_CAMEL_CASE_TYPES, span, m.as_slice()); + cx.span_lint(NON_CAMEL_CASE_TYPES, span, m[]); } } } @@ -978,7 +980,7 @@ impl NonSnakeCase { if !is_snake_case(ident) { cx.span_lint(NON_SNAKE_CASE, span, format!("{} `{}` should have a snake case name such as `{}`", - sort, s, to_snake_case(s.get())).as_slice()); + sort, s, to_snake_case(s.get()))[]); } } } @@ -1065,7 +1067,7 @@ impl LintPass for NonUpperCaseGlobals { format!("static constant `{}` should have an uppercase name \ such as `{}`", s.get(), s.get().chars().map(|c| c.to_uppercase()) - .collect::().as_slice()).as_slice()); + .collect::()[])[]); } } _ => {} @@ -1082,7 +1084,7 @@ impl LintPass for NonUpperCaseGlobals { format!("static constant in pattern `{}` should have an uppercase \ name such as `{}`", s.get(), s.get().chars().map(|c| c.to_uppercase()) - .collect::().as_slice()).as_slice()); + .collect::()[])[]); } } _ => {} @@ -1107,7 +1109,7 @@ impl UnusedParens { if !necessary { cx.span_lint(UNUSED_PARENS, value.span, format!("unnecessary parentheses around {}", - msg).as_slice()) + msg)[]) } } @@ -1209,7 +1211,7 @@ impl LintPass for UnusedImportBraces { let m = format!("braces around {} is unnecessary", token::get_ident(*name).get()); cx.span_lint(UNUSED_IMPORT_BRACES, view_item.span, - m.as_slice()); + m[]); }, _ => () } @@ -1248,7 +1250,7 @@ impl LintPass for NonShorthandFieldPatterns { if ident.node.as_str() == fieldpat.node.ident.as_str() { cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, format!("the `{}:` in this pattern is redundant and can \ - be removed", ident.node.as_str()).as_slice()) + be removed", ident.node.as_str())[]) } } } @@ -1352,7 +1354,7 @@ impl LintPass for UnusedMut { fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { if let ast::ExprMatch(_, ref arms, _) = e.node { for a in arms.iter() { - self.check_unused_mut_pat(cx, a.pats.as_slice()) + self.check_unused_mut_pat(cx, a.pats[]) } } } @@ -1473,7 +1475,7 @@ impl MissingDoc { }); if !has_doc { cx.span_lint(MISSING_DOCS, sp, - format!("missing documentation for {}", desc).as_slice()); + format!("missing documentation for {}", desc)[]); } } } @@ -1487,7 +1489,7 @@ impl LintPass for MissingDoc { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { attr.check_name("doc") && match attr.meta_item_list() { None => false, - Some(l) => attr::contains_name(l.as_slice(), "hidden"), + Some(l) => attr::contains_name(l[], "hidden"), } }); self.doc_hidden_stack.push(doc_hidden); @@ -1509,7 +1511,7 @@ impl LintPass for MissingDoc { } fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) { - self.check_missing_docs_attrs(cx, None, krate.attrs.as_slice(), + self.check_missing_docs_attrs(cx, None, krate.attrs[], krate.span, "crate"); } @@ -1523,7 +1525,7 @@ impl LintPass for MissingDoc { ast::ItemTy(..) => "a type alias", _ => return }; - self.check_missing_docs_attrs(cx, Some(it.id), it.attrs.as_slice(), + self.check_missing_docs_attrs(cx, Some(it.id), it.attrs[], it.span, desc); } @@ -1536,13 +1538,13 @@ impl LintPass for MissingDoc { // Otherwise, doc according to privacy. This will also check // doc for default methods defined on traits. - self.check_missing_docs_attrs(cx, Some(m.id), m.attrs.as_slice(), + self.check_missing_docs_attrs(cx, Some(m.id), m.attrs[], m.span, "a method"); } } fn check_ty_method(&mut self, cx: &Context, tm: &ast::TypeMethod) { - self.check_missing_docs_attrs(cx, Some(tm.id), tm.attrs.as_slice(), + self.check_missing_docs_attrs(cx, Some(tm.id), tm.attrs[], tm.span, "a type method"); } @@ -1552,14 +1554,14 @@ impl LintPass for MissingDoc { let cur_struct_def = *self.struct_def_stack.last() .expect("empty struct_def_stack"); self.check_missing_docs_attrs(cx, Some(cur_struct_def), - sf.node.attrs.as_slice(), sf.span, + sf.node.attrs[], sf.span, "a struct field") } } } fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) { - self.check_missing_docs_attrs(cx, Some(v.node.id), v.node.attrs.as_slice(), + self.check_missing_docs_attrs(cx, Some(v.node.id), v.node.attrs[], v.span, "a variant"); assert!(!self.in_variant); self.in_variant = true; @@ -1675,7 +1677,7 @@ impl Stability { _ => format!("use of {} item", label) }; - cx.span_lint(lint, span, msg.as_slice()); + cx.span_lint(lint, span, msg[]); } fn is_internal(&self, cx: &Context, span: Span) -> bool { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index d8d9d653e62..ffae485364a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -104,7 +104,7 @@ impl LintStore { } pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] { - self.lints.as_slice() + self.lints[] } pub fn get_lint_groups<'t>(&'t self) -> Vec<(&'static str, Vec, bool)> { @@ -124,11 +124,11 @@ impl LintStore { match (sess, from_plugin) { // We load builtin lints first, so a duplicate is a compiler bug. // Use early_error when handling -W help with no crate. - (None, _) => early_error(msg.as_slice()), - (Some(sess), false) => sess.bug(msg.as_slice()), + (None, _) => early_error(msg[]), + (Some(sess), false) => sess.bug(msg[]), // A duplicate name from a plugin is a user error. - (Some(sess), true) => sess.err(msg.as_slice()), + (Some(sess), true) => sess.err(msg[]), } } @@ -149,11 +149,11 @@ impl LintStore { match (sess, from_plugin) { // We load builtin lints first, so a duplicate is a compiler bug. // Use early_error when handling -W help with no crate. - (None, _) => early_error(msg.as_slice()), - (Some(sess), false) => sess.bug(msg.as_slice()), + (None, _) => early_error(msg[]), + (Some(sess), false) => sess.bug(msg[]), // A duplicate name from a plugin is a user error. - (Some(sess), true) => sess.err(msg.as_slice()), + (Some(sess), true) => sess.err(msg[]), } } } @@ -260,8 +260,8 @@ impl LintStore { let warning = format!("lint {} has been renamed to {}", lint_name, new_name); match span { - Some(span) => sess.span_warn(span, warning.as_slice()), - None => sess.warn(warning.as_slice()), + Some(span) => sess.span_warn(span, warning[]), + None => sess.warn(warning[]), }; Some(lint_id) } @@ -271,13 +271,13 @@ impl LintStore { pub fn process_command_line(&mut self, sess: &Session) { for &(ref lint_name, level) in sess.opts.lint_opts.iter() { - match self.find_lint(lint_name.as_slice(), sess, None) { + match self.find_lint(lint_name[], sess, None) { Some(lint_id) => self.set_level(lint_id, (level, CommandLine)), None => { match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone())) .collect::>>() - .get(lint_name.as_slice()) { + .get(lint_name[]) { Some(v) => { v.iter() .map(|lint_id: &LintId| @@ -285,7 +285,7 @@ impl LintStore { .collect::>(); } None => sess.err(format!("unknown {} flag: {}", - level.as_str(), lint_name).as_slice()), + level.as_str(), lint_name)[]), } } } @@ -396,10 +396,10 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint, if level == Forbid { level = Deny; } match (level, span) { - (Warn, Some(sp)) => sess.span_warn(sp, msg.as_slice()), - (Warn, None) => sess.warn(msg.as_slice()), - (Deny, Some(sp)) => sess.span_err(sp, msg.as_slice()), - (Deny, None) => sess.err(msg.as_slice()), + (Warn, Some(sp)) => sess.span_warn(sp, msg[]), + (Warn, None) => sess.warn(msg[]), + (Deny, Some(sp)) => sess.span_err(sp, msg[]), + (Deny, None) => sess.err(msg[]), _ => sess.bug("impossible level in raw_emit_lint"), } @@ -492,7 +492,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> { None => { self.span_lint(builtin::UNKNOWN_LINTS, span, format!("unknown `{}` attribute: `{}`", - level.as_str(), lint_name).as_slice()); + level.as_str(), lint_name)[]); continue; } } @@ -508,7 +508,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> { self.tcx.sess.span_err(span, format!("{}({}) overruled by outer forbid({})", level.as_str(), lint_name, - lint_name).as_slice()); + lint_name)[]); } else if now != level { let src = self.lints.get_level_source(lint_id).1; self.level_stack.push((lint_id, (now, src))); @@ -543,7 +543,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_item(&mut self, it: &ast::Item) { - self.with_lint_attrs(it.attrs.as_slice(), |cx| { + self.with_lint_attrs(it.attrs[], |cx| { run_lints!(cx, check_item, it); cx.visit_ids(|v| v.visit_item(it)); visit::walk_item(cx, it); @@ -551,14 +551,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } fn visit_foreign_item(&mut self, it: &ast::ForeignItem) { - self.with_lint_attrs(it.attrs.as_slice(), |cx| { + self.with_lint_attrs(it.attrs[], |cx| { run_lints!(cx, check_foreign_item, it); visit::walk_foreign_item(cx, it); }) } fn visit_view_item(&mut self, i: &ast::ViewItem) { - self.with_lint_attrs(i.attrs.as_slice(), |cx| { + self.with_lint_attrs(i.attrs[], |cx| { run_lints!(cx, check_view_item, i); cx.visit_ids(|v| v.visit_view_item(i)); visit::walk_view_item(cx, i); @@ -584,7 +584,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { body: &'v ast::Block, span: Span, id: ast::NodeId) { match fk { visit::FkMethod(_, _, m) => { - self.with_lint_attrs(m.attrs.as_slice(), |cx| { + self.with_lint_attrs(m.attrs[], |cx| { run_lints!(cx, check_fn, fk, decl, body, span, id); cx.visit_ids(|v| { v.visit_fn(fk, decl, body, span, id); @@ -600,7 +600,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } fn visit_ty_method(&mut self, t: &ast::TypeMethod) { - self.with_lint_attrs(t.attrs.as_slice(), |cx| { + self.with_lint_attrs(t.attrs[], |cx| { run_lints!(cx, check_ty_method, t); visit::walk_ty_method(cx, t); }) @@ -617,14 +617,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } fn visit_struct_field(&mut self, s: &ast::StructField) { - self.with_lint_attrs(s.node.attrs.as_slice(), |cx| { + self.with_lint_attrs(s.node.attrs[], |cx| { run_lints!(cx, check_struct_field, s); visit::walk_struct_field(cx, s); }) } fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) { - self.with_lint_attrs(v.node.attrs.as_slice(), |cx| { + self.with_lint_attrs(v.node.attrs[], |cx| { run_lints!(cx, check_variant, v, g); visit::walk_variant(cx, v, g); run_lints!(cx, check_variant_post, v, g); @@ -718,7 +718,7 @@ impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> { None => {} Some(lints) => { for (lint_id, span, msg) in lints.into_iter() { - self.span_lint(lint_id.lint, span, msg.as_slice()) + self.span_lint(lint_id.lint, span, msg[]) } } } @@ -764,7 +764,7 @@ pub fn check_crate(tcx: &ty::ctxt, let mut cx = Context::new(tcx, krate, exported_items); // Visit the whole crate. - cx.with_lint_attrs(krate.attrs.as_slice(), |cx| { + cx.with_lint_attrs(krate.attrs[], |cx| { cx.visit_id(ast::CRATE_NODE_ID); cx.visit_ids(|v| { v.visited_outermost = true; @@ -784,7 +784,7 @@ pub fn check_crate(tcx: &ty::ctxt, for &(lint, span, ref msg) in v.iter() { tcx.sess.span_bug(span, format!("unprocessed lint {} at {}: {}", - lint.as_str(), tcx.map.node_to_string(*id), *msg).as_slice()) + lint.as_str(), tcx.map.node_to_string(*id), *msg)[]) } } diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 323b084afdc..98b57511957 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -95,11 +95,11 @@ fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) { for (name, dupes) in map.into_iter() { if dupes.len() == 1 { continue } diag.handler().warn( - format!("using multiple versions of crate `{}`", name).as_slice()); + format!("using multiple versions of crate `{}`", name)[]); for dupe in dupes.into_iter() { let data = cstore.get_crate_data(dupe); diag.span_note(data.span, "used here"); - loader::note_crate_name(diag, data.name().as_slice()); + loader::note_crate_name(diag, data.name()[]); } } } @@ -117,7 +117,7 @@ fn should_link(i: &ast::ViewItem) -> bool { i.attrs.iter().all(|attr| { attr.name().get() != "phase" || attr.meta_item_list().map_or(false, |phases| { - attr::contains_name(phases.as_slice(), "link") + attr::contains_name(phases[], "link") }) }) } @@ -131,8 +131,8 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) { Some(info) => { let (cnum, _, _) = resolve_crate(e, &None, - info.ident.as_slice(), - info.name.as_slice(), + info.ident[], + info.name[], None, i.span); e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum); @@ -157,7 +157,7 @@ fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option { let name = match *path_opt { Some((ref path_str, _)) => { let name = path_str.get().to_string(); - validate_crate_name(Some(e.sess), name.as_slice(), + validate_crate_name(Some(e.sess), name[], Some(i.span)); name } @@ -188,7 +188,7 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { for c in s.chars() { if c.is_alphanumeric() { continue } if c == '_' || c == '-' { continue } - err(format!("invalid character `{}` in crate name: `{}`", c, s).as_slice()); + err(format!("invalid character `{}` in crate name: `{}`", c, s)[]); } match sess { Some(sess) => sess.abort_if_errors(), @@ -246,7 +246,7 @@ fn visit_item(e: &Env, i: &ast::Item) { } else { e.sess.span_err(m.span, format!("unknown kind: `{}`", - k).as_slice()); + k)[]); cstore::NativeUnknown } } @@ -327,7 +327,7 @@ fn existing_match(e: &Env, name: &str, match e.sess.opts.externs.get(name) { Some(locs) => { let found = locs.iter().any(|l| { - let l = fs::realpath(&Path::new(l.as_slice())).ok(); + let l = fs::realpath(&Path::new(l[])).ok(); l == source.dylib || l == source.rlib }); if found { @@ -405,7 +405,7 @@ fn resolve_crate<'a>(e: &mut Env, crate_name: name, hash: hash.map(|a| &*a), filesearch: e.sess.target_filesearch(), - triple: e.sess.opts.target_triple.as_slice(), + triple: e.sess.opts.target_triple[], root: root, rejected_via_hash: vec!(), rejected_via_triple: vec!(), @@ -431,8 +431,8 @@ fn resolve_crate_deps(e: &mut Env, decoder::get_crate_deps(cdata).iter().map(|dep| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); let (local_cnum, _, _) = resolve_crate(e, root, - dep.name.as_slice(), - dep.name.as_slice(), + dep.name[], + dep.name[], Some(&dep.hash), span); (dep.cnum, local_cnum) @@ -455,14 +455,14 @@ impl<'a> PluginMetadataReader<'a> { pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata { let info = extract_crate_info(&self.env, krate).unwrap(); - let target_triple = self.env.sess.opts.target_triple.as_slice(); + let target_triple = self.env.sess.opts.target_triple[]; let is_cross = target_triple != config::host_triple(); let mut should_link = info.should_link && !is_cross; let mut load_ctxt = loader::Context { sess: self.env.sess, span: krate.span, - ident: info.ident.as_slice(), - crate_name: info.name.as_slice(), + ident: info.ident[], + crate_name: info.name[], hash: None, filesearch: self.env.sess.host_filesearch(), triple: config::host_triple(), @@ -483,7 +483,7 @@ impl<'a> PluginMetadataReader<'a> { let message = format!("crate `{}` contains a plugin_registrar fn but \ only a version for triple `{}` could be found (need {})", info.ident, target_triple, config::host_triple()); - self.env.sess.span_err(krate.span, message.as_slice()); + self.env.sess.span_err(krate.span, message[]); // need to abort now because the syntax expansion // code will shortly attempt to load and execute // code from the found library. @@ -502,7 +502,7 @@ impl<'a> PluginMetadataReader<'a> { let message = format!("plugin crate `{}` only found in rlib format, \ but must be available in dylib format", info.ident); - self.env.sess.span_err(krate.span, message.as_slice()); + self.env.sess.span_err(krate.span, message[]); // No need to abort because the loading code will just ignore this // empty dylib. } @@ -511,11 +511,11 @@ impl<'a> PluginMetadataReader<'a> { macros: macros, registrar_symbol: registrar, }; - if should_link && existing_match(&self.env, info.name.as_slice(), + if should_link && existing_match(&self.env, info.name[], None).is_none() { // register crate now to avoid double-reading metadata - register_crate(&mut self.env, &None, info.ident.as_slice(), - info.name.as_slice(), krate.span, library); + register_crate(&mut self.env, &None, info.ident[], + info.name[], krate.span, library); } pc } diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index b702f4925d8..13342bf82cf 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -95,7 +95,7 @@ pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec // FIXME #1920: This path is not always correct if the crate is not linked // into the root namespace. - let mut r = vec![ast_map::PathMod(token::intern(cdata.name.as_slice()))]; + let mut r = vec![ast_map::PathMod(token::intern(cdata.name[]))]; r.push_all(path.as_slice()); r } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index d8168814c6c..b869501237c 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -221,7 +221,7 @@ fn each_reexport(d: rbml::Doc, f: F) -> bool where fn variant_disr_val(d: rbml::Doc) -> Option { reader::maybe_get_doc(d, tag_disr_val).and_then(|val_doc| { reader::with_doc_data(val_doc, |data| { - str::from_utf8(data).and_then(from_str) + str::from_utf8(data).ok().and_then(|s| s.parse()) }) }) } @@ -1160,7 +1160,7 @@ pub fn get_crate_deps(data: &[u8]) -> Vec { } reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| { let name = docstr(depdoc, tag_crate_dep_crate_name); - let hash = Svh::new(docstr(depdoc, tag_crate_dep_hash).as_slice()); + let hash = Svh::new(docstr(depdoc, tag_crate_dep_hash)[]); deps.push(CrateDep { cnum: crate_num, name: name, @@ -1345,7 +1345,7 @@ pub fn get_dylib_dependency_formats(cdata: Cmd) if spec.len() == 0 { continue } let cnum = spec.split(':').nth(0).unwrap(); let link = spec.split(':').nth(1).unwrap(); - let cnum = from_str(cnum).unwrap(); + let cnum = cnum.parse().unwrap(); let cnum = match cdata.cnum_map.get(&cnum) { Some(&n) => n, None => panic!("didn't find a crate in the cnum_map") diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index e5dae926db9..6782b3a7481 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -95,7 +95,7 @@ fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Ident) { } pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) { - rbml_w.wr_tagged_str(tag_def_id, def_to_string(id).as_slice()); + rbml_w.wr_tagged_str(tag_def_id, def_to_string(id)[]); } #[deriving(Clone)] @@ -154,7 +154,7 @@ fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) { rbml_w.end_tag(); rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(s.as_slice()); + rbml_w.wr_str(s[]); rbml_w.end_tag(); } @@ -264,7 +264,7 @@ fn encode_symbol(ecx: &EncodeContext, } None => { ecx.diag.handler().bug( - format!("encode_symbol: id not found {}", id).as_slice()); + format!("encode_symbol: id not found {}", id)[]); } } rbml_w.end_tag(); @@ -332,8 +332,8 @@ fn encode_enum_variant_info(ecx: &EncodeContext, encode_name(rbml_w, variant.node.name.name); encode_parent_item(rbml_w, local_def(id)); encode_visibility(rbml_w, variant.node.vis); - encode_attributes(rbml_w, variant.node.attrs.as_slice()); - encode_repr_attrs(rbml_w, ecx, variant.node.attrs.as_slice()); + encode_attributes(rbml_w, variant.node.attrs[]); + encode_repr_attrs(rbml_w, ecx, variant.node.attrs[]); let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id)); encode_stability(rbml_w, stab); @@ -344,9 +344,9 @@ fn encode_enum_variant_info(ecx: &EncodeContext, let fields = ty::lookup_struct_fields(ecx.tcx, def_id); let idx = encode_info_for_struct(ecx, rbml_w, - fields.as_slice(), + fields[], index); - encode_struct_fields(rbml_w, fields.as_slice(), def_id); + encode_struct_fields(rbml_w, fields[], def_id); encode_index(rbml_w, idx, write_i64); } } @@ -386,12 +386,12 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder, exp.name, token::get_name(method_name)); rbml_w.start_tag(tag_items_data_item_reexport); rbml_w.start_tag(tag_items_data_item_reexport_def_id); - rbml_w.wr_str(def_to_string(method_def_id).as_slice()); + rbml_w.wr_str(def_to_string(method_def_id)[]); rbml_w.end_tag(); rbml_w.start_tag(tag_items_data_item_reexport_name); rbml_w.wr_str(format!("{}::{}", exp.name, - token::get_name(method_name)).as_slice()); + token::get_name(method_name))[]); rbml_w.end_tag(); rbml_w.end_tag(); } @@ -529,7 +529,7 @@ fn encode_reexports(ecx: &EncodeContext, id); rbml_w.start_tag(tag_items_data_item_reexport); rbml_w.start_tag(tag_items_data_item_reexport_def_id); - rbml_w.wr_str(def_to_string(exp.def_id).as_slice()); + rbml_w.wr_str(def_to_string(exp.def_id)[]); rbml_w.end_tag(); rbml_w.start_tag(tag_items_data_item_reexport_name); rbml_w.wr_str(exp.name.as_str()); @@ -562,13 +562,13 @@ fn encode_info_for_mod(ecx: &EncodeContext, // Encode info about all the module children. for item in md.items.iter() { rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(def_to_string(local_def(item.id)).as_slice()); + rbml_w.wr_str(def_to_string(local_def(item.id))[]); rbml_w.end_tag(); each_auxiliary_node_id(&**item, |auxiliary_node_id| { rbml_w.start_tag(tag_mod_child); rbml_w.wr_str(def_to_string(local_def( - auxiliary_node_id)).as_slice()); + auxiliary_node_id))[]); rbml_w.end_tag(); true }); @@ -580,7 +580,7 @@ fn encode_info_for_mod(ecx: &EncodeContext, did, ecx.tcx.map.node_to_string(did)); rbml_w.start_tag(tag_mod_impl); - rbml_w.wr_str(def_to_string(local_def(did)).as_slice()); + rbml_w.wr_str(def_to_string(local_def(did))[]); rbml_w.end_tag(); } } @@ -615,7 +615,7 @@ fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) { ast::Public => 'y', ast::Inherited => 'i', }; - rbml_w.wr_str(ch.to_string().as_slice()); + rbml_w.wr_str(ch.to_string()[]); rbml_w.end_tag(); } @@ -627,7 +627,7 @@ fn encode_unboxed_closure_kind(rbml_w: &mut Encoder, ty::FnMutUnboxedClosureKind => 'm', ty::FnOnceUnboxedClosureKind => 'o', }; - rbml_w.wr_str(ch.to_string().as_slice()); + rbml_w.wr_str(ch.to_string()[]); rbml_w.end_tag(); } @@ -788,7 +788,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, rbml_w.end_tag(); rbml_w.wr_tagged_str(tag_region_param_def_def_id, - def_to_string(param.def_id).as_slice()); + def_to_string(param.def_id)[]); rbml_w.wr_tagged_u64(tag_region_param_def_space, param.space.to_uint() as u64); @@ -864,9 +864,9 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_path(rbml_w, impl_path.chain(Some(elem).into_iter())); match ast_item_opt { Some(&ast::MethodImplItem(ref ast_method)) => { - encode_attributes(rbml_w, ast_method.attrs.as_slice()); + encode_attributes(rbml_w, ast_method.attrs[]); let any_types = !pty.generics.types.is_empty(); - if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) { + if any_types || is_default_impl || should_inline(ast_method.attrs[]) { encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id), ast_item_opt.unwrap())); } @@ -909,7 +909,7 @@ fn encode_info_for_associated_type(ecx: &EncodeContext, match typedef_opt { None => {} Some(typedef) => { - encode_attributes(rbml_w, typedef.attrs.as_slice()); + encode_attributes(rbml_w, typedef.attrs[]); encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx, typedef.id)); } @@ -1043,7 +1043,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_path(rbml_w, path); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); - encode_attributes(rbml_w, item.attrs.as_slice()); + encode_attributes(rbml_w, item.attrs[]); rbml_w.end_tag(); } ast::ItemConst(_, _) => { @@ -1069,8 +1069,8 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(rbml_w, item.ident.name); encode_path(rbml_w, path); - encode_attributes(rbml_w, item.attrs.as_slice()); - if tps_len > 0u || should_inline(item.attrs.as_slice()) { + encode_attributes(rbml_w, item.attrs[]); + if tps_len > 0u || should_inline(item.attrs[]) { encode_inlined_item(ecx, rbml_w, IIItemRef(item)); } if tps_len == 0 { @@ -1086,7 +1086,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_info_for_mod(ecx, rbml_w, m, - item.attrs.as_slice(), + item.attrs[], item.id, path, item.ident, @@ -1103,7 +1103,7 @@ fn encode_info_for_item(ecx: &EncodeContext, // Encode all the items in this module. for foreign_item in fm.items.iter() { rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice()); + rbml_w.wr_str(def_to_string(local_def(foreign_item.id))[]); rbml_w.end_tag(); } encode_visibility(rbml_w, vis); @@ -1131,8 +1131,8 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_item_variances(rbml_w, ecx, item.id); encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(rbml_w, item.ident.name); - encode_attributes(rbml_w, item.attrs.as_slice()); - encode_repr_attrs(rbml_w, ecx, item.attrs.as_slice()); + encode_attributes(rbml_w, item.attrs[]); + encode_repr_attrs(rbml_w, ecx, item.attrs[]); for v in (*enum_definition).variants.iter() { encode_variant_id(rbml_w, local_def(v.node.id)); } @@ -1149,7 +1149,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_enum_variant_info(ecx, rbml_w, item.id, - (*enum_definition).variants.as_slice(), + (*enum_definition).variants[], index); } ast::ItemStruct(ref struct_def, _) => { @@ -1161,7 +1161,7 @@ fn encode_info_for_item(ecx: &EncodeContext, class itself */ let idx = encode_info_for_struct(ecx, rbml_w, - fields.as_slice(), + fields[], index); /* Index the class*/ @@ -1175,16 +1175,16 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_item_variances(rbml_w, ecx, item.id); encode_name(rbml_w, item.ident.name); - encode_attributes(rbml_w, item.attrs.as_slice()); + encode_attributes(rbml_w, item.attrs[]); encode_path(rbml_w, path.clone()); encode_stability(rbml_w, stab); encode_visibility(rbml_w, vis); - encode_repr_attrs(rbml_w, ecx, item.attrs.as_slice()); + encode_repr_attrs(rbml_w, ecx, item.attrs[]); /* Encode def_ids for each field and method for methods, write all the stuff get_trait_method needs to know*/ - encode_struct_fields(rbml_w, fields.as_slice(), def_id); + encode_struct_fields(rbml_w, fields[], def_id); encode_inlined_item(ecx, rbml_w, IIItemRef(item)); @@ -1216,7 +1216,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_family(rbml_w, 'i'); encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(rbml_w, item.ident.name); - encode_attributes(rbml_w, item.attrs.as_slice()); + encode_attributes(rbml_w, item.attrs[]); encode_unsafety(rbml_w, unsafety); match ty.node { ast::TyPath(ref path, _) if path.segments @@ -1319,7 +1319,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics); encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref); encode_name(rbml_w, item.ident.name); - encode_attributes(rbml_w, item.attrs.as_slice()); + encode_attributes(rbml_w, item.attrs[]); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() { @@ -1337,7 +1337,7 @@ fn encode_info_for_item(ecx: &EncodeContext, rbml_w.end_tag(); rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(def_to_string(method_def_id.def_id()).as_slice()); + rbml_w.wr_str(def_to_string(method_def_id.def_id())[]); rbml_w.end_tag(); } encode_path(rbml_w, path.clone()); @@ -1422,14 +1422,14 @@ fn encode_info_for_item(ecx: &EncodeContext, }; match trait_item { &ast::RequiredMethod(ref m) => { - encode_attributes(rbml_w, m.attrs.as_slice()); + encode_attributes(rbml_w, m.attrs[]); encode_trait_item(rbml_w); encode_item_sort(rbml_w, 'r'); encode_method_argument_names(rbml_w, &*m.decl); } &ast::ProvidedMethod(ref m) => { - encode_attributes(rbml_w, m.attrs.as_slice()); + encode_attributes(rbml_w, m.attrs[]); encode_trait_item(rbml_w); encode_item_sort(rbml_w, 'p'); encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item)); @@ -1438,7 +1438,7 @@ fn encode_info_for_item(ecx: &EncodeContext, &ast::TypeTraitItem(ref associated_type) => { encode_attributes(rbml_w, - associated_type.attrs.as_slice()); + associated_type.attrs[]); encode_item_sort(rbml_w, 't'); } } @@ -1802,7 +1802,7 @@ fn encode_macro_def(ecx: &EncodeContext, let def = ecx.tcx.sess.codemap().span_to_snippet(*span) .expect("Unable to find source for macro"); rbml_w.start_tag(tag_macro_def); - rbml_w.wr_str(def.as_slice()); + rbml_w.wr_str(def[]); rbml_w.end_tag(); } @@ -1849,7 +1849,7 @@ fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) { fn visit_struct_field(&mut self, field: &ast::StructField) { self.rbml_w.start_tag(tag_struct_field); self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id); - encode_attributes(self.rbml_w, field.node.attrs.as_slice()); + encode_attributes(self.rbml_w, field.node.attrs[]); self.rbml_w.end_tag(); } } @@ -1921,13 +1921,13 @@ fn encode_misc_info(ecx: &EncodeContext, rbml_w.start_tag(tag_misc_info_crate_items); for item in krate.module.items.iter() { rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(def_to_string(local_def(item.id)).as_slice()); + rbml_w.wr_str(def_to_string(local_def(item.id))[]); rbml_w.end_tag(); each_auxiliary_node_id(&**item, |auxiliary_node_id| { rbml_w.start_tag(tag_mod_child); rbml_w.wr_str(def_to_string(local_def( - auxiliary_node_id)).as_slice()); + auxiliary_node_id))[]); rbml_w.end_tag(); true }); @@ -2096,17 +2096,17 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, let mut rbml_w = writer::Encoder::new(wr); - encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name.as_slice()); + encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name[]); encode_crate_triple(&mut rbml_w, tcx.sess .opts .target_triple - .as_slice()); + []); encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash); encode_dylib_dependency_formats(&mut rbml_w, &ecx); let mut i = rbml_w.writer.tell().unwrap(); - encode_attributes(&mut rbml_w, krate.attrs.as_slice()); + encode_attributes(&mut rbml_w, krate.attrs[]); stats.attr_bytes = rbml_w.writer.tell().unwrap() - i; i = rbml_w.writer.tell().unwrap(); diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index bc34b0b45e9..5f554eb9c1e 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -316,14 +316,14 @@ impl<'a> Context<'a> { &Some(ref r) => format!("{} which `{}` depends on", message, r.ident) }; - self.sess.span_err(self.span, message.as_slice()); + self.sess.span_err(self.span, message[]); if self.rejected_via_triple.len() > 0 { let mismatches = self.rejected_via_triple.iter(); for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() { self.sess.fileline_note(self.span, format!("crate `{}`, path #{}, triple {}: {}", - self.ident, i+1, got, path.display()).as_slice()); + self.ident, i+1, got, path.display())[]); } } if self.rejected_via_hash.len() > 0 { @@ -333,7 +333,7 @@ impl<'a> Context<'a> { for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() { self.sess.fileline_note(self.span, format!("crate `{}` path {}{}: {}", - self.ident, "#", i+1, path.display()).as_slice()); + self.ident, "#", i+1, path.display())[]); } match self.root { &None => {} @@ -341,7 +341,7 @@ impl<'a> Context<'a> { for (i, path) in r.paths().iter().enumerate() { self.sess.fileline_note(self.span, format!("crate `{}` path #{}: {}", - r.ident, i+1, path.display()).as_slice()); + r.ident, i+1, path.display())[]); } } } @@ -387,7 +387,7 @@ impl<'a> Context<'a> { None => return FileDoesntMatch, Some(file) => file, }; - let (hash, rlib) = if file.starts_with(rlib_prefix.as_slice()) && + let (hash, rlib) = if file.starts_with(rlib_prefix[]) && file.ends_with(".rlib") { (file.slice(rlib_prefix.len(), file.len() - ".rlib".len()), true) @@ -448,26 +448,26 @@ impl<'a> Context<'a> { _ => { self.sess.span_err(self.span, format!("multiple matching crates for `{}`", - self.crate_name).as_slice()); + self.crate_name)[]); self.sess.note("candidates:"); for lib in libraries.iter() { match lib.dylib { Some(ref p) => { self.sess.note(format!("path: {}", - p.display()).as_slice()); + p.display())[]); } None => {} } match lib.rlib { Some(ref p) => { self.sess.note(format!("path: {}", - p.display()).as_slice()); + p.display())[]); } None => {} } let data = lib.metadata.as_slice(); let name = decoder::get_crate_name(data); - note_crate_name(self.sess.diagnostic(), name.as_slice()); + note_crate_name(self.sess.diagnostic(), name[]); } None } @@ -521,11 +521,11 @@ impl<'a> Context<'a> { format!("multiple {} candidates for `{}` \ found", flavor, - self.crate_name).as_slice()); + self.crate_name)[]); self.sess.span_note(self.span, format!(r"candidate #1: {}", ret.as_ref().unwrap() - .display()).as_slice()); + .display())[]); error = 1; ret = None; } @@ -533,7 +533,7 @@ impl<'a> Context<'a> { error += 1; self.sess.span_note(self.span, format!(r"candidate #{}: {}", error, - lib.display()).as_slice()); + lib.display())[]); continue } *slot = Some(metadata); @@ -608,17 +608,17 @@ impl<'a> Context<'a> { let mut rlibs = HashSet::new(); let mut dylibs = HashSet::new(); { - let mut locs = locs.iter().map(|l| Path::new(l.as_slice())).filter(|loc| { + let mut locs = locs.iter().map(|l| Path::new(l[])).filter(|loc| { if !loc.exists() { sess.err(format!("extern location for {} does not exist: {}", - self.crate_name, loc.display()).as_slice()); + self.crate_name, loc.display())[]); return false; } let file = match loc.filename_str() { Some(file) => file, None => { sess.err(format!("extern location for {} is not a file: {}", - self.crate_name, loc.display()).as_slice()); + self.crate_name, loc.display())[]); return false; } }; @@ -626,12 +626,12 @@ impl<'a> Context<'a> { return true } else { let (ref prefix, ref suffix) = dylibname; - if file.starts_with(prefix.as_slice()) && file.ends_with(suffix.as_slice()) { + if file.starts_with(prefix[]) && file.ends_with(suffix[]) { return true } } sess.err(format!("extern location for {} is of an unknown type: {}", - self.crate_name, loc.display()).as_slice()); + self.crate_name, loc.display())[]); false }); @@ -664,7 +664,7 @@ impl<'a> Context<'a> { } pub fn note_crate_name(diag: &SpanHandler, name: &str) { - diag.handler().note(format!("crate name: {}", name).as_slice()); + diag.handler().note(format!("crate name: {}", name)[]); } impl ArchiveMetadata { diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 9d3a2c1d667..7683506f0f4 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -233,7 +233,7 @@ fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore { '&' => ty::RegionTraitStore(parse_region(st, conv), parse_mutability(st)), c => { st.tcx.sess.bug(format!("parse_trait_store(): bad input '{}'", - c).as_slice()) + c)[]) } } } @@ -287,7 +287,7 @@ fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion { } '[' => { let def = parse_def(st, RegionParameter, |x,y| conv(x,y)); - let ident = token::str_to_ident(parse_str(st, ']').as_slice()); + let ident = token::str_to_ident(parse_str(st, ']')[]); ty::BrNamed(def, ident.name) } 'f' => { @@ -318,7 +318,7 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region { assert_eq!(next(st), '|'); let index = parse_uint(st); assert_eq!(next(st), '|'); - let nm = token::str_to_ident(parse_str(st, ']').as_slice()); + let nm = token::str_to_ident(parse_str(st, ']')[]); ty::ReEarlyBound(node_id, space, index, nm.name) } 'f' => { @@ -560,7 +560,7 @@ fn parse_abi_set(st: &mut PState) -> abi::Abi { assert_eq!(next(st), '['); scan(st, |c| c == ']', |bytes| { let abi_str = str::from_utf8(bytes).unwrap(); - abi::lookup(abi_str.as_slice()).expect(abi_str) + abi::lookup(abi_str[]).expect(abi_str) }) } @@ -639,12 +639,12 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId { let crate_part = buf[0u..colon_idx]; let def_part = buf[colon_idx + 1u..len]; - let crate_num = match str::from_utf8(crate_part).and_then(from_str::) { + let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| s.parse::()) { Some(cn) => cn as ast::CrateNum, None => panic!("internal error: parse_def_id: crate number expected, found {}", crate_part) }; - let def_num = match str::from_utf8(def_part).and_then(from_str::) { + let def_num = match str::from_utf8(def_part).ok().and_then(|s| s.parse::()) { Some(dn) => dn as ast::NodeId, None => panic!("internal error: parse_def_id: id expected, found {}", def_part) diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index 6b90bcd60e7..060e2f67faf 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -48,7 +48,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) None => { tcx.sess.span_bug(ast_ty.span, format!("unbound path {}", - path.repr(tcx)).as_slice()) + path.repr(tcx))[]) } Some(&d) => d }; diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 69fbd59fd92..ce86d6805b2 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -132,7 +132,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata, // Do an Option dance to use the path after it is moved below. let s = ast_map::path_to_string(ast_map::Values(path.iter())); path_as_str = Some(s); - path_as_str.as_ref().map(|x| x.as_slice()) + path_as_str.as_ref().map(|x| x[]) }); let mut ast_dsr = reader::Decoder::new(ast_doc); let from_id_range = Decodable::decode(&mut ast_dsr).unwrap(); @@ -1876,7 +1876,7 @@ fn decode_side_tables(dcx: &DecodeContext, None => { dcx.tcx.sess.bug( format!("unknown tag found in side tables: {:x}", - tag).as_slice()); + tag)[]); } Some(value) => { let val_doc = entry_doc.get(c::tag_table_val as uint); @@ -1961,7 +1961,7 @@ fn decode_side_tables(dcx: &DecodeContext, _ => { dcx.tcx.sess.bug( format!("unknown tag found in side tables: {:x}", - tag).as_slice()); + tag)[]); } } } diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 82bed254031..2d50757782d 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -362,7 +362,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let mut cond_exit = discr_exit; for arm in arms.iter() { cond_exit = self.add_dummy_node(&[cond_exit]); // 2 - let pats_exit = self.pats_any(arm.pats.as_slice(), + let pats_exit = self.pats_any(arm.pats[], cond_exit); // 3 let guard_exit = self.opt_expr(&arm.guard, pats_exit); // 4 @@ -617,14 +617,14 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.tcx.sess.span_bug( expr.span, format!("no loop scope for id {}", - loop_id).as_slice()); + loop_id)[]); } r => { self.tcx.sess.span_bug( expr.span, format!("bad entry `{}` in def_map for label", - r).as_slice()); + r)[]); } } } diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index e33f44967f1..13bd22a67c4 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -50,7 +50,7 @@ fn replace_newline_with_backslash_l(s: String) -> String { } impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { - fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name.as_slice()).unwrap() } + fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name[]).unwrap() } fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> { dot::Id::new(format!("N{}", i.node_id())).unwrap() @@ -83,8 +83,7 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { let s = self.ast_map.node_to_string(node_id); // left-aligns the lines let s = replace_newline_with_backslash_l(s); - label.push_str(format!("exiting scope_{} {}", i, - s.as_slice()).as_slice()); + label.push_str(format!("exiting scope_{} {}", i, s[])[]); } dot::EscStr(label.into_cow()) } diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index cb454f94dc7..5a08d7c179d 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -74,13 +74,11 @@ impl<'a> CheckLoopVisitor<'a> { Loop => {} Closure => { self.sess.span_err(span, - format!("`{}` inside of a closure", - name).as_slice()); + format!("`{}` inside of a closure", name)[]); } Normal => { self.sess.span_err(span, - format!("`{}` outside of loop", - name).as_slice()); + format!("`{}` outside of loop", name)[]); } } } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 9a94eb97931..da1bd09ceff 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -162,7 +162,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) { // First, check legality of move bindings. check_legality_of_move_bindings(cx, arm.guard.is_some(), - arm.pats.as_slice()); + arm.pats[]); // Second, if there is a guard on each arm, make sure it isn't // assigning or borrowing anything mutably. @@ -199,7 +199,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) { } // Fourth, check for unreachable arms. - check_arms(cx, inlined_arms.as_slice(), source); + check_arms(cx, inlined_arms[], source); // Finally, check if the whole match expression is exhaustive. // Check for empty enum, because is_useful only works on inhabited types. @@ -231,7 +231,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) { pat.span, format!("refutable pattern in `for` loop binding: \ `{}` not covered", - pat_to_string(uncovered_pat)).as_slice()); + pat_to_string(uncovered_pat))[]); }); // Check legality of move bindings. @@ -304,7 +304,7 @@ fn check_arms(cx: &MatchCheckCtxt, for pat in pats.iter() { let v = vec![&**pat]; - match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) { + match is_useful(cx, &seen, v[], LeaveOutWitness) { NotUseful => { match source { ast::MatchSource::IfLetDesugar { .. } => { @@ -356,7 +356,7 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat { fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) { match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) { UsefulWithWitness(pats) => { - let witness = match pats.as_slice() { + let witness = match pats[] { [ref witness] => &**witness, [] => DUMMY_WILD_PAT, _ => unreachable!() @@ -610,7 +610,7 @@ fn is_useful(cx: &MatchCheckCtxt, UsefulWithWitness(pats) => UsefulWithWitness({ let arity = constructor_arity(cx, &c, left_ty); let mut result = { - let pat_slice = pats.as_slice(); + let pat_slice = pats[]; let subpats = Vec::from_fn(arity, |i| { pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p) }); @@ -657,10 +657,10 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix, witness: WitnessPreference) -> Usefulness { let arity = constructor_arity(cx, &ctor, lty); let matrix = Matrix(m.iter().filter_map(|r| { - specialize(cx, r.as_slice(), &ctor, 0u, arity) + specialize(cx, r[], &ctor, 0u, arity) }).collect()); match specialize(cx, v, &ctor, 0u, arity) { - Some(v) => is_useful(cx, &matrix, v.as_slice(), witness), + Some(v) => is_useful(cx, &matrix, v[], witness), None => NotUseful } } @@ -1047,7 +1047,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, format!("binding pattern {} is not an \ identifier: {}", p.id, - p.node).as_slice()); + p.node)[]); } } } diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs index 21e94d69366..6ff34d62500 100644 --- a/src/librustc/middle/check_static.rs +++ b/src/librustc/middle/check_static.rs @@ -112,7 +112,7 @@ impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> { }; self.tcx.sess.span_err(e.span, format!("mutable statics are not allowed \ - to have {}", suffix).as_slice()); + to have {}", suffix)[]); } fn check_static_type(&self, e: &ast::Expr) { @@ -168,7 +168,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> { ty::ty_enum(did, _) if ty::has_dtor(self.tcx, did) => { self.tcx.sess.span_err(e.span, format!("{} are not allowed to have \ - destructors", self.msg()).as_slice()) + destructors", self.msg())[]) } _ => {} } @@ -232,7 +232,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> { let msg = "constants cannot refer to other statics, \ insert an intermediate constant \ instead"; - self.tcx.sess.span_err(e.span, msg.as_slice()); + self.tcx.sess.span_err(e.span, msg[]); } _ => {} } diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index 90242a3252e..c36b4aa7f23 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -105,7 +105,7 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> { _ => { self.sess.span_err(e.span, format!("expected item, found {}", - self.ast_map.node_to_string(def_id.node)).as_slice()); + self.ast_map.node_to_string(def_id.node))[]); return; }, } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 62f1a30f8e7..5b89912dd03 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -117,7 +117,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt, None => None, Some(ast_map::NodeItem(it)) => match it.node { ast::ItemEnum(ast::EnumDef { ref variants }, _) => { - variant_expr(variants.as_slice(), variant_def.node) + variant_expr(variants[], variant_def.node) } _ => None }, @@ -138,7 +138,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt, // NOTE this doesn't do the right thing, it compares inlined // NodeId's to the original variant_def's NodeId, but they // come from different crates, so they will likely never match. - variant_expr(variants.as_slice(), variant_def.node).map(|e| e.id) + variant_expr(variants[], variant_def.node).map(|e| e.id) } _ => None }, @@ -364,7 +364,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P { pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val { match eval_const_expr_partial(tcx, e) { Ok(r) => r, - Err(s) => tcx.sess.span_fatal(e.span, s.as_slice()) + Err(s) => tcx.sess.span_fatal(e.span, s[]) } } @@ -603,7 +603,7 @@ pub fn lit_to_const(lit: &ast::Lit) -> const_val { ast::LitInt(n, ast::UnsignedIntLit(_)) => const_uint(n), ast::LitFloat(ref n, _) | ast::LitFloatUnsuffixed(ref n) => { - const_float(from_str::(n.get()).unwrap() as f64) + const_float(n.get().parse::().unwrap() as f64) } ast::LitBool(b) => const_bool(b) } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 17ebd1b94a7..a2d417ca345 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -311,7 +311,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let mut t = on_entry.to_vec(); self.apply_gen_kill(cfgidx, t.as_mut_slice()); temp_bits = t; - temp_bits.as_slice() + temp_bits[] } }; debug!("{} each_bit_for_node({}, cfgidx={}) bits={}", @@ -420,7 +420,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let bits = self.kills.slice_mut(start, end); debug!("{} add_kills_from_flow_exits flow_exit={} bits={} [before]", self.analysis_name, flow_exit, mut_bits_to_string(bits)); - bits.clone_from_slice(orig_kills.as_slice()); + bits.clone_from_slice(orig_kills[]); debug!("{} add_kills_from_flow_exits flow_exit={} bits={} [after]", self.analysis_name, flow_exit, mut_bits_to_string(bits)); } @@ -553,7 +553,7 @@ fn bits_to_string(words: &[uint]) -> String { let mut v = word; for _ in range(0u, uint::BYTES) { result.push(sep); - result.push_str(format!("{:02x}", v & 0xFF).as_slice()); + result.push_str(format!("{:02x}", v & 0xFF)[]); v >>= 8; sep = '-'; } diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 3cb628c2e65..6b56ece28bd 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -118,7 +118,7 @@ fn calculate_type(sess: &session::Session, let src = sess.cstore.get_used_crate_source(cnum).unwrap(); if src.rlib.is_some() { return } sess.err(format!("dependency `{}` not found in rlib format", - data.name).as_slice()); + data.name)[]); }); return Vec::new(); } @@ -197,7 +197,7 @@ fn calculate_type(sess: &session::Session, match kind { cstore::RequireStatic => "rlib", cstore::RequireDynamic => "dylib", - }).as_slice()); + })[]); } } } @@ -222,7 +222,7 @@ fn add_library(sess: &session::Session, let data = sess.cstore.get_crate_data(cnum); sess.err(format!("cannot satisfy dependencies so `{}` only \ shows up once", - data.name).as_slice()); + data.name)[]); sess.help("having upstream crates all available in one format \ will likely make this go away"); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index abc3c8d0d8f..4ee0064b0e6 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -678,7 +678,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { self.tcx().sess.span_bug( callee.span, format!("unexpected callee type {}", - callee_ty.repr(self.tcx())).as_slice()) + callee_ty.repr(self.tcx()))[]) } }; match overloaded_call_type { @@ -869,7 +869,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { ty::ty_rptr(r, ref m) => (m.mutbl, r), _ => self.tcx().sess.span_bug(expr.span, format!("bad overloaded deref type {}", - method_ty.repr(self.tcx())).as_slice()) + method_ty.repr(self.tcx()))[]) }; let bk = ty::BorrowKind::from_mutbl(m); self.delegate.borrow(expr.id, expr.span, cmt, @@ -1186,7 +1186,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // pattern. let msg = format!("Pattern has unexpected type: {}", def); - tcx.sess.span_bug(pat.span, msg.as_slice()) + tcx.sess.span_bug(pat.span, msg[]) } Some(def) => { @@ -1195,7 +1195,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // should not resolve. let msg = format!("Pattern has unexpected def: {}", def); - tcx.sess.span_bug(pat.span, msg.as_slice()) + tcx.sess.span_bug(pat.span, msg[]) } } } diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 82ddbcee5a7..11ab44ba09f 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -141,7 +141,7 @@ pub trait Combine<'tcx> { for _ in a_regions.iter() { invariance.push(ty::Invariant); } - invariance.as_slice() + invariance[] } }; @@ -411,7 +411,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, format!("{}: bot and var types should have been handled ({},{})", this.tag(), a.repr(this.infcx().tcx), - b.repr(this.infcx().tcx)).as_slice()); + b.repr(this.infcx().tcx))[]); } (&ty::ty_err, _) | (_, &ty::ty_err) => { diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index b4c1c0b396b..0ea3d415ec5 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -199,9 +199,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ref trace_origins, ref same_regions) => { if !same_regions.is_empty() { - self.report_processed_errors(var_origins.as_slice(), - trace_origins.as_slice(), - same_regions.as_slice()); + self.report_processed_errors(var_origins[], + trace_origins[], + same_regions[]); } } } @@ -374,7 +374,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { format!("{}: {} ({})", message_root_str, expected_found_str, - ty::type_err_to_str(self.tcx, terr)).as_slice()); + ty::type_err_to_str(self.tcx, terr))[]); match trace.origin { infer::MatchExpressionArm(_, arm_span) => @@ -438,13 +438,13 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { origin.span(), format!( "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx)).as_slice()); + param_ty.user_string(self.tcx))[]); self.tcx.sess.span_help( origin.span(), format!( "consider adding an explicit lifetime bound `{}: {}`...", param_ty.user_string(self.tcx), - sub.user_string(self.tcx)).as_slice()); + sub.user_string(self.tcx))[]); } ty::ReStatic => { @@ -453,12 +453,12 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { origin.span(), format!( "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx)).as_slice()); + param_ty.user_string(self.tcx))[]); self.tcx.sess.span_help( origin.span(), format!( "consider adding an explicit lifetime bound `{}: 'static`...", - param_ty.user_string(self.tcx)).as_slice()); + param_ty.user_string(self.tcx))[]); } _ => { @@ -467,16 +467,16 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { origin.span(), format!( "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx)).as_slice()); + param_ty.user_string(self.tcx))[]); self.tcx.sess.span_help( origin.span(), format!( "consider adding an explicit lifetime bound to `{}`", - param_ty.user_string(self.tcx)).as_slice()); + param_ty.user_string(self.tcx))[]); note_and_explain_region( self.tcx, format!("the parameter type `{}` must be valid for ", - param_ty.user_string(self.tcx)).as_slice(), + param_ty.user_string(self.tcx))[], sub, "..."); } @@ -518,7 +518,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ty::local_var_name_str(self.tcx, upvar_id.var_id) .get() - .to_string()).as_slice()); + .to_string())[]); note_and_explain_region( self.tcx, "...the borrowed pointer is valid for ", @@ -530,7 +530,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ty::local_var_name_str(self.tcx, upvar_id.var_id) .get() - .to_string()).as_slice(), + .to_string())[], sup, ""); } @@ -576,7 +576,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { outlive the enclosing closure", ty::local_var_name_str(self.tcx, id).get() - .to_string()).as_slice()); + .to_string())[]); note_and_explain_region( self.tcx, "captured variable is valid for ", @@ -618,7 +618,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span, format!("the type `{}` does not fulfill the \ required lifetime", - self.ty_to_string(ty)).as_slice()); + self.ty_to_string(ty))[]); note_and_explain_region(self.tcx, "type must outlive ", sub, @@ -644,7 +644,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span, format!("the type `{}` (provided as the value of \ a type parameter) is not valid at this point", - self.ty_to_string(ty)).as_slice()); + self.ty_to_string(ty))[]); note_and_explain_region(self.tcx, "type must outlive ", sub, @@ -710,7 +710,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span, format!("type of expression contains references \ that are not valid during the expression: `{}`", - self.ty_to_string(t)).as_slice()); + self.ty_to_string(t))[]); note_and_explain_region( self.tcx, "type is only valid for ", @@ -732,7 +732,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span, format!("in type `{}`, reference has a longer lifetime \ than the data it references", - self.ty_to_string(ty)).as_slice()); + self.ty_to_string(ty))[]); note_and_explain_region( self.tcx, "the pointer is valid for ", @@ -857,7 +857,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { let (fn_decl, generics, unsafety, ident, expl_self, span) = node_inner.expect("expect item fn"); let taken = lifetimes_in_scope(self.tcx, scope_id); - let life_giver = LifeGiver::with_taken(taken.as_slice()); + let life_giver = LifeGiver::with_taken(taken[]); let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self, generics, same_regions, &life_giver); let (fn_decl, expl_self, generics) = rebuilder.rebuild(); @@ -933,7 +933,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } expl_self_opt = self.rebuild_expl_self(expl_self_opt, lifetime, &anon_nums, ®ion_names); - inputs = self.rebuild_args_ty(inputs.as_slice(), lifetime, + inputs = self.rebuild_args_ty(inputs[], lifetime, &anon_nums, ®ion_names); output = self.rebuild_output(&output, lifetime, &anon_nums, ®ion_names); ty_params = self.rebuild_ty_params(ty_params, lifetime, @@ -968,7 +968,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { names.push(lt_name); } names.sort(); - let name = token::str_to_ident(names[0].as_slice()).name; + let name = token::str_to_ident(names[0][]).name; return (name_to_dummy_lifetime(name), Kept); } return (self.life_giver.give_lifetime(), Fresh); @@ -1219,7 +1219,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { .sess .fatal(format!( "unbound path {}", - pprust::path_to_string(path)).as_slice()) + pprust::path_to_string(path))[]) } Some(&d) => d }; @@ -1417,7 +1417,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { opt_explicit_self, generics); let msg = format!("consider using an explicit lifetime \ parameter as shown: {}", suggested_fn); - self.tcx.sess.span_help(span, msg.as_slice()); + self.tcx.sess.span_help(span, msg[]); } fn report_inference_failure(&self, @@ -1455,7 +1455,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { var_origin.span(), format!("cannot infer an appropriate lifetime{} \ due to conflicting requirements", - var_description).as_slice()); + var_description)[]); } fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) { @@ -1500,7 +1500,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { self.tcx.sess.span_note( trace.origin.span(), format!("...so that {} ({})", - desc, values_str).as_slice()); + desc, values_str)[]); } None => { // Really should avoid printing this error at @@ -1509,7 +1509,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { // doing right now. - nmatsakis self.tcx.sess.span_note( trace.origin.span(), - format!("...so that {}", desc).as_slice()); + format!("...so that {}", desc)[]); } } } @@ -1526,7 +1526,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { "...so that closure can access `{}`", ty::local_var_name_str(self.tcx, upvar_id.var_id) .get() - .to_string()).as_slice()) + .to_string())[]) } infer::InfStackClosure(span) => { self.tcx.sess.span_note( @@ -1551,7 +1551,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { does not outlive the enclosing closure", ty::local_var_name_str( self.tcx, - id).get().to_string()).as_slice()); + id).get().to_string())[]); } infer::IndexSlice(span) => { self.tcx.sess.span_note( @@ -1595,7 +1595,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { span, format!("...so type `{}` of expression is valid during the \ expression", - self.ty_to_string(t)).as_slice()); + self.ty_to_string(t))[]); } infer::BindingTypeIsNotValidAtDecl(span) => { self.tcx.sess.span_note( @@ -1607,14 +1607,14 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { span, format!("...so that the reference type `{}` \ does not outlive the data it points at", - self.ty_to_string(ty)).as_slice()); + self.ty_to_string(ty))[]); } infer::RelateParamBound(span, t) => { self.tcx.sess.span_note( span, format!("...so that the type `{}` \ will meet the declared lifetime bounds", - self.ty_to_string(t)).as_slice()); + self.ty_to_string(t))[]); } infer::RelateDefaultParamBound(span, t) => { self.tcx.sess.span_note( @@ -1622,13 +1622,13 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { format!("...so that type parameter \ instantiated with `{}`, \ will meet its declared lifetime bounds", - self.ty_to_string(t)).as_slice()); + self.ty_to_string(t))[]); } infer::RelateRegionParamBound(span) => { self.tcx.sess.span_note( span, format!("...so that the declared lifetime parameter bounds \ - are satisfied").as_slice()); + are satisfied")[]); } } } @@ -1677,7 +1677,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt, Some(node) => match node { ast_map::NodeItem(item) => match item.node { ast::ItemFn(_, _, _, ref gen, _) => { - taken.push_all(gen.lifetimes.as_slice()); + taken.push_all(gen.lifetimes[]); None }, _ => None @@ -1685,7 +1685,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt, ast_map::NodeImplItem(ii) => { match *ii { ast::MethodImplItem(ref m) => { - taken.push_all(m.pe_generics().lifetimes.as_slice()); + taken.push_all(m.pe_generics().lifetimes[]); Some(m.id) } ast::TypeImplItem(_) => None, @@ -1744,10 +1744,10 @@ impl LifeGiver { let mut lifetime; loop { let mut s = String::from_str("'"); - s.push_str(num_to_string(self.counter.get()).as_slice()); + s.push_str(num_to_string(self.counter.get())[]); if !self.taken.contains(&s) { lifetime = name_to_dummy_lifetime( - token::str_to_ident(s.as_slice()).name); + token::str_to_ident(s[]).name); self.generated.borrow_mut().push(lifetime); break; } diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index ab0f98ec74a..2a19f37e7d4 100644 --- a/src/librustc/middle/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/infer/higher_ranked/mod.rs @@ -189,7 +189,7 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C span, format!("region {} is not associated with \ any bound region from A!", - r0).as_slice()) + r0)[]) } } @@ -339,7 +339,7 @@ fn var_ids<'tcx, T: Combine<'tcx>>(combiner: &T, r => { combiner.infcx().tcx.sess.span_bug( combiner.trace().origin.span(), - format!("found non-region-vid: {}", r).as_slice()); + format!("found non-region-vid: {}", r)[]); } }).collect() } diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 25eadae5b92..6d031c86507 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -992,7 +992,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess.span_err(sp, format!("{}{}", mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty), - error_str).as_slice()); + error_str)[]); for err in err.iter() { ty::note_and_explain_type_err(self.tcx, *err) diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index 3e55f6fa896..0ca1a593ce7 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -60,7 +60,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, } let requested_node : Option = - os::getenv("RUST_REGION_GRAPH_NODE").and_then(|s|from_str(s.as_slice())); + os::getenv("RUST_REGION_GRAPH_NODE").and_then(|s| s.parse()); if requested_node.is_some() && requested_node != Some(subject_node) { return; diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index bcaf39cc8db..661f7e56429 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { origin.span(), format!("cannot relate bound region: {} <= {}", sub.repr(self.tcx), - sup.repr(self.tcx)).as_slice()); + sup.repr(self.tcx))[]); } (_, ReStatic) => { // all regions are subregions of static, so we can ignore this @@ -724,7 +724,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { self.tcx.sess.bug( format!("cannot relate bound region: LUB({}, {})", a.repr(self.tcx), - b.repr(self.tcx)).as_slice()); + b.repr(self.tcx))[]); } (ReStatic, _) | (_, ReStatic) => { @@ -741,7 +741,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { format!("lub_concrete_regions invoked with \ non-concrete regions: {}, {}", a, - b).as_slice()); + b)[]); } (ReFree(ref fr), ReScope(s_id)) | @@ -824,7 +824,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { self.tcx.sess.bug( format!("cannot relate bound region: GLB({}, {})", a.repr(self.tcx), - b.repr(self.tcx)).as_slice()); + b.repr(self.tcx))[]); } (ReStatic, r) | (r, ReStatic) => { @@ -844,7 +844,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { format!("glb_concrete_regions invoked with \ non-concrete regions: {}, {}", a, - b).as_slice()); + b)[]); } (ReFree(ref fr), ReScope(s_id)) | @@ -965,7 +965,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { self.expansion(var_data.as_mut_slice()); self.contraction(var_data.as_mut_slice()); let values = - self.extract_values_and_collect_conflicts(var_data.as_slice(), + self.extract_values_and_collect_conflicts(var_data[], errors); self.collect_concrete_region_errors(&values, errors); values @@ -1403,7 +1403,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { for var {}, lower_bounds={}, upper_bounds={}", node_idx, lower_bounds.repr(self.tcx), - upper_bounds.repr(self.tcx)).as_slice()); + upper_bounds.repr(self.tcx))[]); } fn collect_error_for_contracting_node( @@ -1447,7 +1447,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { format!("collect_error_for_contracting_node() could not find error \ for var {}, upper_bounds={}", node_idx, - upper_bounds.repr(self.tcx)).as_slice()); + upper_bounds.repr(self.tcx))[]); } fn collect_concrete_regions(&self, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b76d798941e..798daf8d541 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -323,7 +323,7 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { self.tcx .sess .span_bug(span, format!("no variable registered for id {}", - node_id).as_slice()); + node_id)[]); } } } @@ -594,7 +594,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.ir.tcx.sess.span_bug( span, format!("no live node registered for node {}", - node_id).as_slice()); + node_id)[]); } } } @@ -1129,7 +1129,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Uninteresting cases: just propagate in rev exec order ast::ExprVec(ref exprs) => { - self.propagate_through_exprs(exprs.as_slice(), succ) + self.propagate_through_exprs(exprs[], succ) } ast::ExprRepeat(ref element, ref count) => { @@ -1154,7 +1154,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } else { succ }; - let succ = self.propagate_through_exprs(args.as_slice(), succ); + let succ = self.propagate_through_exprs(args[], succ); self.propagate_through_expr(&**f, succ) } @@ -1167,11 +1167,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } else { succ }; - self.propagate_through_exprs(args.as_slice(), succ) + self.propagate_through_exprs(args[], succ) } ast::ExprTup(ref exprs) => { - self.propagate_through_exprs(exprs.as_slice(), succ) + self.propagate_through_exprs(exprs[], succ) } ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op) => { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index dce75579ca0..1c2ceea7716 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -238,7 +238,7 @@ pub fn deref_kind<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> deref_kind { None => { tcx.sess.bug( format!("deref_kind() invoked on non-derefable type {}", - ty_to_string(tcx, t)).as_slice()); + ty_to_string(tcx, t))[]); } } } @@ -635,7 +635,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { span, format!("Upvar of non-closure {} - {}", fn_node_id, - ty.repr(self.tcx())).as_slice()); + ty.repr(self.tcx()))[]); } } } @@ -917,7 +917,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { self.tcx().sess.span_bug( node.span(), format!("Explicit deref of non-derefable type: {}", - base_cmt.ty.repr(self.tcx())).as_slice()); + base_cmt.ty.repr(self.tcx()))[]); } } } @@ -996,7 +996,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { self.tcx().sess.span_bug( elt.span(), format!("Explicit index of non-index type `{}`", - base_cmt.ty.repr(self.tcx())).as_slice()); + base_cmt.ty.repr(self.tcx()))[]); } } } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index f8b4ae73a1c..6f63ae166fe 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -615,10 +615,10 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { match result { None => true, Some((span, msg, note)) => { - self.tcx.sess.span_err(span, msg.as_slice()); + self.tcx.sess.span_err(span, msg[]); match note { Some((span, msg)) => { - self.tcx.sess.span_note(span, msg.as_slice()) + self.tcx.sess.span_note(span, msg[]) } None => {}, } @@ -720,7 +720,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { UnnamedField(idx) => format!("field #{} of {} is private", idx + 1, struct_desc), }; - self.tcx.sess.span_err(span, msg.as_slice()); + self.tcx.sess.span_err(span, msg[]); } // Given the ID of a method, checks to ensure it's in scope. @@ -742,7 +742,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { method_id, None, format!("method `{}`", - string).as_slice())); + string)[])); } // Checks that a path is in scope. @@ -759,9 +759,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { self.ensure_public(span, def, Some(origdid), - format!("{} `{}`", - tyname, - name).as_slice()) + format!("{} `{}`", tyname, name)[]) }; match self.last_private_map[path_id] { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 38d3b859c9d..4d83075480b 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -50,7 +50,7 @@ fn generics_require_inlining(generics: &ast::Generics) -> bool { // monomorphized or it was marked with `#[inline]`. This will only return // true for functions. fn item_might_be_inlined(item: &ast::Item) -> bool { - if attributes_specify_inlining(item.attrs.as_slice()) { + if attributes_specify_inlining(item.attrs[]) { return true } @@ -65,7 +65,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool { fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method, impl_src: ast::DefId) -> bool { - if attributes_specify_inlining(method.attrs.as_slice()) || + if attributes_specify_inlining(method.attrs[]) || generics_require_inlining(method.pe_generics()) { return true } @@ -202,7 +202,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { ast::MethodImplItem(ref method) => { if generics_require_inlining(method.pe_generics()) || attributes_specify_inlining( - method.attrs.as_slice()) { + method.attrs[]) { true } else { let impl_did = self.tcx @@ -249,7 +249,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { None => { self.tcx.sess.bug(format!("found unmapped ID in worklist: \ {}", - search_item).as_slice()) + search_item)[]) } } } @@ -341,7 +341,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { .bug(format!("found unexpected thingy in worklist: {}", self.tcx .map - .node_to_string(search_item)).as_slice()) + .node_to_string(search_item))[]) } } } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index be191801626..bc9dc6b399d 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -409,7 +409,7 @@ impl<'a> LifetimeContext<'a> { self.sess.span_err( lifetime_ref.span, format!("use of undeclared lifetime name `{}`", - token::get_name(lifetime_ref.name)).as_slice()); + token::get_name(lifetime_ref.name))[]); } fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &Vec) { @@ -423,7 +423,7 @@ impl<'a> LifetimeContext<'a> { lifetime.lifetime.span, format!("illegal lifetime parameter name: `{}`", token::get_name(lifetime.lifetime.name)) - .as_slice()); + []); } } @@ -437,7 +437,7 @@ impl<'a> LifetimeContext<'a> { format!("lifetime name `{}` declared twice in \ the same scope", token::get_name(lifetime_j.lifetime.name)) - .as_slice()); + []); } } diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 30a47ff9132..a5e8e4695af 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -620,7 +620,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { (space={}, index={})", region_name.as_str(), self.root_ty.repr(self.tcx()), - space, i).as_slice()); + space, i)[]); } } } @@ -677,7 +677,7 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> { p.space, p.idx, self.root_ty.repr(self.tcx()), - self.substs.repr(self.tcx())).as_slice()); + self.substs.repr(self.tcx()))[]); } }; diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index 9804f6d222a..d48685ce27d 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -154,7 +154,7 @@ pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { ty::ty_err => { tcx.sess.bug( format!("ty_is_local invoked on unexpected type: {}", - ty.repr(tcx)).as_slice()) + ty.repr(tcx))[]) } } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 8ba28b61006..2b42849a87b 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -709,7 +709,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let all_bounds = util::transitive_bounds( - self.tcx(), caller_trait_refs.as_slice()); + self.tcx(), caller_trait_refs[]); let matching_bounds = all_bounds.filter( @@ -762,7 +762,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().sess.span_bug( obligation.cause.span, format!("No entry for unboxed closure: {}", - closure_def_id.repr(self.tcx())).as_slice()); + closure_def_id.repr(self.tcx()))[]); } }; @@ -1281,7 +1281,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().sess.bug( format!( "asked to assemble builtin bounds of unexpected type: {}", - self_ty.repr(self.tcx())).as_slice()); + self_ty.repr(self.tcx()))[]); } }; @@ -1436,7 +1436,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().sess.span_bug( obligation.cause.span, format!("builtin bound for {} was ambig", - obligation.repr(self.tcx())).as_slice()); + obligation.repr(self.tcx()))[]); } } } @@ -1554,7 +1554,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().sess.span_bug( obligation.cause.span, format!("Fn pointer candidate for inappropriate self type: {}", - self_ty.repr(self.tcx())).as_slice()); + self_ty.repr(self.tcx()))[]); } }; @@ -1595,7 +1595,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().sess.span_bug( obligation.cause.span, format!("No entry for unboxed closure: {}", - closure_def_id.repr(self.tcx())).as_slice()); + closure_def_id.repr(self.tcx()))[]); } }; @@ -1692,8 +1692,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().sess.bug( format!("Impl {} was matchable against {} but now is not", impl_def_id.repr(self.tcx()), - obligation.repr(self.tcx())) - .as_slice()); + obligation.repr(self.tcx()))[]); } } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 50a6fb9d0ca..edaf2f16721 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1891,7 +1891,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { _ => { cx.sess.bug(format!("ParameterEnvironment::from_item(): \ `{}` is not an item", - cx.map.node_to_string(id)).as_slice()) + cx.map.node_to_string(id))[]) } } } @@ -1960,7 +1960,7 @@ impl UnboxedClosureKind { }; match result { Ok(trait_did) => trait_did, - Err(err) => cx.sess.fatal(err.as_slice()), + Err(err) => cx.sess.fatal(err[]), } } } @@ -2596,7 +2596,7 @@ pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { ty_str => mk_mach_uint(ast::TyU8), ty_open(ty) => sequence_element_type(cx, ty), _ => cx.sess.bug(format!("sequence_element_type called on non-sequence value: {}", - ty_to_string(cx, ty)).as_slice()), + ty_to_string(cx, ty))[]), } } @@ -2972,7 +2972,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { ty_struct(did, ref substs) => { let flds = struct_fields(cx, did, substs); let mut res = - TypeContents::union(flds.as_slice(), + TypeContents::union(flds[], |f| tc_mt(cx, f.mt, cache)); if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) { @@ -2989,21 +2989,21 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { // FIXME(#14449): `borrowed_contents` below assumes `&mut` // unboxed closure. let upvars = unboxed_closure_upvars(cx, did, substs); - TypeContents::union(upvars.as_slice(), + TypeContents::union(upvars[], |f| tc_ty(cx, f.ty, cache)) | borrowed_contents(r, MutMutable) } ty_tup(ref tys) => { - TypeContents::union(tys.as_slice(), + TypeContents::union(tys[], |ty| tc_ty(cx, *ty, cache)) } ty_enum(did, ref substs) => { let variants = substd_enum_variants(cx, did, substs); let mut res = - TypeContents::union(variants.as_slice(), |variant| { - TypeContents::union(variant.args.as_slice(), + TypeContents::union(variants[], |variant| { + TypeContents::union(variant.args[], |arg_ty| { tc_ty(cx, *arg_ty, cache) }) @@ -3068,7 +3068,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { kind_bounds_to_contents( cx, tp_def.bounds.builtin_bounds, - tp_def.bounds.trait_bounds.as_slice()) + tp_def.bounds.trait_bounds[]) } ty_infer(_) => { @@ -3658,7 +3658,7 @@ pub fn close_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { ty_open(ty) => mk_rptr(cx, ReStatic, mt {ty: ty, mutbl:ast::MutImmutable}), _ => cx.sess.bug(format!("Trying to close a non-open type {}", - ty_to_string(cx, ty)).as_slice()) + ty_to_string(cx, ty))[]) } } @@ -3759,7 +3759,7 @@ pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) Some(ty) => ty.clone(), None => cx.sess.bug( format!("node_id_to_trait_ref: no trait ref for node `{}`", - cx.map.node_to_string(id)).as_slice()) + cx.map.node_to_string(id))[]) } } @@ -3772,7 +3772,7 @@ pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> { Some(ty) => ty, None => cx.sess.bug( format!("node_id_to_type: no type for node `{}`", - cx.map.node_to_string(id)).as_slice()) + cx.map.node_to_string(id))[]) } } @@ -3865,7 +3865,7 @@ pub fn ty_region(tcx: &ctxt, tcx.sess.span_bug( span, format!("ty_region() invoked on an inappropriate ty: {}", - s).as_slice()); + s)[]); } } } @@ -3926,11 +3926,11 @@ pub fn expr_span(cx: &ctxt, id: NodeId) -> Span { Some(f) => { cx.sess.bug(format!("Node id {} is not an expr: {}", id, - f).as_slice()); + f)[]); } None => { cx.sess.bug(format!("Node id {} is not present \ - in the node map", id).as_slice()); + in the node map", id)[]); } } } @@ -3946,14 +3946,14 @@ pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString { cx.sess.bug( format!("Variable id {} maps to {}, not local", id, - pat).as_slice()); + pat)[]); } } } r => { cx.sess.bug(format!("Variable id {} maps to {}, not local", id, - r).as_slice()); + r)[]); } } } @@ -3996,7 +3996,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, cx.sess.bug( format!("add_env adjustment on non-bare-fn: \ {}", - b).as_slice()); + b)[]); } } } @@ -4024,7 +4024,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, {}", i, ty_to_string(cx, adjusted_ty)) - .as_slice()); + []); } } } @@ -4087,7 +4087,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>, } _ => cx.sess.span_bug(span, format!("UnsizeLength with bad sty: {}", - ty_to_string(cx, ty)).as_slice()) + ty_to_string(cx, ty))[]) }, &UnsizeStruct(box ref k, tp_index) => match ty.sty { ty_struct(did, ref substs) => { @@ -4099,7 +4099,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>, } _ => cx.sess.span_bug(span, format!("UnsizeStruct with bad sty: {}", - ty_to_string(cx, ty)).as_slice()) + ty_to_string(cx, ty))[]) }, &UnsizeVtable(TyTrait { ref principal, bounds }, _) => { mk_trait(cx, (*principal).clone(), bounds) @@ -4112,7 +4112,7 @@ pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def { Some(&def) => def, None => { tcx.sess.span_bug(expr.span, format!( - "no def-map entry for expr {}", expr.id).as_slice()); + "no def-map entry for expr {}", expr.id)[]); } } } @@ -4206,7 +4206,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { expr.span, format!("uncategorized def for expr {}: {}", expr.id, - def).as_slice()); + def)[]); } } } @@ -4331,7 +4331,7 @@ pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field]) token::get_name(name), fields.iter() .map(|f| token::get_name(f.name).get().to_string()) - .collect::>()).as_slice()); + .collect::>())[]); } pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem]) @@ -4565,7 +4565,7 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) match item.node { ItemTrait(_, _, _, _, ref ms) => { let (_, p) = - ast_util::split_trait_methods(ms.as_slice()); + ast_util::split_trait_methods(ms[]); p.iter() .map(|m| { match impl_or_trait_item( @@ -4584,14 +4584,14 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) _ => { cx.sess.bug(format!("provided_trait_methods: `{}` is \ not a trait", - id).as_slice()) + id)[]) } } } _ => { cx.sess.bug(format!("provided_trait_methods: `{}` is not a \ trait", - id).as_slice()) + id)[]) } } } else { @@ -4827,7 +4827,7 @@ impl<'tcx> VariantInfo<'tcx> { }, ast::StructVariantKind(ref struct_def) => { - let fields: &[StructField] = struct_def.fields.as_slice(); + let fields: &[StructField] = struct_def.fields[]; assert!(fields.len() > 0); @@ -4978,7 +4978,7 @@ pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) cx.sess .span_err(e.span, format!("expected constant: {}", - *err).as_slice()); + *err)[]); } }, None => {} @@ -5258,7 +5258,7 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec { _ => { cx.sess.bug( format!("ID not mapped to struct fields: {}", - cx.map.node_to_string(did.node)).as_slice()); + cx.map.node_to_string(did.node))[]); } } } else { @@ -5291,7 +5291,7 @@ pub fn struct_fields<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &Substs<'tc pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec> { v.iter().enumerate().map(|(i, &f)| { field { - name: token::intern(i.to_string().as_slice()), + name: token::intern(i.to_string()[]), mt: mt { ty: f, mutbl: MutImmutable @@ -5470,7 +5470,7 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint { }; tcx.sess.span_err(count_expr.span, format!( "expected positive integer for repeat count, found {}", - found).as_slice()); + found)[]); } Err(_) => { let found = match count_expr.node { @@ -5485,7 +5485,7 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint { }; tcx.sess.span_err(count_expr.span, format!( "expected constant integer for repeat count, found {}", - found).as_slice()); + found)[]); } } 0 @@ -6244,7 +6244,7 @@ pub fn with_freevars(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where { match tcx.freevars.borrow().get(&fid) { None => f(&[]), - Some(d) => f(d.as_slice()) + Some(d) => f(d[]) } } diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 5c2fe0854ee..a2e33454320 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -141,17 +141,17 @@ impl<'a> PluginLoader<'a> { // this is fatal: there are almost certainly macros we need // inside this crate, so continue would spew "macro undefined" // errors - Err(err) => self.sess.span_fatal(vi.span, err.as_slice()) + Err(err) => self.sess.span_fatal(vi.span, err[]) }; unsafe { let registrar = - match lib.symbol(symbol.as_slice()) { + match lib.symbol(symbol[]) { Ok(registrar) => { mem::transmute::<*mut u8,PluginRegistrarFun>(registrar) } // again fatal if we can't register macros - Err(err) => self.sess.span_fatal(vi.span, err.as_slice()) + Err(err) => self.sess.span_fatal(vi.span, err[]) }; self.plugins.registrars.push(registrar); diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 0652645907b..335b7489063 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -555,17 +555,17 @@ pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions match (value, opt_type_desc) { (Some(..), None) => { early_error(format!("codegen option `{}` takes no \ - value", key).as_slice()) + value", key)[]) } (None, Some(type_desc)) => { early_error(format!("codegen option `{0}` requires \ {1} (-C {0}=)", - key, type_desc).as_slice()) + key, type_desc)[]) } (Some(value), Some(type_desc)) => { early_error(format!("incorrect value `{}` for codegen \ option `{}` - {} was expected", - value, key, type_desc).as_slice()) + value, key, type_desc)[]) } (None, None) => unreachable!() } @@ -575,7 +575,7 @@ pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions } if !found { early_error(format!("unknown codegen option: `{}`", - key).as_slice()); + key)[]); } } return cg; @@ -588,10 +588,10 @@ pub fn default_lib_output() -> CrateType { pub fn default_configuration(sess: &Session) -> ast::CrateConfig { use syntax::parse::token::intern_and_get_ident as intern; - let end = sess.target.target.target_endian.as_slice(); - let arch = sess.target.target.arch.as_slice(); - let wordsz = sess.target.target.target_word_size.as_slice(); - let os = sess.target.target.target_os.as_slice(); + let end = sess.target.target.target_endian[]; + let arch = sess.target.target.arch[]; + let wordsz = sess.target.target.target_word_size[]; + let os = sess.target.target.target_os[]; let fam = match sess.target.target.options.is_like_windows { true => InternedString::new("windows"), @@ -627,23 +627,23 @@ pub fn build_configuration(sess: &Session) -> ast::CrateConfig { append_configuration(&mut user_cfg, InternedString::new("test")) } let mut v = user_cfg.into_iter().collect::>(); - v.push_all(default_cfg.as_slice()); + v.push_all(default_cfg[]); v } pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config { - let target = match Target::search(opts.target_triple.as_slice()) { + let target = match Target::search(opts.target_triple[]) { Ok(t) => t, Err(e) => { - sp.handler().fatal((format!("Error loading target specification: {}", e)).as_slice()); + sp.handler().fatal((format!("Error loading target specification: {}", e))[]); } }; - let (int_type, uint_type) = match target.target_word_size.as_slice() { + let (int_type, uint_type) = match target.target_word_size[] { "32" => (ast::TyI32, ast::TyU32), "64" => (ast::TyI64, ast::TyU64), w => sp.handler().fatal((format!("target specification was invalid: unrecognized \ - target-word-size {}", w)).as_slice()) + target-word-size {}", w))[]) }; Config { @@ -756,7 +756,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let unparsed_crate_types = matches.opt_strs("crate-type"); let crate_types = parse_crate_types_from_list(unparsed_crate_types) - .unwrap_or_else(|e| early_error(e.as_slice())); + .unwrap_or_else(|e| early_error(e[])); let mut lint_opts = vec!(); let mut describe_lints = false; @@ -766,7 +766,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { if lint_name == "help" { describe_lints = true; } else { - lint_opts.push((lint_name.replace("-", "_").into_string(), level)); + lint_opts.push((lint_name.replace("-", "_"), level)); } } } @@ -784,7 +784,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } if this_bit == 0 { early_error(format!("unknown debug flag: {}", - *debug_flag).as_slice()) + *debug_flag)[]) } debugging_opts |= this_bit; } @@ -829,7 +829,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { "dep-info" => OutputTypeDepInfo, _ => { early_error(format!("unknown emission type: `{}`", - part).as_slice()) + part)[]) } }; output_types.push(output_type) @@ -868,7 +868,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { Some(arg) => { early_error(format!("optimization level needs to be \ between 0-3 (instead was `{}`)", - arg).as_slice()); + arg)[]); } } } else { @@ -906,7 +906,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { Some(arg) => { early_error(format!("debug info level needs to be between \ 0-2 (instead was `{}`)", - arg).as_slice()); + arg)[]); } } } else { @@ -923,7 +923,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { }; let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| { - Path::new(s.as_slice()) + Path::new(s[]) }).collect(); let libs = matches.opt_strs("l").into_iter().map(|s| { @@ -937,7 +937,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { (_, s) => { early_error(format!("unknown library kind `{}`, expected \ one of dylib, framework, or static", - s).as_slice()); + s)[]); } }; (name.to_string(), kind) @@ -982,7 +982,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { // --debuginfo"); } - let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) { + let color = match matches.opt_str("color").as_ref().map(|s| s[]) { Some("auto") => Auto, Some("always") => Always, Some("never") => Never, @@ -992,7 +992,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { Some(arg) => { early_error(format!("argument for --color must be auto, always \ or never (instead was `{}`)", - arg).as_slice()) + arg)[]) } }; @@ -1093,7 +1093,7 @@ mod test { #[test] fn test_switch_implies_cfg_test() { let matches = - &match getopts(&["--test".to_string()], optgroups().as_slice()) { + &match getopts(&["--test".to_string()], optgroups()[]) { Ok(m) => m, Err(f) => panic!("test_switch_implies_cfg_test: {}", f) }; @@ -1101,7 +1101,7 @@ mod test { let sessopts = build_session_options(matches); let sess = build_session(sessopts, None, registry); let cfg = build_configuration(&sess); - assert!((attr::contains_name(cfg.as_slice(), "test"))); + assert!((attr::contains_name(cfg[], "test"))); } // When the user supplies --test and --cfg test, don't implicitly add @@ -1110,7 +1110,7 @@ mod test { fn test_switch_implies_cfg_test_unless_cfg_test() { let matches = &match getopts(&["--test".to_string(), "--cfg=test".to_string()], - optgroups().as_slice()) { + optgroups()[]) { Ok(m) => m, Err(f) => { panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f) @@ -1130,7 +1130,7 @@ mod test { { let matches = getopts(&[ "-Awarnings".to_string() - ], optgroups().as_slice()).unwrap(); + ], optgroups()[]).unwrap(); let registry = diagnostics::registry::Registry::new(&[]); let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry); @@ -1141,7 +1141,7 @@ mod test { let matches = getopts(&[ "-Awarnings".to_string(), "-Dwarnings".to_string() - ], optgroups().as_slice()).unwrap(); + ], optgroups()[]).unwrap(); let registry = diagnostics::registry::Registry::new(&[]); let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry); @@ -1151,7 +1151,7 @@ mod test { { let matches = getopts(&[ "-Adead_code".to_string() - ], optgroups().as_slice()).unwrap(); + ], optgroups()[]).unwrap(); let registry = diagnostics::registry::Registry::new(&[]); let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 8516ece202c..37bdd1673e9 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -172,7 +172,7 @@ impl Session { // cases later on pub fn impossible_case(&self, sp: Span, msg: &str) -> ! { self.span_bug(sp, - format!("impossible case reached: {}", msg).as_slice()); + format!("impossible case reached: {}", msg)[]); } pub fn verbose(&self) -> bool { self.debugging_opt(config::VERBOSE) } pub fn time_passes(&self) -> bool { self.debugging_opt(config::TIME_PASSES) } @@ -211,7 +211,7 @@ impl Session { } pub fn target_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> { filesearch::FileSearch::new(self.sysroot(), - self.opts.target_triple.as_slice(), + self.opts.target_triple[], &self.opts.addl_lib_search_paths) } pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> { diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index bc6fb1be075..e1448364a9e 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -14,6 +14,7 @@ use std::cell::{RefCell, Cell}; use std::collections::HashMap; use std::fmt::Show; use std::hash::{Hash, Hasher}; +use std::iter::repeat; use std::time::Duration; use syntax::ast; @@ -48,7 +49,7 @@ pub fn time(do_it: bool, what: &str, u: U, f: F) -> T where }; let rv = rv.unwrap(); - println!("{}time: {}.{:03} \t{}", " ".repeat(old), + println!("{}time: {}.{:03} \t{}", repeat(" ").take(old).collect::(), dur.num_seconds(), dur.num_milliseconds() % 1000, what); DEPTH.with(|slot| slot.set(old)); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 85a06125e23..5f61c04d366 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -55,12 +55,12 @@ pub fn note_and_explain_region(cx: &ctxt, (ref str, Some(span)) => { cx.sess.span_note( span, - format!("{}{}{}", prefix, *str, suffix).as_slice()); + format!("{}{}{}", prefix, *str, suffix)[]); Some(span) } (ref str, None) => { cx.sess.note( - format!("{}{}{}", prefix, *str, suffix).as_slice()); + format!("{}{}{}", prefix, *str, suffix)[]); None } } @@ -269,7 +269,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { }; if abi != abi::Rust { - s.push_str(format!("extern {} ", abi.to_string()).as_slice()); + s.push_str(format!("extern {} ", abi.to_string())[]); }; s.push_str("fn"); @@ -293,7 +293,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { match cty.store { ty::UniqTraitStore => {} ty::RegionTraitStore(region, _) => { - s.push_str(region_to_string(cx, "", true, region).as_slice()); + s.push_str(region_to_string(cx, "", true, region)[]); } } @@ -312,7 +312,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { assert_eq!(cty.onceness, ast::Once); s.push_str("proc"); push_sig_to_string(cx, &mut s, '(', ')', &cty.sig, - bounds_str.as_slice()); + bounds_str[]); } ty::RegionTraitStore(..) => { match cty.onceness { @@ -320,7 +320,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { ast::Once => s.push_str("once ") } push_sig_to_string(cx, &mut s, '|', '|', &cty.sig, - bounds_str.as_slice()); + bounds_str[]); } } @@ -353,7 +353,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { ty::FnConverging(t) => { if !ty::type_is_nil(t) { s.push_str(" -> "); - s.push_str(ty_to_string(cx, t).as_slice()); + s.push_str(ty_to_string(cx, t)[]); } } ty::FnDiverging => { @@ -390,7 +390,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { } ty_rptr(r, ref tm) => { let mut buf = region_ptr_to_string(cx, r); - buf.push_str(mt_to_string(cx, tm).as_slice()); + buf.push_str(mt_to_string(cx, tm)[]); buf } ty_open(typ) => @@ -400,7 +400,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { .iter() .map(|elem| ty_to_string(cx, *elem)) .collect::>(); - match strs.as_slice() { + match strs[] { [ref string] => format!("({},)", string), strs => format!("({})", strs.connect(", ")) } @@ -551,7 +551,7 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>, pub fn ty_to_short_str<'tcx>(cx: &ctxt<'tcx>, typ: Ty<'tcx>) -> String { let mut s = typ.repr(cx).to_string(); if s.len() >= 32u { - s = s.slice(0u, 32u).to_string(); + s = s[0u..32u].to_string(); } return s; } @@ -616,7 +616,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for [T] { impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - repr_vec(tcx, self.as_slice()) + repr_vec(tcx, self[]) } } @@ -624,7 +624,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice { // autoderef cannot convert the &[T] handler impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - repr_vec(tcx, self.as_slice()) + repr_vec(tcx, self[]) } } diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index 3a451070316..0bd4265e487 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -53,7 +53,7 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, args: &str, cwd: Option<&Path>, paths: &[&Path]) -> ProcessOutput { let ar = match *maybe_ar_prog { - Some(ref ar) => ar.as_slice(), + Some(ref ar) => ar[], None => "ar" }; let mut cmd = Command::new(ar); @@ -75,22 +75,22 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, if !o.status.success() { handler.err(format!("{} failed with: {}", cmd, - o.status).as_slice()); + o.status)[]); handler.note(format!("stdout ---\n{}", str::from_utf8(o.output - .as_slice()).unwrap()) - .as_slice()); + []).unwrap()) + []); handler.note(format!("stderr ---\n{}", str::from_utf8(o.error - .as_slice()).unwrap()) - .as_slice()); + []).unwrap()) + []); handler.abort_if_errors(); } o }, Err(e) => { - handler.err(format!("could not exec `{}`: {}", ar.as_slice(), - e).as_slice()); + handler.err(format!("could not exec `{}`: {}", ar[], + e)[]); handler.abort_if_errors(); panic!("rustc::back::archive::run_ar() should not reach this point"); } @@ -106,16 +106,16 @@ pub fn find_library(name: &str, osprefix: &str, ossuffix: &str, for path in search_paths.iter() { debug!("looking for {} inside {}", name, path.display()); - let test = path.join(oslibname.as_slice()); + let test = path.join(oslibname[]); if test.exists() { return test } if oslibname != unixlibname { - let test = path.join(unixlibname.as_slice()); + let test = path.join(unixlibname[]); if test.exists() { return test } } } handler.fatal(format!("could not find native static library `{}`, \ perhaps an -L flag is missing?", - name).as_slice()); + name)[]); } impl<'a> Archive<'a> { @@ -147,7 +147,7 @@ impl<'a> Archive<'a> { /// Lists all files in an archive pub fn files(&self) -> Vec { let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, &[&self.dst]); - let output = str::from_utf8(output.output.as_slice()).unwrap(); + let output = str::from_utf8(output.output[]).unwrap(); // use lines_any because windows delimits output with `\r\n` instead of // just `\n` output.lines_any().map(|s| s.to_string()).collect() @@ -179,9 +179,9 @@ impl<'a> ArchiveBuilder<'a> { /// search in the relevant locations for a library named `name`. pub fn add_native_library(&mut self, name: &str) -> io::IoResult<()> { let location = find_library(name, - self.archive.slib_prefix.as_slice(), - self.archive.slib_suffix.as_slice(), - self.archive.lib_search_paths.as_slice(), + self.archive.slib_prefix[], + self.archive.slib_suffix[], + self.archive.lib_search_paths[], self.archive.handler); self.add_archive(&location, name, |_| false) } @@ -197,12 +197,12 @@ impl<'a> ArchiveBuilder<'a> { // as simple comparison is not enough - there // might be also an extra name suffix let obj_start = format!("{}", name); - let obj_start = obj_start.as_slice(); + let obj_start = obj_start[]; // Ignoring all bytecode files, no matter of // name let bc_ext = ".bytecode.deflate"; - self.add_archive(rlib, name.as_slice(), |fname: &str| { + self.add_archive(rlib, name[], |fname: &str| { let skip_obj = lto && fname.starts_with(obj_start) && fname.ends_with(".o"); skip_obj || fname.ends_with(bc_ext) || fname == METADATA_FILENAME @@ -239,7 +239,7 @@ impl<'a> ArchiveBuilder<'a> { // allow running `ar s file.a` to update symbols only. if self.should_update_symbols { run_ar(self.archive.handler, &self.archive.maybe_ar_prog, - "s", Some(self.work_dir.path()), args.as_slice()); + "s", Some(self.work_dir.path()), args[]); } return self.archive; } @@ -259,7 +259,7 @@ impl<'a> ArchiveBuilder<'a> { // Add the archive members seen so far, without updating the // symbol table (`S`). run_ar(self.archive.handler, &self.archive.maybe_ar_prog, - "cruS", Some(self.work_dir.path()), args.as_slice()); + "cruS", Some(self.work_dir.path()), args[]); args.clear(); args.push(&abs_dst); @@ -274,7 +274,7 @@ impl<'a> ArchiveBuilder<'a> { // necessary. let flags = if self.should_update_symbols { "crus" } else { "cruS" }; run_ar(self.archive.handler, &self.archive.maybe_ar_prog, - flags, Some(self.work_dir.path()), args.as_slice()); + flags, Some(self.work_dir.path()), args[]); self.archive } @@ -316,7 +316,7 @@ impl<'a> ArchiveBuilder<'a> { } else { filename }; - let new_filename = self.work_dir.path().join(filename.as_slice()); + let new_filename = self.work_dir.path().join(filename[]); try!(fs::rename(file, &new_filename)); self.members.push(Path::new(filename)); } diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index 1f8549098d9..1056ac928e6 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -44,15 +44,15 @@ pub fn get_rpath_flags(config: RPathConfig) -> Vec where l.map(|p| p.clone()) }).collect::>(); - let rpaths = get_rpaths(config, libs.as_slice()); - flags.push_all(rpaths_to_flags(rpaths.as_slice()).as_slice()); + let rpaths = get_rpaths(config, libs[]); + flags.push_all(rpaths_to_flags(rpaths[])[]); flags } fn rpaths_to_flags(rpaths: &[String]) -> Vec { let mut ret = Vec::new(); for rpath in rpaths.iter() { - ret.push(format!("-Wl,-rpath,{}", (*rpath).as_slice())); + ret.push(format!("-Wl,-rpath,{}", (*rpath)[])); } return ret; } @@ -82,14 +82,14 @@ fn get_rpaths(mut config: RPathConfig, libs: &[Path]) -> Vec } } - log_rpaths("relative", rel_rpaths.as_slice()); - log_rpaths("fallback", fallback_rpaths.as_slice()); + log_rpaths("relative", rel_rpaths[]); + log_rpaths("fallback", fallback_rpaths[]); let mut rpaths = rel_rpaths; - rpaths.push_all(fallback_rpaths.as_slice()); + rpaths.push_all(fallback_rpaths[]); // Remove duplicates - let rpaths = minimize_rpaths(rpaths.as_slice()); + let rpaths = minimize_rpaths(rpaths[]); return rpaths; } @@ -140,7 +140,7 @@ fn minimize_rpaths(rpaths: &[String]) -> Vec { let mut set = HashSet::new(); let mut minimized = Vec::new(); for rpath in rpaths.iter() { - if set.insert(rpath.as_slice()) { + if set.insert(rpath[]) { minimized.push(rpath.clone()); } } diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 98fa659ba55..d40c9ee8af6 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -65,7 +65,7 @@ impl Svh { } pub fn as_str<'a>(&'a self) -> &'a str { - self.hash.as_slice() + self.hash[] } pub fn calculate(metadata: &Vec, krate: &ast::Crate) -> Svh { @@ -358,7 +358,7 @@ mod svh_visitor { fn macro_name(macro: &Mac) -> token::InternedString { match ¯o.node { &MacInvocTT(ref path, ref _tts, ref _stx_ctxt) => { - let s = path.segments.as_slice(); + let s = path.segments[]; assert_eq!(s.len(), 1); content(s[0].identifier) } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index d12cb356e3f..99a25bebf40 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -224,7 +224,7 @@ impl Target { Some(val) => val, None => handler.fatal((format!("Field {} in target specification is required", name)) - .as_slice()) + []) } }; @@ -365,7 +365,7 @@ impl Target { let target_path = os::getenv("RUST_TARGET_PATH").unwrap_or(String::new()); - let paths = os::split_paths(target_path.as_slice()); + let paths = os::split_paths(target_path[]); // FIXME 16351: add a sane default search path? for dir in paths.iter() { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 3bf817b42b0..568bb023b68 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -469,7 +469,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { new_loan.span, format!("cannot borrow `{}`{} as mutable \ more than once at a time", - nl, new_loan_msg).as_slice()) + nl, new_loan_msg)[]) } (ty::UniqueImmBorrow, _) => { @@ -477,7 +477,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { new_loan.span, format!("closure requires unique access to `{}` \ but {} is already borrowed{}", - nl, ol_pronoun, old_loan_msg).as_slice()); + nl, ol_pronoun, old_loan_msg)[]); } (_, ty::UniqueImmBorrow) => { @@ -485,7 +485,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { new_loan.span, format!("cannot borrow `{}`{} as {} because \ previous closure requires unique access", - nl, new_loan_msg, new_loan.kind.to_user_str()).as_slice()); + nl, new_loan_msg, new_loan.kind.to_user_str())[]); } (_, _) => { @@ -498,7 +498,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { new_loan.kind.to_user_str(), ol_pronoun, old_loan.kind.to_user_str(), - old_loan_msg).as_slice()); + old_loan_msg)[]); } } @@ -507,7 +507,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_note( span, format!("borrow occurs due to use of `{}` in closure", - nl).as_slice()); + nl)[]); } _ => { } } @@ -556,7 +556,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_note( old_loan.span, - format!("{}; {}", borrow_summary, rule_summary).as_slice()); + format!("{}; {}", borrow_summary, rule_summary)[]); let old_loan_span = self.tcx().map.span(old_loan.kill_scope.node_id()); self.bccx.span_end_note(old_loan_span, @@ -626,13 +626,13 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_err( span, format!("cannot use `{}` because it was mutably borrowed", - self.bccx.loan_path_to_string(copy_path).as_slice()) - .as_slice()); + self.bccx.loan_path_to_string(copy_path)[]) + []); self.bccx.span_note( loan_span, format!("borrow of `{}` occurs here", - self.bccx.loan_path_to_string(&*loan_path).as_slice()) - .as_slice()); + self.bccx.loan_path_to_string(&*loan_path)[]) + []); } } } @@ -651,20 +651,20 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let err_message = match move_kind { move_data::Captured => format!("cannot move `{}` into closure because it is borrowed", - self.bccx.loan_path_to_string(move_path).as_slice()), + self.bccx.loan_path_to_string(move_path)[]), move_data::Declared | move_data::MoveExpr | move_data::MovePat => format!("cannot move out of `{}` because it is borrowed", - self.bccx.loan_path_to_string(move_path).as_slice()) + self.bccx.loan_path_to_string(move_path)[]) }; - self.bccx.span_err(span, err_message.as_slice()); + self.bccx.span_err(span, err_message[]); self.bccx.span_note( loan_span, format!("borrow of `{}` occurs here", - self.bccx.loan_path_to_string(&*loan_path).as_slice()) - .as_slice()); + self.bccx.loan_path_to_string(&*loan_path)[]) + []); } } } @@ -814,7 +814,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_err( assignment_span, format!("cannot assign to {}", - self.bccx.cmt_to_string(&*assignee_cmt)).as_slice()); + self.bccx.cmt_to_string(&*assignee_cmt))[]); self.bccx.span_help( self.tcx().map.span(upvar_id.closure_expr_id), "consider changing this closure to take self by mutable reference"); @@ -823,7 +823,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { assignment_span, format!("cannot assign to {} {}", assignee_cmt.mutbl.to_user_str(), - self.bccx.cmt_to_string(&*assignee_cmt)).as_slice()); + self.bccx.cmt_to_string(&*assignee_cmt))[]); } } _ => match opt_loan_path(&assignee_cmt) { @@ -833,14 +833,14 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { format!("cannot assign to {} {} `{}`", assignee_cmt.mutbl.to_user_str(), self.bccx.cmt_to_string(&*assignee_cmt), - self.bccx.loan_path_to_string(&*lp)).as_slice()); + self.bccx.loan_path_to_string(&*lp))[]); } None => { self.bccx.span_err( assignment_span, format!("cannot assign to {} {}", assignee_cmt.mutbl.to_user_str(), - self.bccx.cmt_to_string(&*assignee_cmt)).as_slice()); + self.bccx.cmt_to_string(&*assignee_cmt))[]); } } } @@ -960,10 +960,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_err( span, format!("cannot assign to `{}` because it is borrowed", - self.bccx.loan_path_to_string(loan_path)).as_slice()); + self.bccx.loan_path_to_string(loan_path))[]); self.bccx.span_note( loan.span, format!("borrow of `{}` occurs here", - self.bccx.loan_path_to_string(loan_path)).as_slice()); + self.bccx.loan_path_to_string(loan_path))[]); } } diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index 25ed5182555..dbbc52cf362 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -124,12 +124,12 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>, let attrs : &[ast::Attribute]; attrs = match tcx.map.find(id) { Some(ast_map::NodeItem(ref item)) => - item.attrs.as_slice(), + item.attrs[], Some(ast_map::NodeImplItem(&ast::MethodImplItem(ref m))) => - m.attrs.as_slice(), + m.attrs[], Some(ast_map::NodeTraitItem(&ast::ProvidedMethod(ref m))) => - m.attrs.as_slice(), - _ => [].as_slice(), + m.attrs[], + _ => [][], }; let span_err = @@ -145,7 +145,7 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>, for (i, mpi) in vec_rc.iter().enumerate() { let render = || this.path_loan_path(*mpi).user_string(tcx); if span_err { - tcx.sess.span_err(sp, format!("{}: `{}`", kind, render()).as_slice()); + tcx.sess.span_err(sp, format!("{}: `{}`", kind, render())[]); } if print { println!("id:{} {}[{}] `{}`", id, kind, i, render()); @@ -157,7 +157,7 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>, for (i, f) in vec_rc.iter().enumerate() { let render = || f.loan_path_user_string(this, tcx); if span_err { - tcx.sess.span_err(sp, format!("{}: `{}`", kind, render()).as_slice()); + tcx.sess.span_err(sp, format!("{}: `{}`", kind, render())[]); } if print { println!("id:{} {}[{}] `{}`", id, kind, i, render()); @@ -199,11 +199,11 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { // First, filter out duplicates moved.sort(); moved.dedup(); - debug!("fragments 1 moved: {}", path_lps(moved.as_slice())); + debug!("fragments 1 moved: {}", path_lps(moved[])); assigned.sort(); assigned.dedup(); - debug!("fragments 1 assigned: {}", path_lps(assigned.as_slice())); + debug!("fragments 1 assigned: {}", path_lps(assigned[])); // Second, build parents from the moved and assigned. for m in moved.iter() { @@ -223,14 +223,14 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { parents.sort(); parents.dedup(); - debug!("fragments 2 parents: {}", path_lps(parents.as_slice())); + debug!("fragments 2 parents: {}", path_lps(parents[])); // Third, filter the moved and assigned fragments down to just the non-parents - moved.retain(|f| non_member(*f, parents.as_slice())); - debug!("fragments 3 moved: {}", path_lps(moved.as_slice())); + moved.retain(|f| non_member(*f, parents[])); + debug!("fragments 3 moved: {}", path_lps(moved[])); - assigned.retain(|f| non_member(*f, parents.as_slice())); - debug!("fragments 3 assigned: {}", path_lps(assigned.as_slice())); + assigned.retain(|f| non_member(*f, parents[])); + debug!("fragments 3 assigned: {}", path_lps(assigned[])); // Fourth, build the leftover from the moved, assigned, and parents. for m in moved.iter() { @@ -248,16 +248,16 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { unmoved.sort(); unmoved.dedup(); - debug!("fragments 4 unmoved: {}", frag_lps(unmoved.as_slice())); + debug!("fragments 4 unmoved: {}", frag_lps(unmoved[])); // Fifth, filter the leftover fragments down to its core. unmoved.retain(|f| match *f { AllButOneFrom(_) => true, - Just(mpi) => non_member(mpi, parents.as_slice()) && - non_member(mpi, moved.as_slice()) && - non_member(mpi, assigned.as_slice()) + Just(mpi) => non_member(mpi, parents[]) && + non_member(mpi, moved[]) && + non_member(mpi, assigned[]) }); - debug!("fragments 5 unmoved: {}", frag_lps(unmoved.as_slice())); + debug!("fragments 5 unmoved: {}", frag_lps(unmoved[])); // Swap contents back in. fragments.unmoved_fragments = unmoved; @@ -434,7 +434,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>, let msg = format!("type {} ({}) is not fragmentable", parent_ty.repr(tcx), sty_and_variant_info); let opt_span = origin_id.and_then(|id|tcx.map.opt_span(id)); - tcx.sess.opt_span_bug(opt_span, msg.as_slice()) + tcx.sess.opt_span_bug(opt_span, msg[]) } } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 08d12f8282b..d7f50ccc6ba 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -310,7 +310,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { self.tcx().sess.span_bug( cmt.span, format!("invalid borrow lifetime: {}", - loan_region).as_slice()); + loan_region)[]); } }; debug!("loan_scope = {}", loan_scope); diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index fbe78152a60..73b345a70af 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -120,7 +120,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, bccx.span_err( move_from.span, format!("cannot move out of {}", - bccx.cmt_to_string(&*move_from)).as_slice()); + bccx.cmt_to_string(&*move_from))[]); } mc::cat_downcast(ref b, _) | @@ -132,7 +132,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_from.span, format!("cannot move out of type `{}`, \ which defines the `Drop` trait", - b.ty.user_string(bccx.tcx)).as_slice()); + b.ty.user_string(bccx.tcx))[]); }, _ => panic!("this path should not cause illegal move") } @@ -155,10 +155,10 @@ fn note_move_destination(bccx: &BorrowckCtxt, format!("to prevent the move, \ use `ref {0}` or `ref mut {0}` to capture value by \ reference", - pat_name).as_slice()); + pat_name)[]); } else { bccx.span_note(move_to_span, format!("and here (use `ref {0}` or `ref mut {0}`)", - pat_name).as_slice()); + pat_name)[]); } } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 9be87b533f2..a13001b7968 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -146,7 +146,7 @@ fn borrowck_fn(this: &mut BorrowckCtxt, check_loans::check_loans(this, &loan_dfcx, flowed_moves, - all_loans.as_slice(), + all_loans[], id, decl, body); @@ -527,7 +527,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { pub fn report(&self, err: BckError<'tcx>) { self.span_err( err.span, - self.bckerr_to_string(&err).as_slice()); + self.bckerr_to_string(&err)[]); self.note_and_explain_bckerr(err); } @@ -549,7 +549,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { use_span, format!("{} of possibly uninitialized variable: `{}`", verb, - self.loan_path_to_string(lp)).as_slice()); + self.loan_path_to_string(lp))[]); (self.loan_path_to_string(moved_lp), String::new()) } @@ -591,7 +591,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { format!("{} of {}moved value: `{}`", verb, msg, - nl).as_slice()); + nl)[]); (ol, moved_lp_msg) } }; @@ -610,7 +610,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.bug(format!("MoveExpr({}) maps to \ {}, not Expr", the_move.id, - r).as_slice()) + r)[]) } }; let (suggestion, _) = move_suggestion(self.tcx, param_env, expr_ty, @@ -621,7 +621,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { ol, moved_lp_msg, expr_ty.user_string(self.tcx), - suggestion).as_slice()); + suggestion)[]); } move_data::MovePat => { @@ -632,7 +632,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { which is moved by default", ol, moved_lp_msg, - pat_ty.user_string(self.tcx)).as_slice()); + pat_ty.user_string(self.tcx))[]); self.tcx.sess.span_help(span, "use `ref` to override"); } @@ -648,7 +648,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.bug(format!("Captured({}) maps to \ {}, not Expr", the_move.id, - r).as_slice()) + r)[]) } }; let (suggestion, help) = move_suggestion(self.tcx, @@ -663,7 +663,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { ol, moved_lp_msg, expr_ty.user_string(self.tcx), - suggestion).as_slice()); + suggestion)[]); self.tcx.sess.span_help(expr_span, help); } } @@ -696,7 +696,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_err( span, format!("re-assignment of immutable variable `{}`", - self.loan_path_to_string(lp)).as_slice()); + self.loan_path_to_string(lp))[]); self.tcx.sess.span_note(assign.span, "prior assignment occurs here"); } @@ -822,12 +822,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_err( span, format!("{} in an aliasable location", - prefix).as_slice()); + prefix)[]); } mc::AliasableClosure(id) => { self.tcx.sess.span_err(span, format!("{} in a captured outer \ - variable in an `Fn` closure", prefix).as_slice()); + variable in an `Fn` closure", prefix)[]); span_help!(self.tcx.sess, self.tcx.map.span(id), "consider changing this closure to take self by mutable reference"); } @@ -835,12 +835,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { mc::AliasableStaticMut(..) => { self.tcx.sess.span_err( span, - format!("{} in a static location", prefix).as_slice()); + format!("{} in a static location", prefix)[]); } mc::AliasableBorrowed => { self.tcx.sess.span_err( span, - format!("{} in a `&` reference", prefix).as_slice()); + format!("{} in a `&` reference", prefix)[]); } } @@ -908,12 +908,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { note_and_explain_region( self.tcx, format!("{} would have to be valid for ", - descr).as_slice(), + descr)[], loan_scope, "..."); note_and_explain_region( self.tcx, - format!("...but {} is only valid for ", descr).as_slice(), + format!("...but {} is only valid for ", descr)[], ptr_scope, ""); } @@ -933,7 +933,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { out.push('('); self.append_loan_path_to_string(&**lp_base, out); out.push_str(DOWNCAST_PRINTED_OPERATOR); - out.push_str(ty::item_path_str(self.tcx, variant_def_id).as_slice()); + out.push_str(ty::item_path_str(self.tcx, variant_def_id)[]); out.push(')'); } @@ -947,7 +947,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } mc::PositionalField(idx) => { out.push('.'); - out.push_str(idx.to_string().as_slice()); + out.push_str(idx.to_string()[]); } } } @@ -979,7 +979,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { out.push('('); self.append_autoderefd_loan_path_to_string(&**lp_base, out); out.push(':'); - out.push_str(ty::item_path_str(self.tcx, variant_def_id).as_slice()); + out.push_str(ty::item_path_str(self.tcx, variant_def_id)[]); out.push(')'); } diff --git a/src/librustc_borrowck/graphviz.rs b/src/librustc_borrowck/graphviz.rs index 3427be1443b..e2813c8e988 100644 --- a/src/librustc_borrowck/graphviz.rs +++ b/src/librustc_borrowck/graphviz.rs @@ -59,7 +59,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> { if seen_one { sets.push_str(" "); } else { seen_one = true; } sets.push_str(variant.short_name()); sets.push_str(": "); - sets.push_str(self.dataflow_for_variant(e, n, variant).as_slice()); + sets.push_str(self.dataflow_for_variant(e, n, variant)[]); } sets } @@ -88,7 +88,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> { set.push_str(", "); } let loan_str = self.borrowck_ctxt.loan_path_to_string(&*lp); - set.push_str(loan_str.as_slice()); + set.push_str(loan_str[]); saw_some = true; true }); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 60b890b0370..20bb9c2f4fd 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -58,12 +58,12 @@ pub fn compile_input(sess: Session, let outputs = build_output_filenames(input, outdir, output, - krate.attrs.as_slice(), + krate.attrs[], &sess); - let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), + let id = link::find_crate_name(Some(&sess), krate.attrs[], input); let expanded_crate - = match phase_2_configure_and_expand(&sess, krate, id.as_slice(), + = match phase_2_configure_and_expand(&sess, krate, id[], addl_plugins) { None => return, Some(k) => k @@ -75,7 +75,7 @@ pub fn compile_input(sess: Session, let mut forest = ast_map::Forest::new(expanded_crate); let ast_map = assign_node_ids_and_map(&sess, &mut forest); - write_out_deps(&sess, input, &outputs, id.as_slice()); + write_out_deps(&sess, input, &outputs, id[]); if stop_after_phase_2(&sess) { return; } @@ -163,9 +163,9 @@ pub fn phase_2_configure_and_expand(sess: &Session, let time_passes = sess.time_passes(); *sess.crate_types.borrow_mut() = - collect_crate_types(sess, krate.attrs.as_slice()); + collect_crate_types(sess, krate.attrs[]); *sess.crate_metadata.borrow_mut() = - collect_crate_metadata(sess, krate.attrs.as_slice()); + collect_crate_metadata(sess, krate.attrs[]); time(time_passes, "gated feature checking", (), |_| { let (features, unknown_features) = @@ -257,8 +257,8 @@ pub fn phase_2_configure_and_expand(sess: &Session, if cfg!(windows) { _old_path = os::getenv("PATH").unwrap_or(_old_path); let mut new_path = sess.host_filesearch().get_dylib_search_paths(); - new_path.extend(os::split_paths(_old_path.as_slice()).into_iter()); - os::setenv("PATH", os::join_paths(new_path.as_slice()).unwrap()); + new_path.extend(os::split_paths(_old_path[]).into_iter()); + os::setenv("PATH", os::join_paths(new_path[]).unwrap()); } let cfg = syntax::ext::expand::ExpansionConfig { crate_name: crate_name.to_string(), @@ -503,7 +503,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, time(sess.time_passes(), "LLVM passes", (), |_| write::run_passes(sess, trans, - sess.opts.output_types.as_slice(), + sess.opts.output_types[], outputs)); } @@ -517,14 +517,14 @@ pub fn phase_6_link_output(sess: &Session, outputs: &OutputFilenames) { let old_path = os::getenv("PATH").unwrap_or_else(||String::new()); let mut new_path = sess.host_filesearch().get_tools_search_paths(); - new_path.extend(os::split_paths(old_path.as_slice()).into_iter()); - os::setenv("PATH", os::join_paths(new_path.as_slice()).unwrap()); + new_path.extend(os::split_paths(old_path[]).into_iter()); + os::setenv("PATH", os::join_paths(new_path[]).unwrap()); time(sess.time_passes(), "linking", (), |_| link::link_binary(sess, trans, outputs, - trans.link.crate_name.as_slice())); + trans.link.crate_name[])); os::setenv("PATH", old_path); } @@ -613,7 +613,7 @@ fn write_out_deps(sess: &Session, // write Makefile-compatible dependency rules let files: Vec = sess.codemap().files.borrow() .iter().filter(|fmap| fmap.is_real_file()) - .map(|fmap| escape_dep_filename(fmap.name.as_slice())) + .map(|fmap| escape_dep_filename(fmap.name[])) .collect(); let mut file = try!(io::File::create(&deps_filename)); for path in out_filenames.iter() { @@ -627,7 +627,7 @@ fn write_out_deps(sess: &Session, Ok(()) => {} Err(e) => { sess.fatal(format!("error writing dependencies to `{}`: {}", - deps_filename.display(), e).as_slice()); + deps_filename.display(), e)[]); } } } @@ -698,7 +698,7 @@ pub fn collect_crate_types(session: &Session, if !res { session.warn(format!("dropping unsupported crate type `{}` \ for target `{}`", - *crate_type, session.opts.target_triple).as_slice()); + *crate_type, session.opts.target_triple)[]); } res diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6944c733456..1fb90d7860e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -55,6 +55,7 @@ use rustc::DIAGNOSTICS; use std::any::AnyRefExt; use std::io; +use std::iter::repeat; use std::os; use std::thread; @@ -88,12 +89,12 @@ fn run_compiler(args: &[String]) { let descriptions = diagnostics::registry::Registry::new(&DIAGNOSTICS); match matches.opt_str("explain") { Some(ref code) => { - match descriptions.find_description(code.as_slice()) { + match descriptions.find_description(code[]) { Some(ref description) => { println!("{}", description); } None => { - early_error(format!("no extended information for {}", code).as_slice()); + early_error(format!("no extended information for {}", code)[]); } } return; @@ -119,7 +120,7 @@ fn run_compiler(args: &[String]) { early_error("no input filename given"); } 1u => { - let ifile = matches.free[0].as_slice(); + let ifile = matches.free[0][]; if ifile == "-" { let contents = io::stdin().read_to_end().unwrap(); let src = String::from_utf8(contents).unwrap(); @@ -138,7 +139,7 @@ fn run_compiler(args: &[String]) { } let pretty = matches.opt_default("pretty", "normal").map(|a| { - pretty::parse_pretty(&sess, a.as_slice()) + pretty::parse_pretty(&sess, a[]) }); match pretty.into_iter().next() { Some((ppm, opt_uii)) => { @@ -261,7 +262,8 @@ Available lint options: .map(|&s| s.name.width(true)) .max().unwrap_or(0); let padded = |x: &str| { - let mut s = " ".repeat(max_name_len - x.char_len()); + let mut s = repeat(" ").take(max_name_len - x.chars().count()) + .collect::(); s.push_str(x); s }; @@ -274,7 +276,7 @@ Available lint options: for lint in lints.into_iter() { let name = lint.name_lower().replace("_", "-"); println!(" {} {:7.7} {}", - padded(name.as_slice()), lint.default_level.as_str(), lint.desc); + padded(name[]), lint.default_level.as_str(), lint.desc); } println!("\n"); }; @@ -287,7 +289,8 @@ Available lint options: .map(|&(s, _)| s.width(true)) .max().unwrap_or(0); let padded = |x: &str| { - let mut s = " ".repeat(max_name_len - x.char_len()); + let mut s = repeat(" ").take(max_name_len - x.chars().count()) + .collect::(); s.push_str(x); s }; @@ -303,7 +306,7 @@ Available lint options: let desc = to.into_iter().map(|x| x.as_str().replace("_", "-")) .collect::>().connect(", "); println!(" {} {}", - padded(name.as_slice()), desc); + padded(name[]), desc); } println!("\n"); }; @@ -367,10 +370,10 @@ pub fn handle_options(mut args: Vec) -> Option { } let matches = - match getopts::getopts(args.as_slice(), config::optgroups().as_slice()) { + match getopts::getopts(args[], config::optgroups()[]) { Ok(m) => m, Err(f) => { - early_error(f.to_string().as_slice()); + early_error(f.to_string()[]); } }; @@ -518,7 +521,7 @@ pub fn monitor(f: F) { "run with `RUST_BACKTRACE=1` for a backtrace".to_string(), ]; for note in xs.iter() { - emitter.emit(None, note.as_slice(), None, diagnostic::Note) + emitter.emit(None, note[], None, diagnostic::Note) } match r.read_to_string() { @@ -526,8 +529,7 @@ pub fn monitor(f: F) { Err(e) => { emitter.emit(None, format!("failed to read internal \ - stderr: {}", - e).as_slice(), + stderr: {}", e)[], None, diagnostic::Error) } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 2eb9d2c67a7..4b10ca92e70 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -71,10 +71,10 @@ pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option`, `typed`, `identified`, \ - or `expanded,identified`; got {}", name).as_slice()); + or `expanded,identified`; got {}", name)[]); } }; - let opt_second = opt_second.and_then::(from_str); + let opt_second = opt_second.and_then(|s| s.parse::()); (first, opt_second) } @@ -276,7 +276,7 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { try!(pp::word(&mut s.s, ppaux::ty_to_string( tcx, - ty::expr_ty(tcx, expr)).as_slice())); + ty::expr_ty(tcx, expr))[])); s.pclose() } _ => Ok(()) @@ -311,7 +311,7 @@ pub enum UserIdentifiedItem { impl FromStr for UserIdentifiedItem { fn from_str(s: &str) -> Option { - from_str(s).map(ItemViaNode).or_else(|| { + s.parse().map(ItemViaNode).or_else(|| { let v : Vec<_> = s.split_str("::") .map(|x|x.to_string()) .collect(); @@ -322,7 +322,7 @@ impl FromStr for UserIdentifiedItem { enum NodesMatchingUII<'a, 'ast: 'a> { NodesMatchingDirect(option::IntoIter), - NodesMatchingSuffix(ast_map::NodesMatchingSuffix<'a, 'ast, String>), + NodesMatchingSuffix(ast_map::NodesMatchingSuffix<'a, 'ast>), } impl<'a, 'ast> Iterator for NodesMatchingUII<'a, 'ast> { @@ -348,7 +348,7 @@ impl UserIdentifiedItem { ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), ItemViaPath(ref parts) => - NodesMatchingSuffix(map.nodes_matching_suffix(parts.as_slice())), + NodesMatchingSuffix(map.nodes_matching_suffix(parts[])), } } @@ -360,7 +360,7 @@ impl UserIdentifiedItem { user_option, self.reconstructed_input(), is_wrong_because); - sess.fatal(message.as_slice()) + sess.fatal(message[]) }; let mut saw_node = ast::DUMMY_NODE_ID; @@ -414,12 +414,12 @@ pub fn pretty_print_input(sess: Session, opt_uii: Option, ofile: Option) { let krate = driver::phase_1_parse_input(&sess, cfg, input); - let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), input); + let id = link::find_crate_name(Some(&sess), krate.attrs[], input); let is_expanded = needs_expansion(&ppm); let compute_ast_map = needs_ast_map(&ppm, &opt_uii); let krate = if compute_ast_map { - match driver::phase_2_configure_and_expand(&sess, krate, id.as_slice(), None) { + match driver::phase_2_configure_and_expand(&sess, krate, id[], None) { None => return, Some(k) => k } @@ -438,7 +438,7 @@ pub fn pretty_print_input(sess: Session, }; let src_name = driver::source_name(input); - let src = sess.codemap().get_filemap(src_name.as_slice()) + let src = sess.codemap().get_filemap(src_name[]) .src.as_bytes().to_vec(); let mut rdr = MemReader::new(src); @@ -499,7 +499,7 @@ pub fn pretty_print_input(sess: Session, debug!("pretty printing flow graph for {}", opt_uii); let uii = opt_uii.unwrap_or_else(|| { sess.fatal(format!("`pretty flowgraph=..` needs NodeId (int) or - unique path suffix (b::c::d)").as_slice()) + unique path suffix (b::c::d)")[]) }); let ast_map = ast_map.expect("--pretty flowgraph missing ast_map"); @@ -507,7 +507,7 @@ pub fn pretty_print_input(sess: Session, let node = ast_map.find(nodeid).unwrap_or_else(|| { sess.fatal(format!("--pretty flowgraph couldn't find id: {}", - nodeid).as_slice()) + nodeid)[]) }); let code = blocks::Code::from_node(node); @@ -526,8 +526,8 @@ pub fn pretty_print_input(sess: Session, // point to what was found, if there's an // accessible span. match ast_map.opt_span(nodeid) { - Some(sp) => sess.span_fatal(sp, message.as_slice()), - None => sess.fatal(message.as_slice()) + Some(sp) => sess.span_fatal(sp, message[]), + None => sess.fatal(message[]) } } } @@ -587,7 +587,7 @@ fn print_flowgraph(variants: Vec, let m = "graphviz::render failed"; io::IoError { detail: Some(match orig_detail { - None => m.into_string(), + None => m.to_string(), Some(d) => format!("{}: {}", m, d) }), ..ioerr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d4a0b49436d..bf9e9294307 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -97,8 +97,8 @@ use std::mem::replace; use std::rc::{Rc, Weak}; use std::uint; -// Definition mapping -pub type DefMap = RefCell>; +mod check_unused; +mod record_exports; #[deriving(Copy)] struct BindingInfo { @@ -1119,14 +1119,14 @@ impl<'a> Resolver<'a> { self.resolve_error(sp, format!("duplicate definition of {} `{}`", namespace_error_to_string(duplicate_type), - token::get_name(name)).as_slice()); + token::get_name(name))[]); { let r = child.span_for_namespace(ns); for sp in r.iter() { self.session.span_note(*sp, format!("first definition of {} `{}` here", namespace_error_to_string(duplicate_type), - token::get_name(name)).as_slice()); + token::get_name(name))[]); } } } @@ -2147,7 +2147,7 @@ impl<'a> Resolver<'a> { debug!("(building import directive) building import \ directive: {}::{}", self.names_to_string(module_.imports.borrow().last().unwrap() - .module_path.as_slice()), + .module_path[]), token::get_name(target)); let mut import_resolutions = module_.import_resolutions @@ -2265,10 +2265,10 @@ impl<'a> Resolver<'a> { let msg = format!("unresolved import `{}`{}", self.import_path_to_string( import_directive.module_path - .as_slice(), + [], import_directive.subclass), help); - self.resolve_error(span, msg.as_slice()); + self.resolve_error(span, msg[]); } Indeterminate => break, // Bail out. We'll come around next time. Success(()) => () // Good. Continue. @@ -2298,7 +2298,7 @@ impl<'a> Resolver<'a> { .iter() .map(|seg| seg.identifier.name) .collect(); - self.names_to_string(names.as_slice()) + self.names_to_string(names[]) } fn import_directive_subclass_to_string(&mut self, @@ -2340,7 +2340,7 @@ impl<'a> Resolver<'a> { debug!("(resolving import for module) resolving import `{}::...` in \ `{}`", - self.names_to_string(module_path.as_slice()), + self.names_to_string(module_path[]), self.module_to_string(&*module_)); // First, resolve the module path for the directive, if necessary. @@ -2349,7 +2349,7 @@ impl<'a> Resolver<'a> { Some((self.graph_root.get_module(), LastMod(AllPublic))) } else { match self.resolve_module_path(module_.clone(), - module_path.as_slice(), + module_path[], DontUseLexicalScope, import_directive.span, ImportSearch) { @@ -2941,7 +2941,7 @@ impl<'a> Resolver<'a> { ValueNS => "value", }, token::get_name(name).get()); - self.session.span_err(import_span, msg.as_slice()); + self.session.span_err(import_span, msg[]); } Some(_) | None => {} } @@ -2956,7 +2956,7 @@ impl<'a> Resolver<'a> { if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) { let msg = format!("`{}` is not directly importable", token::get_name(name)); - self.session.span_err(import_span, msg.as_slice()); + self.session.span_err(import_span, msg[]); } } @@ -2981,7 +2981,7 @@ impl<'a> Resolver<'a> { crate in this module \ (maybe you meant `use {0}::*`?)", token::get_name(name).get()); - self.session.span_err(import_span, msg.as_slice()); + self.session.span_err(import_span, msg[]); } Some(_) | None => {} } @@ -3003,7 +3003,7 @@ impl<'a> Resolver<'a> { let msg = format!("import `{}` conflicts with value \ in this module", token::get_name(name).get()); - self.session.span_err(import_span, msg.as_slice()); + self.session.span_err(import_span, msg[]); if let Some(span) = value.value_span { self.session.span_note(span, "conflicting value here"); @@ -3021,7 +3021,7 @@ impl<'a> Resolver<'a> { let msg = format!("import `{}` conflicts with type in \ this module", token::get_name(name).get()); - self.session.span_err(import_span, msg.as_slice()); + self.session.span_err(import_span, msg[]); if let Some(span) = ty.type_span { self.session.span_note(span, "note conflicting type here") @@ -3034,7 +3034,7 @@ impl<'a> Resolver<'a> { let msg = format!("inherent implementations \ are only allowed on types \ defined in the current module"); - self.session.span_err(span, msg.as_slice()); + self.session.span_err(span, msg[]); self.session.span_note(import_span, "import from other module here") } @@ -3043,7 +3043,7 @@ impl<'a> Resolver<'a> { let msg = format!("import `{}` conflicts with existing \ submodule", token::get_name(name).get()); - self.session.span_err(import_span, msg.as_slice()); + self.session.span_err(import_span, msg[]); if let Some(span) = ty.type_span { self.session.span_note(span, "note conflicting module here") @@ -3073,7 +3073,7 @@ impl<'a> Resolver<'a> { .span_err(span, format!("an external crate named `{}` has already \ been imported into this module", - token::get_name(name).get()).as_slice()); + token::get_name(name).get())[]); } } @@ -3092,7 +3092,7 @@ impl<'a> Resolver<'a> { format!("the name `{}` conflicts with an external \ crate that has been imported into this \ module", - token::get_name(name).get()).as_slice()); + token::get_name(name).get())[]); } } @@ -3140,7 +3140,7 @@ impl<'a> Resolver<'a> { let segment_name = token::get_name(name); let module_name = self.module_to_string(&*search_module); let mut span = span; - let msg = if "???" == module_name.as_slice() { + let msg = if "???" == module_name[] { span.hi = span.lo + Pos::from_uint(segment_name.get().len()); match search_parent_externals(name, @@ -3253,14 +3253,14 @@ impl<'a> Resolver<'a> { match module_prefix_result { Failed(None) => { let mpath = self.names_to_string(module_path); - let mpath = mpath.as_slice(); + let mpath = mpath[]; match mpath.rfind(':') { Some(idx) => { let msg = format!("Could not find `{}` in `{}`", // idx +- 1 to account for the // colons on either side - mpath.slice_from(idx + 1), - mpath.slice_to(idx - 1)); + mpath[idx + 1..], + mpath[0..idx - 1]); return Failed(Some((span, msg))); }, None => { @@ -3431,7 +3431,7 @@ impl<'a> Resolver<'a> { true) { Failed(Some((span, msg))) => self.resolve_error(span, format!("failed to resolve. {}", - msg)), + msg)[]), Failed(None) => (), // Continue up the search chain. Indeterminate => { // We couldn't see through the higher scope because of an @@ -3686,8 +3686,8 @@ impl<'a> Resolver<'a> { "unresolved import"); } else { let err = format!("unresolved import (maybe you meant `{}::*`?)", - sn.slice(0, sn.len())); - self.resolve_error((*imports)[index].span, err.as_slice()); + sn); + self.resolve_error((*imports)[index].span, err[]); } } @@ -3779,7 +3779,7 @@ impl<'a> Resolver<'a> { match def_like { DlDef(d @ DefUpvar(..)) => { self.session.span_bug(span, - format!("unexpected {} in bindings", d).as_slice()) + format!("unexpected {} in bindings", d)[]) } DlDef(d @ DefLocal(_)) => { let node_id = d.def_id().node; @@ -3995,7 +3995,7 @@ impl<'a> Resolver<'a> { generics, implemented_traits, &**self_type, - impl_items.as_slice()); + impl_items[]); } ItemTrait(_, ref generics, ref unbound, ref bounds, ref trait_items) => { @@ -4080,7 +4080,7 @@ impl<'a> Resolver<'a> { ItemStruct(ref struct_def, ref generics) => { self.resolve_struct(item.id, generics, - struct_def.fields.as_slice()); + struct_def.fields[]); } ItemMod(ref module_) => { @@ -4153,7 +4153,7 @@ impl<'a> Resolver<'a> { parameter in this type \ parameter list", token::get_name( - name)).as_slice()) + name))[]) } seen_bindings.insert(name); @@ -4330,7 +4330,7 @@ impl<'a> Resolver<'a> { }; let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str); - self.resolve_error(trait_reference.path.span, msg.as_slice()); + self.resolve_error(trait_reference.path.span, msg[]); } Some(def) => { match def { @@ -4342,14 +4342,14 @@ impl<'a> Resolver<'a> { self.resolve_error(trait_reference.path.span, format!("`{}` is not a trait", self.path_names_to_string( - &trait_reference.path))); + &trait_reference.path))[]); // If it's a typedef, give a note if let DefTy(..) = def { self.session.span_note( trait_reference.path.span, format!("`type` aliases cannot be used for traits") - .as_slice()); + []); } } } @@ -4546,7 +4546,7 @@ impl<'a> Resolver<'a> { self.resolve_error(span, format!("method `{}` is not a member of trait `{}`", token::get_name(name), - path_str).as_slice()); + path_str)[]); } } } @@ -4613,7 +4613,7 @@ impl<'a> Resolver<'a> { format!("variable `{}` from pattern #1 is \ not bound in pattern #{}", token::get_name(key), - i + 1).as_slice()); + i + 1)[]); } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { @@ -4622,7 +4622,7 @@ impl<'a> Resolver<'a> { format!("variable `{}` is bound with different \ mode in pattern #{} than in pattern #1", token::get_name(key), - i + 1).as_slice()); + i + 1)[]); } } } @@ -4635,7 +4635,7 @@ impl<'a> Resolver<'a> { format!("variable `{}` from pattern {}{} is \ not bound in pattern {}1", token::get_name(key), - "#", i + 1, "#").as_slice()); + "#", i + 1, "#")[]); } } } @@ -4752,7 +4752,7 @@ impl<'a> Resolver<'a> { None => { let msg = format!("use of undeclared type name `{}`", self.path_names_to_string(path)); - self.resolve_error(ty.span, msg.as_slice()); + self.resolve_error(ty.span, msg[]); } } } @@ -4832,7 +4832,7 @@ impl<'a> Resolver<'a> { format!("declaration of `{}` shadows an enum \ variant or unit-like struct in \ scope", - token::get_name(renamed)).as_slice()); + token::get_name(renamed))[]); } FoundConst(ref def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ @@ -4884,7 +4884,7 @@ impl<'a> Resolver<'a> { list", token::get_ident( ident)) - .as_slice()) + []) } else if bindings_list.get(&renamed) == Some(&pat_id) { // Then this is a duplicate variable in the @@ -4893,7 +4893,7 @@ impl<'a> Resolver<'a> { format!("identifier `{}` is bound \ more than once in the same \ pattern", - token::get_ident(ident)).as_slice()); + token::get_ident(ident))[]); } // Else, not bound in the same pattern: do // nothing. @@ -4922,7 +4922,7 @@ impl<'a> Resolver<'a> { path.segments .last() .unwrap() - .identifier)).as_slice()); + .identifier))[]); } None => { self.resolve_error(path.span, @@ -4931,7 +4931,7 @@ impl<'a> Resolver<'a> { path.segments .last() .unwrap() - .identifier)).as_slice()); + .identifier))[]); } } @@ -4962,7 +4962,7 @@ impl<'a> Resolver<'a> { def: {}", result); let msg = format!("`{}` does not name a structure", self.path_names_to_string(path)); - self.resolve_error(path.span, msg.as_slice()); + self.resolve_error(path.span, msg[]); } } } @@ -5024,7 +5024,7 @@ impl<'a> Resolver<'a> { match err { Some((span, msg)) => { self.resolve_error(span, format!("failed to resolve: {}", - msg)); + msg)[]); } None => () } @@ -5220,7 +5220,7 @@ impl<'a> Resolver<'a> { let last_private; let module = self.current_module.clone(); match self.resolve_module_path(module, - module_path.as_slice(), + module_path[], UseLexicalScope, path.span, PathSearch) { @@ -5235,7 +5235,7 @@ impl<'a> Resolver<'a> { }; self.resolve_error(span, format!("failed to resolve. {}", - msg.as_slice())); + msg)[]); return None; } Indeterminate => panic!("indeterminate unexpected"), @@ -5278,7 +5278,7 @@ impl<'a> Resolver<'a> { let containing_module; let last_private; match self.resolve_module_path_from_root(root_module, - module_path.as_slice(), + module_path[], 0, path.span, PathSearch, @@ -5288,13 +5288,13 @@ impl<'a> Resolver<'a> { Some((span, msg)) => (span, msg), None => { let msg = format!("Use of undeclared module `::{}`", - self.names_to_string(module_path.as_slice())); + self.names_to_string(module_path[])); (path.span, msg) } }; self.resolve_error(span, format!("failed to resolve. {}", - msg.as_slice())); + msg)[]); return None; } @@ -5335,7 +5335,7 @@ impl<'a> Resolver<'a> { } TypeNS => { let name = ident.name; - self.search_ribs(self.type_ribs.as_slice(), name, span) + self.search_ribs(self.type_ribs[], name, span) } }; @@ -5389,7 +5389,8 @@ impl<'a> Resolver<'a> { Failed(err) => { match err { Some((span, msg)) => - self.resolve_error(span, format!("failed to resolve. {}", msg)), + self.resolve_error(span, format!("failed to resolve. {}", + msg)[]), None => () } @@ -5409,9 +5410,9 @@ impl<'a> Resolver<'a> { rs } - fn resolve_error(&self, span: Span, s: T) { + fn resolve_error(&self, span: Span, s: &str) { if self.emit_errors { - self.session.span_err(span, s.as_slice()); + self.session.span_err(span, s); } } @@ -5446,7 +5447,7 @@ impl<'a> Resolver<'a> { } } else { match this.resolve_module_path(root, - name_path.as_slice(), + name_path[], UseLexicalScope, span, PathSearch) { @@ -5484,7 +5485,7 @@ impl<'a> Resolver<'a> { let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::>(); // Look for a method in the current self type's impl module. - match get_module(self, path.span, name_path.as_slice()) { + match get_module(self, path.span, name_path[]) { Some(module) => match module.children.borrow().get(&name) { Some(binding) => { let p_str = self.path_names_to_string(&path); @@ -5695,7 +5696,7 @@ impl<'a> Resolver<'a> { def: {}", result); let msg = format!("`{}` does not name a structure", self.path_names_to_string(path)); - self.resolve_error(path.span, msg.as_slice()); + self.resolve_error(path.span, msg[]); } } @@ -5751,13 +5752,13 @@ impl<'a> Resolver<'a> { ExprBreak(Some(label)) | ExprAgain(Some(label)) => { let renamed = mtwt::resolve(label); - match self.search_ribs(self.label_ribs.as_slice(), + match self.search_ribs(self.label_ribs[], renamed, expr.span) { None => { self.resolve_error( expr.span, format!("use of undeclared label `{}`", - token::get_ident(label)).as_slice()) + token::get_ident(label))[]) } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. @@ -5893,7 +5894,7 @@ impl<'a> Resolver<'a> { then {}", node_id, *entry.get(), - def).as_slice()); + def)[]); }, Vacant(entry) => { entry.set(def); }, } @@ -5909,7 +5910,7 @@ impl<'a> Resolver<'a> { self.resolve_error(pat.span, format!("cannot use `ref` binding mode \ with {}", - descr).as_slice()); + descr)[]); } } } @@ -5945,8 +5946,7 @@ impl<'a> Resolver<'a> { return "???".to_string(); } self.names_to_string(names.into_iter().rev() - .collect::>() - .as_slice()) + .collect::>()[]) } #[allow(dead_code)] // useful for debugging diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 5617110bfec..ec61d3a6953 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -126,7 +126,7 @@ pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: &Input) -> String { let validate = |s: String, span: Option| { - creader::validate_crate_name(sess, s.as_slice(), span); + creader::validate_crate_name(sess, s[], span); s }; @@ -144,7 +144,7 @@ pub fn find_crate_name(sess: Option<&Session>, let msg = format!("--crate-name and #[crate_name] are \ required to match, but `{}` != `{}`", s, name); - sess.span_err(attr.span, msg.as_slice()); + sess.span_err(attr.span, msg[]); } } return validate(s.clone(), None); @@ -190,17 +190,17 @@ fn symbol_hash<'tcx>(tcx: &ty::ctxt<'tcx>, // to be independent of one another in the crate. symbol_hasher.reset(); - symbol_hasher.input_str(link_meta.crate_name.as_slice()); + symbol_hasher.input_str(link_meta.crate_name[]); symbol_hasher.input_str("-"); symbol_hasher.input_str(link_meta.crate_hash.as_str()); for meta in tcx.sess.crate_metadata.borrow().iter() { - symbol_hasher.input_str(meta.as_slice()); + symbol_hasher.input_str(meta[]); } symbol_hasher.input_str("-"); - symbol_hasher.input_str(encoder::encoded_ty(tcx, t).as_slice()); + symbol_hasher.input_str(encoder::encoded_ty(tcx, t)[]); // Prefix with 'h' so that it never blends into adjacent digits let mut hash = String::from_str("h"); - hash.push_str(truncated_hash_result(symbol_hasher).as_slice()); + hash.push_str(truncated_hash_result(symbol_hasher)[]); hash } @@ -249,7 +249,7 @@ pub fn sanitize(s: &str) -> String { let mut tstr = String::new(); for c in c.escape_unicode() { tstr.push(c) } result.push('$'); - result.push_str(tstr.slice_from(1)); + result.push_str(tstr[1..]); } } } @@ -258,7 +258,7 @@ pub fn sanitize(s: &str) -> String { if result.len() > 0u && result.as_bytes()[0] != '_' as u8 && ! (result.as_bytes()[0] as char).is_xid_start() { - return format!("_{}", result.as_slice()); + return format!("_{}", result[]); } return result; @@ -284,12 +284,12 @@ pub fn mangle>(mut path: PI, fn push(n: &mut String, s: &str) { let sani = sanitize(s); - n.push_str(format!("{}{}", sani.len(), sani).as_slice()); + n.push_str(format!("{}{}", sani.len(), sani)[]); } // First, connect each component with pairs. for e in path { - push(&mut n, token::get_name(e.name()).get().as_slice()) + push(&mut n, token::get_name(e.name()).get()[]) } match hash { @@ -327,17 +327,17 @@ pub fn mangle_exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, path: PathEl hash.push(EXTRA_CHARS.as_bytes()[extra2] as char); hash.push(EXTRA_CHARS.as_bytes()[extra3] as char); - exported_name(path, hash.as_slice()) + exported_name(path, hash[]) } pub fn mangle_internal_name_by_type_and_seq<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, name: &str) -> String { let s = ppaux::ty_to_string(ccx.tcx(), t); - let path = [PathName(token::intern(s.as_slice())), + let path = [PathName(token::intern(s[])), gensym_name(name)]; let hash = get_symbol_hash(ccx, t); - mangle(ast_map::Values(path.iter()), Some(hash.as_slice())) + mangle(ast_map::Values(path.iter()), Some(hash[])) } pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> String { @@ -357,7 +357,7 @@ pub fn remove(sess: &Session, path: &Path) { Err(e) => { sess.err(format!("failed to remove {}: {}", path.display(), - e).as_slice()); + e)[]); } } } @@ -372,7 +372,7 @@ pub fn link_binary(sess: &Session, for &crate_type in sess.crate_types.borrow().iter() { if invalid_output_for_target(sess, crate_type) { sess.bug(format!("invalid output type `{}` for target os `{}`", - crate_type, sess.opts.target_triple).as_slice()); + crate_type, sess.opts.target_triple)[]); } let out_file = link_binary_output(sess, trans, crate_type, outputs, crate_name); @@ -437,8 +437,8 @@ pub fn filename_for_input(sess: &Session, out_filename.with_filename(format!("lib{}.rlib", libname)) } config::CrateTypeDylib => { - let (prefix, suffix) = (sess.target.target.options.dll_prefix.as_slice(), - sess.target.target.options.dll_suffix.as_slice()); + let (prefix, suffix) = (sess.target.target.options.dll_prefix[], + sess.target.target.options.dll_suffix[]); out_filename.with_filename(format!("{}{}{}", prefix, libname, @@ -448,7 +448,7 @@ pub fn filename_for_input(sess: &Session, out_filename.with_filename(format!("lib{}.a", libname)) } config::CrateTypeExecutable => { - let suffix = sess.target.target.options.exe_suffix.as_slice(); + let suffix = sess.target.target.options.exe_suffix[]; out_filename.with_filename(format!("{}{}", libname, suffix)) } } @@ -477,12 +477,12 @@ fn link_binary_output(sess: &Session, if !out_is_writeable { sess.fatal(format!("output file {} is not writeable -- check its \ permissions.", - out_filename.display()).as_slice()); + out_filename.display())[]); } else if !obj_is_writeable { sess.fatal(format!("object file {} is not writeable -- check its \ permissions.", - obj_filename.display()).as_slice()); + obj_filename.display())[]); } match crate_type { @@ -507,7 +507,7 @@ fn archive_search_paths(sess: &Session) -> Vec { let mut rustpath = filesearch::rust_path(); rustpath.push(sess.target_filesearch().get_lib_path()); let mut search: Vec = sess.opts.addl_lib_search_paths.borrow().clone(); - search.push_all(rustpath.as_slice()); + search.push_all(rustpath[]); return search; } @@ -536,7 +536,7 @@ fn link_rlib<'a>(sess: &'a Session, for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() { match kind { cstore::NativeStatic => { - ab.add_native_library(l.as_slice()).unwrap(); + ab.add_native_library(l[]).unwrap(); } cstore::NativeFramework | cstore::NativeUnknown => {} } @@ -584,12 +584,12 @@ fn link_rlib<'a>(sess: &'a Session, let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir"); let metadata = tmpdir.path().join(METADATA_FILENAME); match fs::File::create(&metadata).write(trans.metadata - .as_slice()) { + []) { Ok(..) => {} Err(e) => { sess.err(format!("failed to write {}: {}", metadata.display(), - e).as_slice()); + e)[]); sess.abort_if_errors(); } } @@ -605,27 +605,27 @@ fn link_rlib<'a>(sess: &'a Session, // extension to it. This is to work around a bug in LLDB that // would cause it to crash if the name of a file in an archive // was exactly 16 bytes. - let bc_filename = obj_filename.with_extension(format!("{}.bc", i).as_slice()); + let bc_filename = obj_filename.with_extension(format!("{}.bc", i)[]); let bc_deflated_filename = obj_filename.with_extension( - format!("{}.bytecode.deflate", i).as_slice()); + format!("{}.bytecode.deflate", i)[]); let bc_data = match fs::File::open(&bc_filename).read_to_end() { Ok(buffer) => buffer, Err(e) => sess.fatal(format!("failed to read bytecode: {}", - e).as_slice()) + e)[]) }; - let bc_data_deflated = match flate::deflate_bytes(bc_data.as_slice()) { + let bc_data_deflated = match flate::deflate_bytes(bc_data[]) { Some(compressed) => compressed, None => sess.fatal(format!("failed to compress bytecode from {}", - bc_filename.display()).as_slice()) + bc_filename.display())[]) }; let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) { Ok(file) => file, Err(e) => { sess.fatal(format!("failed to create compressed bytecode \ - file: {}", e).as_slice()) + file: {}", e)[]) } }; @@ -634,7 +634,7 @@ fn link_rlib<'a>(sess: &'a Session, Ok(()) => {} Err(e) => { sess.err(format!("failed to write compressed bytecode: \ - {}", e).as_slice()); + {}", e)[]); sess.abort_if_errors() } }; @@ -674,7 +674,7 @@ fn write_rlib_bytecode_object_v1(writer: &mut T, try! { writer.write(RLIB_BYTECODE_OBJECT_MAGIC) }; try! { writer.write_le_u32(1) }; try! { writer.write_le_u64(bc_data_deflated_size) }; - try! { writer.write(bc_data_deflated.as_slice()) }; + try! { writer.write(bc_data_deflated[]) }; let number_of_bytes_written_so_far = RLIB_BYTECODE_OBJECT_MAGIC.len() + // magic id @@ -725,11 +725,11 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { let p = match *path { Some(ref p) => p.clone(), None => { sess.err(format!("could not find rlib for: `{}`", - name).as_slice()); + name)[]); continue } }; - ab.add_rlib(&p, name.as_slice(), sess.lto()).unwrap(); + ab.add_rlib(&p, name[], sess.lto()).unwrap(); let native_libs = csearch::get_native_libraries(&sess.cstore, cnum); all_native_libs.extend(native_libs.into_iter()); @@ -751,7 +751,7 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { cstore::NativeUnknown => "library", cstore::NativeFramework => "framework", }; - sess.note(format!("{}: {}", name, *lib).as_slice()); + sess.note(format!("{}: {}", name, *lib)[]); } } @@ -765,12 +765,12 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, // The invocations of cc share some flags across platforms let pname = get_cc_prog(sess); - let mut cmd = Command::new(pname.as_slice()); + let mut cmd = Command::new(pname[]); - cmd.args(sess.target.target.options.pre_link_args.as_slice()); + cmd.args(sess.target.target.options.pre_link_args[]); link_args(&mut cmd, sess, dylib, tmpdir.path(), trans, obj_filename, out_filename); - cmd.args(sess.target.target.options.post_link_args.as_slice()); + cmd.args(sess.target.target.options.post_link_args[]); if !sess.target.target.options.no_compiler_rt { cmd.arg("-lcompiler-rt"); } @@ -790,11 +790,11 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, if !prog.status.success() { sess.err(format!("linking with `{}` failed: {}", pname, - prog.status).as_slice()); - sess.note(format!("{}", &cmd).as_slice()); + prog.status)[]); + sess.note(format!("{}", &cmd)[]); let mut output = prog.error.clone(); - output.push_all(prog.output.as_slice()); - sess.note(str::from_utf8(output.as_slice()).unwrap()); + output.push_all(prog.output[]); + sess.note(str::from_utf8(output[]).unwrap()); sess.abort_if_errors(); } debug!("linker stderr:\n{}", String::from_utf8(prog.error).unwrap()); @@ -803,7 +803,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, Err(e) => { sess.err(format!("could not exec the linker `{}`: {}", pname, - e).as_slice()); + e)[]); sess.abort_if_errors(); } } @@ -815,7 +815,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, match Command::new("dsymutil").arg(out_filename).output() { Ok(..) => {} Err(e) => { - sess.err(format!("failed to run dsymutil: {}", e).as_slice()); + sess.err(format!("failed to run dsymutil: {}", e)[]); sess.abort_if_errors(); } } @@ -864,7 +864,7 @@ fn link_args(cmd: &mut Command, let mut v = b"-Wl,-force_load,".to_vec(); v.push_all(morestack.as_vec()); - cmd.arg(v.as_slice()); + cmd.arg(v[]); } else { cmd.args(&["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]); } @@ -989,7 +989,7 @@ fn link_args(cmd: &mut Command, if sess.opts.cg.rpath { let mut v = "-Wl,-install_name,@rpath/".as_bytes().to_vec(); v.push_all(out_filename.filename().unwrap()); - cmd.arg(v.as_slice()); + cmd.arg(v[]); } } else { cmd.arg("-shared"); @@ -1001,7 +1001,7 @@ fn link_args(cmd: &mut Command, // addl_lib_search_paths if sess.opts.cg.rpath { let sysroot = sess.sysroot(); - let target_triple = sess.opts.target_triple.as_slice(); + let target_triple = sess.opts.target_triple[]; let get_install_prefix_lib_path = |:| { let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX"); let tlib = filesearch::relative_target_lib_path(sysroot, target_triple); @@ -1018,14 +1018,14 @@ fn link_args(cmd: &mut Command, get_install_prefix_lib_path: get_install_prefix_lib_path, realpath: ::util::fs::realpath }; - cmd.args(rpath::get_rpath_flags(rpath_config).as_slice()); + cmd.args(rpath::get_rpath_flags(rpath_config)[]); } // Finally add all the linker arguments provided on the command line along // with any #[link_args] attributes found inside the crate let empty = Vec::new(); - cmd.args(sess.opts.cg.link_args.as_ref().unwrap_or(&empty).as_slice()); - cmd.args(used_link_args.as_slice()); + cmd.args(sess.opts.cg.link_args.as_ref().unwrap_or(&empty)[]); + cmd.args(used_link_args[]); } // # Native library linking @@ -1083,14 +1083,14 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { } else { // -force_load is the OSX equivalent of --whole-archive, but it // involves passing the full path to the library to link. - let lib = archive::find_library(l.as_slice(), - sess.target.target.options.staticlib_prefix.as_slice(), - sess.target.target.options.staticlib_suffix.as_slice(), - search_path.as_slice(), + let lib = archive::find_library(l[], + sess.target.target.options.staticlib_prefix[], + sess.target.target.options.staticlib_suffix[], + search_path[], &sess.diagnostic().handler); let mut v = b"-Wl,-force_load,".to_vec(); v.push_all(lib.as_vec()); - cmd.arg(v.as_slice()); + cmd.arg(v[]); } } if takes_hints { @@ -1103,7 +1103,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { cmd.arg(format!("-l{}", l)); } cstore::NativeFramework => { - cmd.arg("-framework").arg(l.as_slice()); + cmd.arg("-framework").arg(l[]); } cstore::NativeStatic => unreachable!(), } @@ -1184,9 +1184,9 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // against the archive. if sess.lto() { let name = cratepath.filename_str().unwrap(); - let name = name.slice(3, name.len() - 5); // chop off lib/.rlib + let name = name[3..name.len() - 5]; // chop off lib/.rlib time(sess.time_passes(), - format!("altering {}.rlib", name).as_slice(), + format!("altering {}.rlib", name)[], (), |()| { let dst = tmpdir.join(cratepath.filename().unwrap()); match fs::copy(&cratepath, &dst) { @@ -1195,7 +1195,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, sess.err(format!("failed to copy {} to {}: {}", cratepath.display(), dst.display(), - e).as_slice()); + e)[]); sess.abort_if_errors(); } } @@ -1207,7 +1207,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, Err(e) => { sess.err(format!("failed to chmod {} when preparing \ for LTO: {}", dst.display(), - e).as_slice()); + e)[]); sess.abort_if_errors(); } } @@ -1221,9 +1221,9 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, maybe_ar_prog: sess.opts.cg.ar.clone() }; let mut archive = Archive::open(config); - archive.remove_file(format!("{}.o", name).as_slice()); + archive.remove_file(format!("{}.o", name)[]); let files = archive.files(); - if files.iter().any(|s| s.as_slice().ends_with(".o")) { + if files.iter().any(|s| s[].ends_with(".o")) { cmd.arg(dst); } }); @@ -1245,7 +1245,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, let mut v = "-l".as_bytes().to_vec(); v.push_all(unlib(&sess.target, cratepath.filestem().unwrap())); - cmd.arg(v.as_slice()); + cmd.arg(v[]); } } @@ -1287,7 +1287,7 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) { } cstore::NativeFramework => { cmd.arg("-framework"); - cmd.arg(lib.as_slice()); + cmd.arg(lib[]); } cstore::NativeStatic => { sess.bug("statics shouldn't be propagated"); diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index b9357280d06..1271330897e 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -53,21 +53,21 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, Some(p) => p, None => { sess.fatal(format!("could not find rlib for: `{}`", - name).as_slice()); + name)[]); } }; let archive = ArchiveRO::open(&path).expect("wanted an rlib"); let file = path.filename_str().unwrap(); - let file = file.slice(3, file.len() - 5); // chop off lib/.rlib + let file = file[3..file.len() - 5]; // chop off lib/.rlib debug!("reading {}", file); for i in iter::count(0u, 1) { let bc_encoded = time(sess.time_passes(), - format!("check for {}.{}.bytecode.deflate", name, i).as_slice(), + format!("check for {}.{}.bytecode.deflate", name, i)[], (), |_| { archive.read(format!("{}.{}.bytecode.deflate", - file, i).as_slice()) + file, i)[]) }); let bc_encoded = match bc_encoded { Some(data) => data, @@ -75,7 +75,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, if i == 0 { // No bitcode was found at all. sess.fatal(format!("missing compressed bytecode in {}", - path.display()).as_slice()); + path.display())[]); } // No more bitcode files to read. break; @@ -98,12 +98,12 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, Some(inflated) => inflated, None => { sess.fatal(format!("failed to decompress bc of `{}`", - name).as_slice()) + name)[]) } } } else { sess.fatal(format!("Unsupported bytecode format version {}", - version).as_slice()) + version)[]) } }) } else { @@ -114,7 +114,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, Some(bc) => bc, None => { sess.fatal(format!("failed to decompress bc of `{}`", - name).as_slice()) + name)[]) } } }) @@ -123,7 +123,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, let ptr = bc_decoded.as_slice().as_ptr(); debug!("linking {}, part {}", name, i); time(sess.time_passes(), - format!("ll link {}.{}", name, i).as_slice(), + format!("ll link {}.{}", name, i)[], (), |()| unsafe { if !llvm::LLVMRustLinkInExternalBitcode(llmod, @@ -131,7 +131,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, bc_decoded.len() as libc::size_t) { write::llvm_err(sess.diagnostic().handler(), format!("failed to load bc of `{}`", - name.as_slice())); + name[])); } }); } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 60b5b32e89f..5be66d42920 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -46,13 +46,13 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { unsafe { let cstr = llvm::LLVMRustGetLastError(); if cstr == ptr::null() { - handler.fatal(msg.as_slice()); + handler.fatal(msg[]); } else { let err = CString::new(cstr, true); let err = String::from_utf8_lossy(err.as_bytes()); handler.fatal(format!("{}: {}", - msg.as_slice(), - err.as_slice()).as_slice()); + msg[], + err[])[]); } } } @@ -103,13 +103,13 @@ impl SharedEmitter { match diag.code { Some(ref code) => { handler.emit_with_code(None, - diag.msg.as_slice(), - code.as_slice(), + diag.msg[], + code[], diag.lvl); }, None => { handler.emit(None, - diag.msg.as_slice(), + diag.msg[], diag.lvl); }, } @@ -164,8 +164,8 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { fn create_target_machine(sess: &Session) -> TargetMachineRef { let reloc_model_arg = match sess.opts.cg.relocation_model { - Some(ref s) => s.as_slice(), - None => sess.target.target.options.relocation_model.as_slice() + Some(ref s) => s[], + None => sess.target.target.options.relocation_model[] }; let reloc_model = match reloc_model_arg { "pic" => llvm::RelocPIC, @@ -176,7 +176,7 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { sess.err(format!("{} is not a valid relocation mode", sess.opts .cg - .relocation_model).as_slice()); + .relocation_model)[]); sess.abort_if_errors(); unreachable!(); } @@ -197,8 +197,8 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { let fdata_sections = ffunction_sections; let code_model_arg = match sess.opts.cg.code_model { - Some(ref s) => s.as_slice(), - None => sess.target.target.options.code_model.as_slice() + Some(ref s) => s[], + None => sess.target.target.options.code_model[] }; let code_model = match code_model_arg { @@ -211,19 +211,19 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { sess.err(format!("{} is not a valid code model", sess.opts .cg - .code_model).as_slice()); + .code_model)[]); sess.abort_if_errors(); unreachable!(); } }; - let triple = sess.target.target.llvm_target.as_slice(); + let triple = sess.target.target.llvm_target[]; let tm = unsafe { triple.with_c_str(|t| { let cpu = match sess.opts.cg.target_cpu { - Some(ref s) => s.as_slice(), - None => sess.target.target.options.cpu.as_slice() + Some(ref s) => s[], + None => sess.target.target.options.cpu[] }; cpu.with_c_str(|cpu| { target_feature(sess).with_c_str(|features| { @@ -350,13 +350,13 @@ unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef, match cgcx.lto_ctxt { Some((sess, _)) => { sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info { - Some(ei) => sess.span_err(ei.call_site, msg.as_slice()), - None => sess.err(msg.as_slice()), + Some(ei) => sess.span_err(ei.call_site, msg[]), + None => sess.err(msg[]), }); } None => { - cgcx.handler.err(msg.as_slice()); + cgcx.handler.err(msg[]); cgcx.handler.note("build without -C codegen-units for more exact errors"); } } @@ -380,8 +380,8 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo cgcx.handler.note(format!("optimization {} for {} at {}: {}", opt.kind.describe(), pass_name, - if loc.is_empty() { "[unknown]" } else { loc.as_slice() }, - llvm::twine_to_string(opt.message)).as_slice()); + if loc.is_empty() { "[unknown]" } else { loc[] }, + llvm::twine_to_string(opt.message))[]); } } @@ -413,7 +413,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_no_opt_bc { let ext = format!("{}.no-opt.bc", name_extra); - output_names.with_extension(ext.as_slice()).with_c_str(|buf| { + output_names.with_extension(ext[]).with_c_str(|buf| { llvm::LLVMWriteBitcodeToFile(llmod, buf); }) } @@ -445,7 +445,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, pass.with_c_str(|s| { if !llvm::LLVMRustAddPass(mpm, s) { cgcx.handler.warn(format!("unknown pass {}, ignoring", - *pass).as_slice()); + *pass)[]); } }) } @@ -467,7 +467,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_lto_bc { let name = format!("{}.lto.bc", name_extra); - output_names.with_extension(name.as_slice()).with_c_str(|buf| { + output_names.with_extension(name[]).with_c_str(|buf| { llvm::LLVMWriteBitcodeToFile(llmod, buf); }) } @@ -501,7 +501,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_bc { let ext = format!("{}.bc", name_extra); - output_names.with_extension(ext.as_slice()).with_c_str(|buf| { + output_names.with_extension(ext[]).with_c_str(|buf| { llvm::LLVMWriteBitcodeToFile(llmod, buf); }) } @@ -509,7 +509,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, time(config.time_passes, "codegen passes", (), |()| { if config.emit_ir { let ext = format!("{}.ll", name_extra); - output_names.with_extension(ext.as_slice()).with_c_str(|output| { + output_names.with_extension(ext[]).with_c_str(|output| { with_codegen(tm, llmod, config.no_builtins, |cpm| { llvm::LLVMRustPrintModule(cpm, llmod, output); }) @@ -517,14 +517,14 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, } if config.emit_asm { - let path = output_names.with_extension(format!("{}.s", name_extra).as_slice()); + let path = output_names.with_extension(format!("{}.s", name_extra)[]); with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType); }); } if config.emit_obj { - let path = output_names.with_extension(format!("{}.o", name_extra).as_slice()); + let path = output_names.with_extension(format!("{}.o", name_extra)[]); with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::ObjectFileType); }); @@ -638,7 +638,7 @@ pub fn run_passes(sess: &Session, // Process the work items, optionally using worker threads. if sess.opts.cg.codegen_units == 1 { - run_work_singlethreaded(sess, trans.reachable.as_slice(), work_items); + run_work_singlethreaded(sess, trans.reachable[], work_items); } else { run_work_multithreaded(sess, work_items, sess.opts.cg.codegen_units); } @@ -666,7 +666,7 @@ pub fn run_passes(sess: &Session, // 2) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. sess.warn(format!("ignoring -o because multiple .{} files were produced", - ext).as_slice()); + ext)[]); } else { // 3) Multiple codegen units, but no `-o some_name`. We // just leave the `foo.0.x` files in place. @@ -699,20 +699,20 @@ pub fn run_passes(sess: &Session, }; let pname = get_cc_prog(sess); - let mut cmd = Command::new(pname.as_slice()); + let mut cmd = Command::new(pname[]); - cmd.args(sess.target.target.options.pre_link_args.as_slice()); + cmd.args(sess.target.target.options.pre_link_args[]); cmd.arg("-nostdlib"); for index in range(0, trans.modules.len()) { - cmd.arg(crate_output.with_extension(format!("{}.o", index).as_slice())); + cmd.arg(crate_output.with_extension(format!("{}.o", index)[])); } cmd.arg("-r") .arg("-o") .arg(windows_output_path.as_ref().unwrap_or(output_path)); - cmd.args(sess.target.target.options.post_link_args.as_slice()); + cmd.args(sess.target.target.options.post_link_args[]); if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 { println!("{}", &cmd); @@ -725,14 +725,14 @@ pub fn run_passes(sess: &Session, Ok(status) => { if !status.success() { sess.err(format!("linking of {} with `{}` failed", - output_path.display(), cmd).as_slice()); + output_path.display(), cmd)[]); sess.abort_if_errors(); } }, Err(e) => { sess.err(format!("could not exec the linker `{}`: {}", pname, - e).as_slice()); + e)[]); sess.abort_if_errors(); }, } @@ -817,12 +817,12 @@ pub fn run_passes(sess: &Session, for i in range(0, trans.modules.len()) { if modules_config.emit_obj { let ext = format!("{}.o", i); - remove(sess, &crate_output.with_extension(ext.as_slice())); + remove(sess, &crate_output.with_extension(ext[])); } if modules_config.emit_bc && !keep_numbered_bitcode { let ext = format!("{}.bc", i); - remove(sess, &crate_output.with_extension(ext.as_slice())); + remove(sess, &crate_output.with_extension(ext[])); } } @@ -948,7 +948,7 @@ fn run_work_multithreaded(sess: &Session, pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { let pname = get_cc_prog(sess); - let mut cmd = Command::new(pname.as_slice()); + let mut cmd = Command::new(pname[]); cmd.arg("-c").arg("-o").arg(outputs.path(config::OutputTypeObject)) .arg(outputs.temp_path(config::OutputTypeAssembly)); @@ -959,18 +959,18 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { if !prog.status.success() { sess.err(format!("linking with `{}` failed: {}", pname, - prog.status).as_slice()); - sess.note(format!("{}", &cmd).as_slice()); + prog.status)[]); + sess.note(format!("{}", &cmd)[]); let mut note = prog.error.clone(); - note.push_all(prog.output.as_slice()); - sess.note(str::from_utf8(note.as_slice()).unwrap()); + note.push_all(prog.output[]); + sess.note(str::from_utf8(note[]).unwrap()); sess.abort_if_errors(); } }, Err(e) => { sess.err(format!("could not exec the linker `{}`: {}", pname, - e).as_slice()); + e)[]); sess.abort_if_errors(); } } @@ -1003,7 +1003,7 @@ unsafe fn configure_llvm(sess: &Session) { if sess.print_llvm_passes() { add("-debug-pass=Structure"); } for arg in sess.opts.cg.llvm_args.iter() { - add((*arg).as_slice()); + add((*arg)[]); } } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 1a4f06663ef..0183aa8c2aa 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -94,7 +94,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { // dump info about all the external crates referenced from this crate self.sess.cstore.iter_crate_data(|n, cmd| { - self.fmt.external_crate_str(krate.span, cmd.name.as_slice(), n); + self.fmt.external_crate_str(krate.span, cmd.name[], n); }); self.fmt.recorder.record("end_external_crates\n"); } @@ -143,7 +143,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { for &(ref span, ref qualname) in sub_paths.iter() { self.fmt.sub_mod_ref_str(path.span, *span, - qualname.as_slice(), + qualname[], self.cur_scope); } } @@ -161,7 +161,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { for &(ref span, ref qualname) in sub_paths.iter() { self.fmt.sub_mod_ref_str(path.span, *span, - qualname.as_slice(), + qualname[], self.cur_scope); } } @@ -180,7 +180,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let (ref span, ref qualname) = sub_paths[len-2]; self.fmt.sub_type_ref_str(path.span, *span, - qualname.as_slice()); + qualname[]); // write the other sub-paths if len <= 2 { @@ -190,7 +190,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { for &(ref span, ref qualname) in sub_paths.iter() { self.fmt.sub_mod_ref_str(path.span, *span, - qualname.as_slice(), + qualname[], self.cur_scope); } } @@ -199,7 +199,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { fn lookup_type_ref(&self, ref_id: NodeId) -> Option { if !self.analysis.ty_cx.def_map.borrow().contains_key(&ref_id) { self.sess.bug(format!("def_map has no key for {} in lookup_type_ref", - ref_id).as_slice()); + ref_id)[]); } let def = (*self.analysis.ty_cx.def_map.borrow())[ref_id]; match def { @@ -212,7 +212,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let def_map = self.analysis.ty_cx.def_map.borrow(); if !def_map.contains_key(&ref_id) { self.sess.span_bug(span, format!("def_map has no key for {} in lookup_def_kind", - ref_id).as_slice()); + ref_id)[]); } let def = (*def_map)[ref_id]; match def { @@ -241,7 +241,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefMethod(..) | def::DefPrimTy(_) => { self.sess.span_bug(span, format!("lookup_def_kind for unexpected item: {}", - def).as_slice()); + def)[]); }, } } @@ -262,8 +262,8 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { span_utils.span_for_last_ident(p.span), id, qualname, - path_to_string(p).as_slice(), - typ.as_slice()); + path_to_string(p)[], + typ[]); } self.collected_paths.clear(); } @@ -285,14 +285,14 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { match item.node { ast::ItemImpl(_, _, _, ref ty, _) => { let mut result = String::from_str("<"); - result.push_str(ty_to_string(&**ty).as_slice()); + result.push_str(ty_to_string(&**ty)[]); match ty::trait_of_item(&self.analysis.ty_cx, ast_util::local_def(method.id)) { Some(def_id) => { result.push_str(" as "); result.push_str( - ty::item_path_str(&self.analysis.ty_cx, def_id).as_slice()); + ty::item_path_str(&self.analysis.ty_cx, def_id)[]); }, None => {} } @@ -302,7 +302,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { _ => { self.sess.span_bug(method.span, format!("Container {} for method {} not an impl?", - impl_id.node, method.id).as_slice()); + impl_id.node, method.id)[]); }, } }, @@ -312,7 +312,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { impl_id.node, method.id, self.analysis.ty_cx.map.get(impl_id.node) - ).as_slice()); + )[]); }, }, None => match ty::trait_of_item(&self.analysis.ty_cx, @@ -328,20 +328,20 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { _ => { self.sess.span_bug(method.span, format!("Could not find container {} for method {}", - def_id.node, method.id).as_slice()); + def_id.node, method.id)[]); } } }, None => { self.sess.span_bug(method.span, format!("Could not find container for method {}", - method.id).as_slice()); + method.id)[]); }, }, }; qualname.push_str(get_ident(method.pe_ident()).get()); - let qualname = qualname.as_slice(); + let qualname = qualname[]; // record the decl for this def (if it has one) let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx, @@ -430,13 +430,13 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { Some(sub_span) => self.fmt.field_str(field.span, Some(sub_span), field.node.id, - name.get().as_slice(), - qualname.as_slice(), - typ.as_slice(), + name.get()[], + qualname[], + typ[], scope_id), None => self.sess.span_bug(field.span, format!("Could not find sub-span for field {}", - qualname).as_slice()), + qualname)[]), } }, _ => (), @@ -463,7 +463,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.fmt.typedef_str(full_span, Some(*param_ss), param.id, - name.as_slice(), + name[], ""); } self.visit_generics(generics); @@ -480,10 +480,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.fmt.fn_str(item.span, sub_span, item.id, - qualname.as_slice(), + qualname[], self.cur_scope); - self.process_formals(&decl.inputs, qualname.as_slice()); + self.process_formals(&decl.inputs, qualname[]); // walk arg and return types for arg in decl.inputs.iter() { @@ -497,7 +497,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { // walk the body self.nest(item.id, |v| v.visit_block(&*body)); - self.process_generic_params(ty_params, item.span, qualname.as_slice(), item.id); + self.process_generic_params(ty_params, item.span, qualname[], item.id); } fn process_static(&mut self, @@ -519,9 +519,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { sub_span, item.id, get_ident(item.ident).get(), - qualname.as_slice(), - value.as_slice(), - ty_to_string(&*typ).as_slice(), + qualname[], + value[], + ty_to_string(&*typ)[], self.cur_scope); // walk type and init value @@ -542,9 +542,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { sub_span, item.id, get_ident(item.ident).get(), - qualname.as_slice(), + qualname[], "", - ty_to_string(&*typ).as_slice(), + ty_to_string(&*typ)[], self.cur_scope); // walk type and init value @@ -568,17 +568,17 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { sub_span, item.id, ctor_id, - qualname.as_slice(), + qualname[], self.cur_scope, - val.as_slice()); + val[]); // fields for field in def.fields.iter() { - self.process_struct_field_def(field, qualname.as_slice(), item.id); + self.process_struct_field_def(field, qualname[], item.id); self.visit_ty(&*field.node.ty); } - self.process_generic_params(ty_params, item.span, qualname.as_slice(), item.id); + self.process_generic_params(ty_params, item.span, qualname[], item.id); } fn process_enum(&mut self, @@ -591,12 +591,12 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { Some(sub_span) => self.fmt.enum_str(item.span, Some(sub_span), item.id, - enum_name.as_slice(), + enum_name[], self.cur_scope, - val.as_slice()), + val[]), None => self.sess.span_bug(item.span, format!("Could not find subspan for enum {}", - enum_name).as_slice()), + enum_name)[]), } for variant in enum_definition.variants.iter() { let name = get_ident(variant.node.name); @@ -612,9 +612,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.span.span_for_first_ident(variant.span), variant.node.id, name, - qualname.as_slice(), - enum_name.as_slice(), - val.as_slice(), + qualname[], + enum_name[], + val[], item.id); for arg in args.iter() { self.visit_ty(&*arg.ty); @@ -630,20 +630,20 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.span.span_for_first_ident(variant.span), variant.node.id, ctor_id, - qualname.as_slice(), - enum_name.as_slice(), - val.as_slice(), + qualname[], + enum_name[], + val[], item.id); for field in struct_def.fields.iter() { - self.process_struct_field_def(field, enum_name.as_slice(), variant.node.id); + self.process_struct_field_def(field, enum_name[], variant.node.id); self.visit_ty(&*field.node.ty); } } } } - self.process_generic_params(ty_params, item.span, enum_name.as_slice(), item.id); + self.process_generic_params(ty_params, item.span, enum_name[], item.id); } fn process_impl(&mut self, @@ -703,9 +703,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.fmt.trait_str(item.span, sub_span, item.id, - qualname.as_slice(), + qualname[], self.cur_scope, - val.as_slice()); + val[]); // super-traits for super_bound in trait_refs.iter() { @@ -737,7 +737,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { } // walk generics and methods - self.process_generic_params(generics, item.span, qualname.as_slice(), item.id); + self.process_generic_params(generics, item.span, qualname[], item.id); for method in methods.iter() { self.visit_trait_item(method) } @@ -755,9 +755,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.fmt.mod_str(item.span, sub_span, item.id, - qualname.as_slice(), + qualname[], self.cur_scope, - filename.as_slice()); + filename[]); self.nest(item.id, |v| visit::walk_mod(v, m)); } @@ -773,7 +773,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { if !def_map.contains_key(&ex.id) { self.sess.span_bug(ex.span, format!("def_map has no key for {} in visit_expr", - ex.id).as_slice()); + ex.id)[]); } let def = &(*def_map)[ex.id]; let sub_span = self.span.span_for_last_ident(ex.span); @@ -840,7 +840,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.cur_scope), _ => self.sess.span_bug(ex.span, format!("Unexpected def kind while looking up path in '{}'", - self.span.snippet(ex.span)).as_slice()), + self.span.snippet(ex.span))[]), } // modules or types in the path prefix match *def { @@ -961,7 +961,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.cur_scope); // walk receiver and args - visit::walk_exprs(self, args.as_slice()); + visit::walk_exprs(self, args[]); } fn process_pat(&mut self, p:&ast::Pat) { @@ -978,7 +978,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { None => { self.sess.span_bug(p.span, format!("Could not find struct_def for `{}`", - self.span.snippet(p.span)).as_slice()); + self.span.snippet(p.span))[]); } }; for &Spanned { node: ref field, span } in fields.iter() { @@ -1062,11 +1062,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { self.fmt.typedef_str(item.span, sub_span, item.id, - qualname.as_slice(), - value.as_slice()); + qualname[], + value[]); self.visit_ty(&**ty); - self.process_generic_params(ty_params, item.span, qualname.as_slice(), item.id); + self.process_generic_params(ty_params, item.span, qualname[], item.id); }, ast::ItemMac(_) => (), _ => visit::walk_item(self, item), @@ -1123,12 +1123,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { None => { self.sess.span_bug(method_type.span, format!("Could not find trait for method {}", - method_type.id).as_slice()); + method_type.id)[]); }, }; qualname.push_str(get_ident(method_type.ident).get()); - let qualname = qualname.as_slice(); + let qualname = qualname[]; let sub_span = self.span.sub_span_after_keyword(method_type.span, keywords::Fn); self.fmt.method_decl_str(method_type.span, @@ -1243,7 +1243,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { id, cnum, name, - s.as_slice(), + s[], self.cur_scope); }, } @@ -1349,8 +1349,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } let mut id = String::from_str("$"); - id.push_str(ex.id.to_string().as_slice()); - self.process_formals(&decl.inputs, id.as_slice()); + id.push_str(ex.id.to_string()[]); + self.process_formals(&decl.inputs, id[]); // walk arg and return types for arg in decl.inputs.iter() { @@ -1393,7 +1393,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { // process collected paths for &(id, ref p, ref immut, ref_kind) in self.collected_paths.iter() { let value = if *immut { - self.span.snippet(p.span).into_string() + self.span.snippet(p.span).to_string() } else { "".to_string() }; @@ -1402,15 +1402,15 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { if !def_map.contains_key(&id) { self.sess.span_bug(p.span, format!("def_map has no key for {} in visit_arm", - id).as_slice()); + id)[]); } let def = &(*def_map)[id]; match *def { def::DefLocal(id) => self.fmt.variable_str(p.span, sub_span, id, - path_to_string(p).as_slice(), - value.as_slice(), + path_to_string(p)[], + value[], ""), def::DefVariant(_,id,_) => self.fmt.ref_str(ref_kind, p.span, @@ -1462,9 +1462,9 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { self.fmt.variable_str(p.span, sub_span, id, - path_to_string(p).as_slice(), - value.as_slice(), - typ.as_slice()); + path_to_string(p)[], + value[], + typ[]); } self.collected_paths.clear(); @@ -1482,7 +1482,7 @@ pub fn process_crate(sess: &Session, return; } - let cratename = match attr::find_crate_name(krate.attrs.as_slice()) { + let cratename = match attr::find_crate_name(krate.attrs[]) { Some(name) => name.get().to_string(), None => { info!("Could not find crate name, using 'unknown_crate'"); @@ -1503,7 +1503,7 @@ pub fn process_crate(sess: &Session, match fs::mkdir_recursive(&root_path, io::USER_RWX) { Err(e) => sess.err(format!("Could not create directory {}: {}", - root_path.display(), e).as_slice()), + root_path.display(), e)[]), _ => (), } @@ -1520,7 +1520,7 @@ pub fn process_crate(sess: &Session, Ok(f) => box f, Err(e) => { let disp = root_path.display(); - sess.fatal(format!("Could not open {}: {}", disp, e).as_slice()); + sess.fatal(format!("Could not open {}: {}", disp, e)[]); } }; root_path.pop(); @@ -1546,7 +1546,7 @@ pub fn process_crate(sess: &Session, cur_scope: 0 }; - visitor.dump_crate_info(cratename.as_slice(), krate); + visitor.dump_crate_info(cratename[], krate); visit::walk_crate(&mut visitor, krate); } diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs index 37d9e5d9940..08670864ade 100644 --- a/src/librustc_trans/save/recorder.rs +++ b/src/librustc_trans/save/recorder.rs @@ -41,7 +41,7 @@ impl Recorder { assert!(self.dump_spans); let result = format!("span,kind,{},{},text,\"{}\"\n", kind, su.extent_str(span), escape(su.snippet(span))); - self.record(result.as_slice()); + self.record(result[]); } } @@ -158,15 +158,15 @@ impl<'a> FmtStrs<'a> { if values.len() != fields.len() { self.span.sess.span_bug(span, format!( "Mismatch between length of fields for '{}', expected '{}', found '{}'", - kind, fields.len(), values.len()).as_slice()); + kind, fields.len(), values.len())[]); } let values = values.iter().map(|s| { // Never take more than 1020 chars if s.len() > 1020 { - s.slice_to(1020) + s[..1020] } else { - s.as_slice() + s[] } }); @@ -182,7 +182,7 @@ impl<'a> FmtStrs<'a> { } ))); Some(strs.fold(String::new(), |mut s, ss| { - s.push_str(ss.as_slice()); + s.push_str(ss[]); s })) } @@ -196,7 +196,7 @@ impl<'a> FmtStrs<'a> { if needs_span { self.span.sess.span_bug(span, format!( "Called record_without_span for '{}' which does requires a span", - label).as_slice()); + label)[]); } assert!(!dump_spans); @@ -210,9 +210,9 @@ impl<'a> FmtStrs<'a> { }; let mut result = String::from_str(label); - result.push_str(values_str.as_slice()); + result.push_str(values_str[]); result.push_str("\n"); - self.recorder.record(result.as_slice()); + self.recorder.record(result[]); } pub fn record_with_span(&mut self, @@ -235,7 +235,7 @@ impl<'a> FmtStrs<'a> { if !needs_span { self.span.sess.span_bug(span, format!("Called record_with_span for '{}' \ - which does not require a span", label).as_slice()); + which does not require a span", label)[]); } let values_str = match self.make_values_str(label, fields, values, span) { @@ -243,7 +243,7 @@ impl<'a> FmtStrs<'a> { None => return, }; let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str); - self.recorder.record(result.as_slice()); + self.recorder.record(result[]); } pub fn check_and_record(&mut self, @@ -273,7 +273,7 @@ impl<'a> FmtStrs<'a> { // variable def's node id let mut qualname = String::from_str(name); qualname.push_str("$"); - qualname.push_str(id.to_string().as_slice()); + qualname.push_str(id.to_string()[]); self.check_and_record(Variable, span, sub_span, diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index 49e8e0fd347..a92d3c06e64 100644 --- a/src/librustc_trans/save/span_utils.rs +++ b/src/librustc_trans/save/span_utils.rs @@ -218,7 +218,7 @@ impl<'a> SpanUtils<'a> { let loc = self.sess.codemap().lookup_char_pos(span.lo); self.sess.span_bug(span, format!("Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}", - self.snippet(span), loc.file.name, loc.line).as_slice()); + self.snippet(span), loc.file.name, loc.line)[]); } if result.is_none() && prev.tok.is_ident() && bracket_count == 0 { return self.make_sub_span(span, Some(prev.sp)); @@ -244,7 +244,7 @@ impl<'a> SpanUtils<'a> { let loc = self.sess.codemap().lookup_char_pos(span.lo); self.sess.span_bug(span, format!( "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}", - self.snippet(span), loc.file.name, loc.line).as_slice()); + self.snippet(span), loc.file.name, loc.line)[]); } return result } diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 2bcd723fc83..33fd14a441b 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -427,7 +427,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _indenter = indenter(); m.iter().filter_map(|br| { - e(br.pats.as_slice()).map(|pats| { + e(br.pats[]).map(|pats| { let this = br.pats[col]; let mut bound_ptrs = br.bound_ptrs.clone(); match this.node { @@ -548,7 +548,7 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( param_env: param_env, }; enter_match(bcx, dm, m, col, val, |pats| - check_match::specialize(&mcx, pats.as_slice(), &ctor, col, variant_size) + check_match::specialize(&mcx, pats[], &ctor, col, variant_size) ) } @@ -790,7 +790,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, let did = langcall(cx, None, format!("comparison of `{}`", - cx.ty_to_string(rhs_t)).as_slice(), + cx.ty_to_string(rhs_t))[], StrEqFnLangItem); callee::trans_lang_call(cx, did, &[lhs, rhs], None) } @@ -943,7 +943,7 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if has_nested_bindings(m, col) { let expanded = expand_nested_bindings(bcx, m, col, val); compile_submatch_continue(bcx, - expanded.as_slice(), + expanded[], vals, chk, col, @@ -1035,8 +1035,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, field_vals.len()) ); let mut vals = field_vals; - vals.push_all(vals_left.as_slice()); - compile_submatch(bcx, pats.as_slice(), vals.as_slice(), chk, has_genuine_default); + vals.push_all(vals_left[]); + compile_submatch(bcx, pats[], vals[], chk, has_genuine_default); return; } _ => () @@ -1189,10 +1189,10 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val); let mut opt_vals = unpacked; - opt_vals.push_all(vals_left.as_slice()); + opt_vals.push_all(vals_left[]); compile_submatch(opt_cx, - opt_ms.as_slice(), - opt_vals.as_slice(), + opt_ms[], + opt_vals[], branch_chk.as_ref().unwrap_or(chk), has_genuine_default); } @@ -1211,8 +1211,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } _ => { compile_submatch(else_cx, - defaults.as_slice(), - vals_left.as_slice(), + defaults[], + vals_left[], chk, has_genuine_default); } @@ -1333,7 +1333,7 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, "__llmatch"); trmode = TrByCopy(alloca_no_lifetime(bcx, llvariable_ty, - bcx.ident(ident).as_slice())); + bcx.ident(ident)[])); } ast::BindByValue(_) => { // in this case, the final type of the variable will be T, @@ -1341,13 +1341,13 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, // above llmatch = alloca_no_lifetime(bcx, llvariable_ty.ptr_to(), - bcx.ident(ident).as_slice()); + bcx.ident(ident)[]); trmode = TrByMove; } ast::BindByRef(_) => { llmatch = alloca_no_lifetime(bcx, llvariable_ty, - bcx.ident(ident).as_slice()); + bcx.ident(ident)[]); trmode = TrByRef; } }; @@ -1415,7 +1415,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, && arm.pats.last().unwrap().node == ast::PatWild(ast::PatWildSingle) }); - compile_submatch(bcx, matches.as_slice(), &[discr_datum.val], &chk, has_default); + compile_submatch(bcx, matches[], &[discr_datum.val], &chk, has_default); let mut arm_cxs = Vec::new(); for arm_data in arm_datas.iter() { @@ -1429,7 +1429,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, arm_cxs.push(bcx); } - bcx = scope_cx.fcx.join_blocks(match_id, arm_cxs.as_slice()); + bcx = scope_cx.fcx.join_blocks(match_id, arm_cxs[]); return bcx; } @@ -1581,7 +1581,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>, let var_ty = node_id_type(bcx, p_id); // Allocate memory on stack for the binding. - let llval = alloc_ty(bcx, var_ty, bcx.ident(*ident).as_slice()); + let llval = alloc_ty(bcx, var_ty, bcx.ident(*ident)[]); // Subtle: be sure that we *populate* the memory *before* // we schedule the cleanup. @@ -1619,7 +1619,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if bcx.sess().asm_comments() { add_comment(bcx, format!("bind_irrefutable_pat(pat={})", - pat.repr(bcx.tcx())).as_slice()); + pat.repr(bcx.tcx()))[]); } let _indenter = indenter(); diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index f7edb281b9e..9794611dd84 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -156,7 +156,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Repr<'tcx> { match t.sty { ty::ty_tup(ref elems) => { - Univariant(mk_struct(cx, elems.as_slice(), false, t), false) + Univariant(mk_struct(cx, elems[], false, t), false) } ty::ty_struct(def_id, ref substs) => { let fields = ty::lookup_struct_fields(cx.tcx(), def_id); @@ -167,16 +167,16 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag(); if dtor { ftys.push(ty::mk_bool()); } - Univariant(mk_struct(cx, ftys.as_slice(), packed, t), dtor) + Univariant(mk_struct(cx, ftys[], packed, t), dtor) } ty::ty_unboxed_closure(def_id, _, ref substs) => { let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs); let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); - Univariant(mk_struct(cx, upvar_types.as_slice(), false, t), false) + Univariant(mk_struct(cx, upvar_types[], false, t), false) } ty::ty_enum(def_id, ref substs) => { let cases = get_cases(cx.tcx(), def_id, substs); - let hint = *ty::lookup_repr_hints(cx.tcx(), def_id).as_slice().get(0) + let hint = *ty::lookup_repr_hints(cx.tcx(), def_id)[].get(0) .unwrap_or(&attr::ReprAny); let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag(); @@ -186,7 +186,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // (Typechecking will reject discriminant-sizing attrs.) assert_eq!(hint, attr::ReprAny); let ftys = if dtor { vec!(ty::mk_bool()) } else { vec!() }; - return Univariant(mk_struct(cx, ftys.as_slice(), false, t), + return Univariant(mk_struct(cx, ftys[], false, t), dtor); } @@ -209,7 +209,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, cx.sess().bug(format!("non-C-like enum {} with specified \ discriminants", ty::item_path_str(cx.tcx(), - def_id)).as_slice()); + def_id))[]); } if cases.len() == 1 { @@ -218,7 +218,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, assert_eq!(hint, attr::ReprAny); let mut ftys = cases[0].tys.clone(); if dtor { ftys.push(ty::mk_bool()); } - return Univariant(mk_struct(cx, ftys.as_slice(), false, t), + return Univariant(mk_struct(cx, ftys[], false, t), dtor); } @@ -227,7 +227,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let mut discr = 0; while discr < 2 { if cases[1 - discr].is_zerolen(cx, t) { - let st = mk_struct(cx, cases[discr].tys.as_slice(), + let st = mk_struct(cx, cases[discr].tys[], false, t); match cases[discr].find_ptr(cx) { Some(ThinPointer(_)) if st.fields.len() == 1 => { @@ -260,17 +260,17 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let fields : Vec<_> = cases.iter().map(|c| { let mut ftys = vec!(ty_of_inttype(ity)); - ftys.push_all(c.tys.as_slice()); + ftys.push_all(c.tys[]); if dtor { ftys.push(ty::mk_bool()); } - mk_struct(cx, ftys.as_slice(), false, t) + mk_struct(cx, ftys[], false, t) }).collect(); - ensure_enum_fits_in_address_space(cx, ity, fields.as_slice(), t); + ensure_enum_fits_in_address_space(cx, ity, fields[], t); General(ity, fields, dtor) } _ => cx.sess().bug(format!("adt::represent_type called on non-ADT type: {}", - ty_to_string(cx.tcx(), t)).as_slice()) + ty_to_string(cx.tcx(), t))[]) } } @@ -290,7 +290,7 @@ pub enum PointerField { impl<'tcx> Case<'tcx> { fn is_zerolen<'a>(&self, cx: &CrateContext<'a, 'tcx>, scapegoat: Ty<'tcx>) -> bool { - mk_struct(cx, self.tys.as_slice(), false, scapegoat).size == 0 + mk_struct(cx, self.tys[], false, scapegoat).size == 0 } fn find_ptr<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> Option { @@ -352,9 +352,9 @@ fn mk_struct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() }; - ensure_struct_fits_in_address_space(cx, lltys.as_slice(), packed, scapegoat); + ensure_struct_fits_in_address_space(cx, lltys[], packed, scapegoat); - let llty_rec = Type::struct_(cx, lltys.as_slice(), packed); + let llty_rec = Type::struct_(cx, lltys[], packed); Struct { size: machine::llsize_of_alloc(cx, llty_rec), align: machine::llalign_of_min(cx, llty_rec), @@ -403,7 +403,7 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp return ity; } attr::ReprExtern => { - attempts = match cx.sess().target.target.arch.as_slice() { + attempts = match cx.sess().target.target.arch[] { // WARNING: the ARM EABI has two variants; the one corresponding to `at_least_32` // appears to be used on Linux and NetBSD, but some systems may use the variant // corresponding to `choose_shortest`. However, we don't run on those yet...? @@ -530,7 +530,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, match *r { CEnum(..) | General(..) | RawNullablePointer { .. } => { } Univariant(ref st, _) | StructWrappedNullablePointer { nonnull: ref st, .. } => - llty.set_struct_body(struct_llfields(cx, st, false, false).as_slice(), + llty.set_struct_body(struct_llfields(cx, st, false, false)[], st.packed) } } @@ -546,7 +546,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Univariant(ref st, _) | StructWrappedNullablePointer { nonnull: ref st, .. } => { match name { None => { - Type::struct_(cx, struct_llfields(cx, st, sizing, dst).as_slice(), + Type::struct_(cx, struct_llfields(cx, st, sizing, dst)[], st.packed) } Some(name) => { assert_eq!(sizing, false); Type::named_struct(cx, name) } @@ -565,7 +565,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // of the size. // // FIXME #10604: this breaks when vector types are present. - let (size, align) = union_size_and_align(sts.as_slice()); + let (size, align) = union_size_and_align(sts[]); let align_s = align as u64; let discr_ty = ll_inttype(cx, ity); let discr_size = machine::llsize_of_alloc(cx, discr_ty); @@ -586,10 +586,10 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Type::array(&discr_ty, align_s / discr_size - 1), pad_ty); match name { - None => Type::struct_(cx, fields.as_slice(), false), + None => Type::struct_(cx, fields[], false), Some(name) => { let mut llty = Type::named_struct(cx, name); - llty.set_struct_body(fields.as_slice(), false); + llty.set_struct_body(fields[], false); llty } } @@ -847,7 +847,7 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v let val = if needs_cast { let ccx = bcx.ccx(); let fields = st.fields.iter().map(|&ty| type_of::type_of(ccx, ty)).collect::>(); - let real_ty = Type::struct_(ccx, fields.as_slice(), st.packed); + let real_ty = Type::struct_(ccx, fields[], st.packed); PointerCast(bcx, val, real_ty.ptr_to()) } else { val @@ -879,14 +879,14 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, for (discr, case) in cases.iter().enumerate() { let mut variant_cx = fcx.new_temp_block( - format!("enum-variant-iter-{}", discr.to_string()).as_slice() + format!("enum-variant-iter-{}", discr.to_string())[] ); let rhs_val = C_integral(ll_inttype(ccx, ity), discr as u64, true); AddCase(llswitch, rhs_val, variant_cx.llbb); let fields = case.fields.iter().map(|&ty| type_of::type_of(bcx.ccx(), ty)).collect::>(); - let real_ty = Type::struct_(ccx, fields.as_slice(), case.packed); + let real_ty = Type::struct_(ccx, fields[], case.packed); let variant_value = PointerCast(variant_cx, value, real_ty.ptr_to()); variant_cx = f(variant_cx, case, variant_value); @@ -961,14 +961,14 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr let lldiscr = C_integral(ll_inttype(ccx, ity), discr as u64, true); let mut f = vec![lldiscr]; f.push_all(vals); - let mut contents = build_const_struct(ccx, case, f.as_slice()); + let mut contents = build_const_struct(ccx, case, f[]); contents.push_all(&[padding(ccx, max_sz - case.size)]); - C_struct(ccx, contents.as_slice(), false) + C_struct(ccx, contents[], false) } Univariant(ref st, _dro) => { assert!(discr == 0); let contents = build_const_struct(ccx, st, vals); - C_struct(ccx, contents.as_slice(), st.packed) + C_struct(ccx, contents[], st.packed) } RawNullablePointer { nndiscr, nnty, .. } => { if discr == nndiscr { @@ -982,7 +982,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr if discr == nndiscr { C_struct(ccx, build_const_struct(ccx, nonnull, - vals).as_slice(), + vals)[], false) } else { let vals = nonnull.fields.iter().map(|&ty| { @@ -992,7 +992,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr }).collect::>(); C_struct(ccx, build_const_struct(ccx, nonnull, - vals.as_slice()).as_slice(), + vals[])[], false) } } diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index e3afe22897e..b8bee100082 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -72,7 +72,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) callee::DontAutorefArg) }) }).collect::>(); - inputs.push_all(ext_inputs.as_slice()); + inputs.push_all(ext_inputs[]); // no failure occurred preparing operands, no need to cleanup fcx.pop_custom_cleanup_scope(temp_scope); @@ -92,18 +92,18 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) if !clobbers.is_empty() { clobbers.push(','); } - clobbers.push_str(more_clobbers.as_slice()); + clobbers.push_str(more_clobbers[]); } // Add the clobbers to our constraints list if clobbers.len() != 0 && constraints.len() != 0 { constraints.push(','); - constraints.push_str(clobbers.as_slice()); + constraints.push_str(clobbers[]); } else { - constraints.push_str(clobbers.as_slice()); + constraints.push_str(clobbers[]); } - debug!("Asm Constraints: {}", constraints.as_slice()); + debug!("Asm Constraints: {}", constraints[]); let num_outputs = outputs.len(); @@ -113,7 +113,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) } else if num_outputs == 1 { output_types[0] } else { - Type::struct_(bcx.ccx(), output_types.as_slice(), false) + Type::struct_(bcx.ccx(), output_types[], false) }; let dialect = match ia.dialect { @@ -126,7 +126,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) InlineAsmCall(bcx, a, c, - inputs.as_slice(), + inputs[], output_type, ia.volatile, ia.alignstack, diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index ca1e0d7de72..a18d403bd95 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -249,7 +249,7 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>, let f = decl_rust_fn(ccx, fn_ty, name); csearch::get_item_attrs(&ccx.sess().cstore, did, |attrs| { - set_llvm_fn_attrs(ccx, attrs.as_slice(), f) + set_llvm_fn_attrs(ccx, attrs[], f) }); ccx.externs().borrow_mut().insert(name.to_string(), f); @@ -302,7 +302,7 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, _ => panic!("expected closure or fn") }; - let llfty = type_of_rust_fn(ccx, env, inputs.as_slice(), output, abi); + let llfty = type_of_rust_fn(ccx, env, inputs[], output, abi); debug!("decl_rust_fn(input count={},type={})", inputs.len(), ccx.tn().type_to_string(llfty)); @@ -369,7 +369,7 @@ fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Err(s) => { bcx.sess().fatal(format!("allocation of `{}` {}", bcx.ty_to_string(info_ty), - s).as_slice()); + s)[]); } } } @@ -510,7 +510,7 @@ pub fn unset_split_stack(f: ValueRef) { // silently mangles such symbols, breaking our linkage model. pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: String) { if ccx.all_llvm_symbols().borrow().contains(&sym) { - ccx.sess().bug(format!("duplicate LLVM symbol: {}", sym).as_slice()); + ccx.sess().bug(format!("duplicate LLVM symbol: {}", sym)[]); } ccx.all_llvm_symbols().borrow_mut().insert(sym); } @@ -546,7 +546,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::mk_nil(ccx.tcx())); get_extern_fn(ccx, &mut *ccx.externs().borrow_mut(), - name.as_slice(), + name[], llvm::CCallConv, llty, dtor_ty) @@ -796,8 +796,8 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, let variant_cx = fcx.new_temp_block( format!("enum-iter-variant-{}", - variant.disr_val.to_string().as_slice()) - .as_slice()); + variant.disr_val.to_string()[]) + []); match adt::trans_case(cx, &*repr, variant.disr_val) { _match::SingleResult(r) => { AddCase(llswitch, r.val, variant_cx.llbb) @@ -822,7 +822,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, } _ => { cx.sess().unimpl(format!("type in iter_structural_ty: {}", - ty_to_string(cx.tcx(), t)).as_slice()) + ty_to_string(cx.tcx(), t))[]) } } return cx; @@ -904,7 +904,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( } _ => { cx.sess().bug(format!("fail-if-zero on unexpected type: {}", - ty_to_string(cx.tcx(), rhs_t)).as_slice()); + ty_to_string(cx.tcx(), rhs_t))[]); } }; let bcx = with_cond(cx, is_zero, |bcx| { @@ -958,19 +958,19 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::ty_bare_fn(ref fn_ty) => { match ccx.sess().target.target.adjust_abi(fn_ty.abi) { Rust | RustCall => { - get_extern_rust_fn(ccx, t, name.as_slice(), did) + get_extern_rust_fn(ccx, t, name[], did) } RustIntrinsic => { ccx.sess().bug("unexpected intrinsic in trans_external_path") } _ => { foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, - name.as_slice()) + name[]) } } } ty::ty_closure(_) => { - get_extern_rust_fn(ccx, t, name.as_slice(), did) + get_extern_rust_fn(ccx, t, name[], did) } _ => { get_extern_const(ccx, did, t) @@ -1024,7 +1024,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llresult = Invoke(bcx, llfn, - llargs.as_slice(), + llargs[], normal_bcx.llbb, landing_pad, Some(attributes)); @@ -1040,7 +1040,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, None => debuginfo::clear_source_location(bcx.fcx) }; - let llresult = Call(bcx, llfn, llargs.as_slice(), Some(attributes)); + let llresult = Call(bcx, llfn, llargs[], Some(attributes)); return (llresult, bcx); } } @@ -1157,7 +1157,7 @@ pub fn call_lifetime_end(cx: Block, ptr: ValueRef) { pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { let _icx = push_ctxt("call_memcpy"); let ccx = cx.ccx(); - let key = match ccx.sess().target.target.target_word_size.as_slice() { + let key = match ccx.sess().target.target.target_word_size[] { "32" => "llvm.memcpy.p0i8.p0i8.i32", "64" => "llvm.memcpy.p0i8.p0i8.i64", tws => panic!("Unsupported target word size for memcpy: {}", tws), @@ -1204,7 +1204,7 @@ fn memzero<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>) { let llty = type_of::type_of(ccx, ty); - let intrinsic_key = match ccx.sess().target.target.target_word_size.as_slice() { + let intrinsic_key = match ccx.sess().target.target.target_word_size[] { "32" => "llvm.memset.p0i8.i32", "64" => "llvm.memset.p0i8.i64", tws => panic!("Unsupported target word size for memset: {}", tws), @@ -1691,7 +1691,7 @@ fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>( "argtuple", arg_scope_id)); let untupled_arg_types = match monomorphized_arg_types[0].sty { - ty::ty_tup(ref types) => types.as_slice(), + ty::ty_tup(ref types) => types[], _ => { bcx.tcx().sess.span_bug(args[0].pat.span, "first arg to `rust-call` ABI function \ @@ -1879,12 +1879,12 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let arg_datums = if abi != RustCall { create_datums_for_fn_args(&fcx, - monomorphized_arg_types.as_slice()) + monomorphized_arg_types[]) } else { create_datums_for_fn_args_under_call_abi( bcx, arg_scope, - monomorphized_arg_types.as_slice()) + monomorphized_arg_types[]) }; bcx = match closure_env.kind { @@ -1892,16 +1892,16 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, copy_args_to_allocas(&fcx, arg_scope, bcx, - decl.inputs.as_slice(), + decl.inputs[], arg_datums) } closure::UnboxedClosure(..) => { copy_unboxed_closure_args_to_allocas( bcx, arg_scope, - decl.inputs.as_slice(), + decl.inputs[], arg_datums, - monomorphized_arg_types.as_slice()) + monomorphized_arg_types[]) } }; @@ -2018,7 +2018,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => ccx.sess().bug( format!("trans_enum_variant_constructor: \ unexpected ctor return type {}", - ctor_ty.repr(tcx)).as_slice()) + ctor_ty.repr(tcx))[]) }; // Get location to store the result. If the user does not care about @@ -2041,7 +2041,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, bcx = expr::trans_adt(bcx, result_ty, disr, - fields.as_slice(), + fields[], None, expr::SaveIn(llresult), call_info); @@ -2090,7 +2090,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx _ => ccx.sess().bug( format!("trans_enum_variant_or_tuple_like_struct: \ unexpected ctor return type {}", - ty_to_string(ccx.tcx(), ctor_ty)).as_slice()) + ty_to_string(ccx.tcx(), ctor_ty))[]) }; let arena = TypedArena::new(); @@ -2102,7 +2102,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx let arg_tys = ty::ty_fn_args(ctor_ty); - let arg_datums = create_datums_for_fn_args(&fcx, arg_tys.as_slice()); + let arg_datums = create_datums_for_fn_args(&fcx, arg_tys[]); if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) { let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot"); @@ -2166,7 +2166,7 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, lvlsrc, Some(sp), format!("enum variant is more than three times larger \ ({} bytes) than the next largest (ignoring padding)", - largest).as_slice()); + largest)[]); ccx.sess().span_note(enum_def.variants[largest_index].span, "this variant is the largest"); @@ -2284,7 +2284,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { match item.node { ast::ItemFn(ref decl, _fn_style, abi, ref generics, ref body) => { if !generics.is_type_parameterized() { - let trans_everywhere = attr::requests_inline(item.attrs.as_slice()); + let trans_everywhere = attr::requests_inline(item.attrs[]); // Ignore `trans_everywhere` for cross-crate inlined items // (`from_external`). `trans_item` will be called once for each // compilation unit that references the item, so it will still get @@ -2295,7 +2295,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { foreign::trans_rust_fn_with_foreign_abi(ccx, &**decl, &**body, - item.attrs.as_slice(), + item.attrs[], llfn, &Substs::trans_empty(), item.id, @@ -2307,7 +2307,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { llfn, &Substs::trans_empty(), item.id, - item.attrs.as_slice()); + item.attrs[]); } update_linkage(ccx, llfn, @@ -2324,7 +2324,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { ast::ItemImpl(_, ref generics, _, _, ref impl_items) => { meth::trans_impl(ccx, item.ident, - impl_items.as_slice(), + impl_items[], generics, item.id); } @@ -2350,7 +2350,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { // Do static_assert checking. It can't really be done much earlier // because we need to get the value of the bool out of LLVM - if attr::contains_name(item.attrs.as_slice(), "static_assert") { + if attr::contains_name(item.attrs[], "static_assert") { if m == ast::MutMutable { ccx.sess().span_fatal(expr.span, "cannot have static_assert on a mutable \ @@ -2427,7 +2427,7 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, _ => panic!("expected bare rust fn") }; - let llfn = decl_rust_fn(ccx, node_type, sym.as_slice()); + let llfn = decl_rust_fn(ccx, node_type, sym[]); finish_register_fn(ccx, sp, sym, node_id, llfn); llfn } @@ -2472,7 +2472,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< match fn_sig.0.inputs[1].sty { ty::ty_tup(ref t_in) => { - inputs.push_all(t_in.as_slice()); + inputs.push_all(t_in[]); inputs } _ => ccx.sess().bug("expected tuple'd inputs") @@ -2607,7 +2607,7 @@ pub fn register_fn_llvmty(ccx: &CrateContext, llfty: Type) -> ValueRef { debug!("register_fn_llvmty id={} sym={}", node_id, sym); - let llfn = decl_fn(ccx, sym.as_slice(), cc, llfty, ty::FnConverging(ty::mk_nil(ccx.tcx()))); + let llfn = decl_fn(ccx, sym[], cc, llfty, ty::FnConverging(ty::mk_nil(ccx.tcx()))); finish_register_fn(ccx, sp, sym, node_id, llfn); llfn } @@ -2659,7 +2659,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext, let (start_fn, args) = if use_start_lang_item { let start_def_id = match ccx.tcx().lang_items.require(StartFnLangItem) { Ok(id) => id, - Err(s) => { ccx.sess().fatal(s.as_slice()); } + Err(s) => { ccx.sess().fatal(s[]); } }; let start_fn = if start_def_id.krate == ast::LOCAL_CRATE { get_item_val(ccx, start_def_id.node) @@ -2750,7 +2750,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let val = match item { ast_map::NodeItem(i) => { let ty = ty::node_id_to_type(ccx.tcx(), i.id); - let sym = || exported_name(ccx, id, ty, i.attrs.as_slice()); + let sym = || exported_name(ccx, id, ty, i.attrs[]); let v = match i.node { ast::ItemStatic(_, _, ref expr) => { @@ -2773,16 +2773,16 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { } else { llvm::LLVMTypeOf(v) }; - if contains_null(sym.as_slice()) { + if contains_null(sym[]) { ccx.sess().fatal( format!("Illegal null byte in export_name \ - value: `{}`", sym).as_slice()); + value: `{}`", sym)[]); } let g = sym.with_c_str(|buf| { llvm::LLVMAddGlobal(ccx.llmod(), llty, buf) }); - if attr::contains_name(i.attrs.as_slice(), + if attr::contains_name(i.attrs[], "thread_local") { llvm::set_thread_local(g, true); } @@ -2807,19 +2807,19 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { sym, i.id) }; - set_llvm_fn_attrs(ccx, i.attrs.as_slice(), llfn); + set_llvm_fn_attrs(ccx, i.attrs[], llfn); llfn } _ => panic!("get_item_val: weird result in table") }; - match attr::first_attr_value_str_by_name(i.attrs.as_slice(), + match attr::first_attr_value_str_by_name(i.attrs[], "link_section") { Some(sect) => { if contains_null(sect.get()) { ccx.sess().fatal(format!("Illegal null byte in link_section value: `{}`", - sect.get()).as_slice()); + sect.get())[]); } unsafe { sect.get().with_c_str(|buf| { @@ -2863,7 +2863,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let abi = ccx.tcx().map.get_foreign_abi(id); let ty = ty::node_id_to_type(ccx.tcx(), ni.id); let name = foreign::link_name(&*ni); - foreign::register_foreign_item_fn(ccx, abi, ty, name.get().as_slice()) + foreign::register_foreign_item_fn(ccx, abi, ty, name.get()[]) } ast::ForeignItemStatic(..) => { foreign::register_static(ccx, &*ni) @@ -2886,7 +2886,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let sym = exported_name(ccx, id, ty, - enm.attrs.as_slice()); + enm.attrs[]); llfn = match enm.node { ast::ItemEnum(_, _) => { @@ -2914,7 +2914,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { id, ty, struct_item.attrs - .as_slice()); + []); let llfn = register_fn(ccx, struct_item.span, sym, ctor_id, ty); set_inline_hint(llfn); @@ -2923,7 +2923,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { ref variant => { ccx.sess().bug(format!("get_item_val(): unexpected variant: {}", - variant).as_slice()) + variant)[]) } }; @@ -2944,10 +2944,10 @@ fn register_method(ccx: &CrateContext, id: ast::NodeId, m: &ast::Method) -> ValueRef { let mty = ty::node_id_to_type(ccx.tcx(), id); - let sym = exported_name(ccx, id, mty, m.attrs.as_slice()); + let sym = exported_name(ccx, id, mty, m.attrs[]); let llfn = register_fn(ccx, m.span, sym, id, mty); - set_llvm_fn_attrs(ccx, m.attrs.as_slice(), llfn); + set_llvm_fn_attrs(ccx, m.attrs[], llfn); llfn } @@ -2986,7 +2986,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { Some(compressed) => compressed, None => cx.sess().fatal("failed to compress metadata"), }.as_slice()); - let llmeta = C_bytes_in_context(cx.metadata_llcx(), compressed.as_slice()); + let llmeta = C_bytes_in_context(cx.metadata_llcx(), compressed[]); let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false); let name = format!("rust_metadata_{}_{}", cx.link_meta().crate_name, @@ -3114,7 +3114,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) let link_meta = link::build_link_meta(&tcx.sess, krate, name); let codegen_units = tcx.sess.opts.cg.codegen_units; - let shared_ccx = SharedCrateContext::new(link_meta.crate_name.as_slice(), + let shared_ccx = SharedCrateContext::new(link_meta.crate_name[], codegen_units, tcx, export_map, @@ -3216,7 +3216,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) llmod: shared_ccx.metadata_llmod(), }; let formats = shared_ccx.tcx().dependency_formats.borrow().clone(); - let no_builtins = attr::contains_name(krate.attrs.as_slice(), "no_builtins"); + let no_builtins = attr::contains_name(krate.attrs[], "no_builtins"); let translation = CrateTranslation { modules: modules, diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs index cf940b13846..1b9c9d221b9 100644 --- a/src/librustc_trans/trans/builder.rs +++ b/src/librustc_trans/trans/builder.rs @@ -555,7 +555,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::>(); self.count_insn("gepi"); - self.inbounds_gep(base, v.as_slice()) + self.inbounds_gep(base, v[]) } } @@ -763,8 +763,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let s = format!("{} ({})", text, self.ccx.sess().codemap().span_to_string(sp)); - debug!("{}", s.as_slice()); - self.add_comment(s.as_slice()); + debug!("{}", s[]); + self.add_comment(s[]); } } @@ -801,7 +801,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }).collect::>(); debug!("Asm Output Type: {}", self.ccx.tn().type_to_string(output)); - let fty = Type::func(argtys.as_slice(), &output); + let fty = Type::func(argtys[], &output); unsafe { let v = llvm::LLVMInlineAsm( fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint); diff --git a/src/librustc_trans/trans/cabi.rs b/src/librustc_trans/trans/cabi.rs index ad2a6db1222..9ea158fbe21 100644 --- a/src/librustc_trans/trans/cabi.rs +++ b/src/librustc_trans/trans/cabi.rs @@ -107,7 +107,7 @@ pub fn compute_abi_info(ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { - match ccx.sess().target.target.arch.as_slice() { + match ccx.sess().target.target.arch[] { "x86" => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def), "x86_64" => if ccx.sess().target.target.options.is_like_windows { cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def) @@ -117,6 +117,6 @@ pub fn compute_abi_info(ccx: &CrateContext, "arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def), "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), a => ccx.sess().fatal((format!("unrecognized arch \"{}\" in target specification", a)) - .as_slice()), + []), } } diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 1a753901f7e..ec3a81afaa0 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -122,7 +122,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) expr.span, format!("type of callee is neither bare-fn nor closure: \ {}", - bcx.ty_to_string(datum.ty)).as_slice()); + bcx.ty_to_string(datum.ty))[]); } } } @@ -208,7 +208,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) bcx.tcx().sess.span_bug( ref_expr.span, format!("cannot translate def {} \ - to a callable thing!", def).as_slice()); + to a callable thing!", def)[]); } } } @@ -288,7 +288,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( _ => { tcx.sess.bug(format!("trans_fn_pointer_shim invoked on invalid type: {}", - bare_fn_ty.repr(tcx)).as_slice()); + bare_fn_ty.repr(tcx))[]); } }; let tuple_input_ty = ty::mk_tup(tcx, input_tys.to_vec()); @@ -310,7 +310,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( let llfn = decl_internal_rust_fn(ccx, tuple_fn_ty, - function_name.as_slice()); + function_name[]); // let block_arena = TypedArena::new(); @@ -345,7 +345,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( None, bare_fn_ty, |bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) }, - ArgVals(llargs.as_slice()), + ArgVals(llargs[]), dest).bcx; finish_fn(&fcx, bcx, output_ty); @@ -813,7 +813,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, bcx = foreign::trans_native_call(bcx, callee_ty, llfn, opt_llretslot.unwrap(), - llargs.as_slice(), arg_tys); + llargs[], arg_tys); } fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_cleanup_scope); diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index fb2c432ef5c..c1bb21c496a 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -404,7 +404,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.ccx.sess().bug( format!("no cleanup scope {} found", - self.ccx.tcx().map.node_to_string(cleanup_scope)).as_slice()); + self.ccx.tcx().map.node_to_string(cleanup_scope))[]); } /// Schedules a cleanup to occur in the top-most scope, which must be a temporary scope. @@ -586,7 +586,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx LoopExit(id, _) => { self.ccx.sess().bug(format!( "cannot exit from scope {}, \ - not in scope", id).as_slice()); + not in scope", id)[]); } } } @@ -655,7 +655,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx let name = scope.block_name("clean"); debug!("generating cleanups for {}", name); let bcx_in = self.new_block(label.is_unwind(), - name.as_slice(), + name[], None); let mut bcx_out = bcx_in; for cleanup in scope.cleanups.iter().rev() { @@ -702,7 +702,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx Some(llbb) => { return llbb; } None => { let name = last_scope.block_name("unwind"); - pad_bcx = self.new_block(true, name.as_slice(), None); + pad_bcx = self.new_block(true, name[], None); last_scope.cached_landing_pad = Some(pad_bcx.llbb); } } @@ -1020,7 +1020,7 @@ pub fn temporary_scope(tcx: &ty::ctxt, } None => { tcx.sess.bug(format!("no temporary scope available for expr {}", - id).as_slice()) + id)[]) } } } diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index d5d954f5a90..8e56ef3c6f3 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -177,7 +177,7 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let tcx = ccx.tcx(); // compute the type of the closure - let cdata_ty = mk_closure_tys(tcx, bound_values.as_slice()); + let cdata_ty = mk_closure_tys(tcx, bound_values[]); // cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a // tuple. This could be a ptr in uniq or a box or on stack, @@ -206,7 +206,7 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if ccx.sess().asm_comments() { add_comment(bcx, format!("Copy {} into closure", - bv.to_string(ccx)).as_slice()); + bv.to_string(ccx))[]); } let bound_data = GEPi(bcx, llbox, &[0u, abi::BOX_FIELD_BODY, i]); @@ -444,7 +444,7 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let s = tcx.map.with_path(id, |path| { mangle_internal_name_by_path_and_seq(path, "closure") }); - let llfn = decl_internal_rust_fn(ccx, fty, s.as_slice()); + let llfn = decl_internal_rust_fn(ccx, fty, s[]); // set an inline hint for all closures set_inline_hint(llfn); @@ -468,7 +468,7 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, &[], ty::ty_fn_ret(fty), ty::ty_fn_abi(fty), - ClosureEnv::new(freevars.as_slice(), + ClosureEnv::new(freevars[], BoxedClosure(cdata_ty, store))); fill_fn_pair(bcx, dest_addr, llfn, llbox); bcx @@ -514,7 +514,7 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, mangle_internal_name_by_path_and_seq(path, "unboxed_closure") }); - let llfn = decl_internal_rust_fn(ccx, function_type, symbol.as_slice()); + let llfn = decl_internal_rust_fn(ccx, function_type, symbol[]); // set an inline hint for all closures set_inline_hint(llfn); @@ -563,7 +563,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( &[], ty::ty_fn_ret(function_type), ty::ty_fn_abi(function_type), - ClosureEnv::new(freevars.as_slice(), + ClosureEnv::new(freevars[], UnboxedClosure(freevar_mode))); // Don't hoist this to the top of the function. It's perfectly legitimate @@ -614,7 +614,7 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.sess().bug(format!("get_wrapper_for_bare_fn: \ expected a statically resolved fn, got \ {}", - def).as_slice()); + def)[]); } }; @@ -632,7 +632,7 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, _ => { ccx.sess().bug(format!("get_wrapper_for_bare_fn: \ expected a closure ty, got {}", - closure_ty.repr(tcx)).as_slice()); + closure_ty.repr(tcx))[]); } }; @@ -640,9 +640,9 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, mangle_internal_name_by_path_and_seq(path, "as_closure") }); let llfn = if is_local { - decl_internal_rust_fn(ccx, closure_ty, name.as_slice()) + decl_internal_rust_fn(ccx, closure_ty, name[]) } else { - decl_rust_fn(ccx, closure_ty, name.as_slice()) + decl_rust_fn(ccx, closure_ty, name[]) }; ccx.closure_bare_wrapper_cache().borrow_mut().insert(fn_ptr, llfn); @@ -663,7 +663,7 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let args = create_datums_for_fn_args(&fcx, ty::ty_fn_args(closure_ty) - .as_slice()); + []); let mut llargs = Vec::new(); match fcx.llretslotptr.get() { Some(llretptr) => { diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 61f27bcfa7a..9a3e39ff10b 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -117,7 +117,7 @@ pub fn gensym_name(name: &str) -> PathElem { let num = token::gensym(name).uint(); // use one colon which will get translated to a period by the mangler, and // we're guaranteed that `num` is globally unique for this crate. - PathName(token::gensym(format!("{}:{}", name, num).as_slice())) + PathName(token::gensym(format!("{}:{}", name, num)[])) } #[deriving(Copy)] @@ -436,7 +436,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { Some(v) => v.clone(), None => { self.tcx().sess.bug(format!( - "no def associated with node id {}", nid).as_slice()); + "no def associated with node id {}", nid)[]); } } } @@ -817,7 +817,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, span, format!("Encountered error `{}` selecting `{}` during trans", e.repr(tcx), - trait_ref.repr(tcx)).as_slice()) + trait_ref.repr(tcx))[]) } }; @@ -844,7 +844,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, span, format!("Encountered errors `{}` fulfilling `{}` during trans", errors.repr(tcx), - trait_ref.repr(tcx)).as_slice()); + trait_ref.repr(tcx))[]); } } } @@ -892,7 +892,7 @@ pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, format!("type parameters for node {} include inference types: \ {}", node, - substs.repr(bcx.tcx())).as_slice()); + substs.repr(bcx.tcx()))[]); } let substs = substs.erase_regions(); @@ -909,8 +909,8 @@ pub fn langcall(bcx: Block, Err(s) => { let msg = format!("{} {}", msg, s); match span { - Some(span) => bcx.tcx().sess.span_fatal(span, msg.as_slice()), - None => bcx.tcx().sess.fatal(msg.as_slice()), + Some(span) => bcx.tcx().sess.span_fatal(span, msg[]), + None => bcx.tcx().sess.fatal(msg[]), } } } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index e4f0543b5e7..4f7d0f8fe75 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -54,7 +54,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit) _ => cx.sess().span_bug(lit.span, format!("integer literal has type {} (expected int \ or uint)", - ty_to_string(cx.tcx(), lit_int_ty)).as_slice()) + ty_to_string(cx.tcx(), lit_int_ty))[]) } } ast::LitFloat(ref fs, t) => { @@ -74,7 +74,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit) } ast::LitBool(b) => C_bool(cx, b), ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()), - ast::LitBinary(ref data) => C_binary_slice(cx, data.as_slice()), + ast::LitBinary(ref data) => C_binary_slice(cx, data[]), } } @@ -95,9 +95,9 @@ fn const_vec(cx: &CrateContext, e: &ast::Expr, .collect::>(); // If the vector contains enums, an LLVM array won't work. let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) { - C_struct(cx, vs.as_slice(), false) + C_struct(cx, vs[], false) } else { - C_array(llunitty, vs.as_slice()) + C_array(llunitty, vs[]) }; (v, llunitty) } @@ -152,13 +152,13 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, v: ValueRef, } _ => { cx.sess().bug(format!("unexpected dereferenceable type {}", - ty_to_string(cx.tcx(), t)).as_slice()) + ty_to_string(cx.tcx(), t))[]) } } } None => { cx.sess().bug(format!("cannot dereference const of type {}", - ty_to_string(cx.tcx(), t)).as_slice()) + ty_to_string(cx.tcx(), t))[]) } } } @@ -203,7 +203,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr) cx.sess() .span_bug(e.span, format!("unexpected static function: {}", - store).as_slice()) + store)[]) } ty::AdjustDerefRef(ref adj) => { let mut ty = ety; @@ -264,7 +264,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr) } _ => cx.sess().span_bug(e.span, format!("unimplemented type in const unsize: {}", - ty_to_string(cx.tcx(), ty)).as_slice()) + ty_to_string(cx.tcx(), ty))[]) } } _ => { @@ -272,7 +272,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr) .span_bug(e.span, format!("unimplemented const \ autoref {}", - autoref).as_slice()) + autoref)[]) } } } @@ -293,7 +293,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr) } cx.sess().bug(format!("const {} of type {} has size {} instead of {}", e.repr(cx.tcx()), ty_to_string(cx.tcx(), ety), - csize, tsize).as_slice()); + csize, tsize)[]); } (llconst, ety_adjusted) } @@ -443,7 +443,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { _ => cx.sess().span_bug(base.span, format!("index-expr base must be a vector \ or string type, found {}", - ty_to_string(cx.tcx(), bt)).as_slice()) + ty_to_string(cx.tcx(), bt))[]) }, ty::ty_rptr(_, mt) => match mt.ty.sty { ty::ty_vec(_, Some(u)) => { @@ -452,12 +452,12 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { _ => cx.sess().span_bug(base.span, format!("index-expr base must be a vector \ or string type, found {}", - ty_to_string(cx.tcx(), bt)).as_slice()) + ty_to_string(cx.tcx(), bt))[]) }, _ => cx.sess().span_bug(base.span, format!("index-expr base must be a vector \ or string type, found {}", - ty_to_string(cx.tcx(), bt)).as_slice()) + ty_to_string(cx.tcx(), bt))[]) }; let len = llvm::LLVMConstIntGetZExtValue(len) as u64; @@ -558,8 +558,8 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { ast::ExprTup(ref es) => { let ety = ty::expr_ty(cx.tcx(), e); let repr = adt::represent_type(cx, ety); - let vals = map_list(es.as_slice()); - adt::trans_const(cx, &*repr, 0, vals.as_slice()) + let vals = map_list(es[]); + adt::trans_const(cx, &*repr, 0, vals[]) } ast::ExprStruct(_, ref fs, ref base_opt) => { let ety = ty::expr_ty(cx.tcx(), e); @@ -590,7 +590,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { } } }).collect::>(); - adt::trans_const(cx, &*repr, discr, cs.as_slice()) + adt::trans_const(cx, &*repr, discr, cs[]) }) } ast::ExprVec(ref es) => { @@ -607,9 +607,9 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { }; let vs = Vec::from_elem(n, const_expr(cx, &**elem).0); if vs.iter().any(|vi| val_ty(*vi) != llunitty) { - C_struct(cx, vs.as_slice(), false) + C_struct(cx, vs[], false) } else { - C_array(llunitty, vs.as_slice()) + C_array(llunitty, vs[]) } } ast::ExprPath(ref pth) => { @@ -655,8 +655,8 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { Some(def::DefStruct(_)) => { let ety = ty::expr_ty(cx.tcx(), e); let repr = adt::represent_type(cx, ety); - let arg_vals = map_list(args.as_slice()); - adt::trans_const(cx, &*repr, 0, arg_vals.as_slice()) + let arg_vals = map_list(args[]); + adt::trans_const(cx, &*repr, 0, arg_vals[]) } Some(def::DefVariant(enum_did, variant_did, _)) => { let ety = ty::expr_ty(cx.tcx(), e); @@ -664,11 +664,11 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef { let vinfo = ty::enum_variant_with_id(cx.tcx(), enum_did, variant_did); - let arg_vals = map_list(args.as_slice()); + let arg_vals = map_list(args[]); adt::trans_const(cx, &*repr, vinfo.disr_val, - arg_vals.as_slice()) + arg_vals[]) } _ => cx.sess().span_bug(e.span, "expected a struct or variant def") } diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 7b962a93990..2c71dd831fb 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -284,7 +284,7 @@ impl<'tcx> SharedCrateContext<'tcx> { // such as a function name in the module. // 1. http://llvm.org/bugs/show_bug.cgi?id=11479 let llmod_id = format!("{}.{}.rs", crate_name, i); - let local_ccx = LocalCrateContext::new(&shared_ccx, llmod_id.as_slice()); + let local_ccx = LocalCrateContext::new(&shared_ccx, llmod_id[]); shared_ccx.local_ccxs.push(local_ccx); } @@ -374,7 +374,7 @@ impl<'tcx> LocalCrateContext<'tcx> { .target .target .data_layout - .as_slice()); + []); let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo { Some(debuginfo::CrateDebugContext::new(llmod)) @@ -726,7 +726,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! { self.sess().fatal( format!("the type `{}` is too big for the current architecture", - obj.repr(self.tcx())).as_slice()) + obj.repr(self.tcx()))[]) } } diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 135e192a2fd..3b24ded6717 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -48,7 +48,7 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>, debug!("trans_stmt({})", s.repr(cx.tcx())); if cx.sess().asm_comments() { - add_span_comment(cx, s.span, s.repr(cx.tcx()).as_slice()); + add_span_comment(cx, s.span, s.repr(cx.tcx())[]); } let mut bcx = cx; @@ -188,7 +188,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } let name = format!("then-block-{}-", thn.id); - let then_bcx_in = bcx.fcx.new_id_block(name.as_slice(), thn.id); + let then_bcx_in = bcx.fcx.new_id_block(name[], thn.id); let then_bcx_out = trans_block(then_bcx_in, &*thn, dest); trans::debuginfo::clear_source_location(bcx.fcx); @@ -437,7 +437,7 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Some(&def::DefLabel(loop_id)) => loop_id, ref r => { bcx.tcx().sess.bug(format!("{} in def-map for label", - r).as_slice()) + r)[]) } } } @@ -501,7 +501,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let v_str = C_str_slice(ccx, fail_str); let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); - let filename = token::intern_and_get_ident(loc.file.name.as_slice()); + let filename = token::intern_and_get_ident(loc.file.name[]); let filename = C_str_slice(ccx, filename); let line = C_uint(ccx, loc.line); let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false); @@ -510,7 +510,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let did = langcall(bcx, Some(sp), "", PanicFnLangItem); let bcx = callee::trans_lang_call(bcx, did, - args.as_slice(), + args[], Some(expr::Ignore)).bcx; Unreachable(bcx); return bcx; @@ -526,7 +526,7 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Extract the file/line from the span let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); - let filename = token::intern_and_get_ident(loc.file.name.as_slice()); + let filename = token::intern_and_get_ident(loc.file.name[]); // Invoke the lang item let filename = C_str_slice(ccx, filename); @@ -537,7 +537,7 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let did = langcall(bcx, Some(sp), "", PanicBoundsCheckFnLangItem); let bcx = callee::trans_lang_call(bcx, did, - args.as_slice(), + args[], Some(expr::Ignore)).bcx; Unreachable(bcx); return bcx; diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 75473dc58bf..9ab4e92b511 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -463,7 +463,7 @@ impl<'tcx> Datum<'tcx, Lvalue> { } _ => bcx.tcx().sess.bug( format!("Unexpected unsized type in get_element: {}", - bcx.ty_to_string(self.ty)).as_slice()) + bcx.ty_to_string(self.ty))[]) }; Datum { val: val, diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 51e3a83f81f..2545de34ed8 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -284,7 +284,7 @@ impl<'tcx> TypeMap<'tcx> { metadata: DIType) { if self.type_to_metadata.insert(type_, metadata).is_some() { cx.sess().bug(format!("Type metadata for Ty '{}' is already in the TypeMap!", - ppaux::ty_to_string(cx.tcx(), type_)).as_slice()); + ppaux::ty_to_string(cx.tcx(), type_))[]); } } @@ -297,7 +297,7 @@ impl<'tcx> TypeMap<'tcx> { if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() { let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id); cx.sess().bug(format!("Type metadata for unique id '{}' is already in the TypeMap!", - unique_type_id_str.as_slice()).as_slice()); + unique_type_id_str[])[]); } } @@ -378,14 +378,14 @@ impl<'tcx> TypeMap<'tcx> { self.get_unique_type_id_of_type(cx, component_type); let component_type_id = self.get_unique_type_id_as_string(component_type_id); - unique_type_id.push_str(component_type_id.as_slice()); + unique_type_id.push_str(component_type_id[]); } }, ty::ty_uniq(inner_type) => { unique_type_id.push('~'); let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type); let inner_type_id = self.get_unique_type_id_as_string(inner_type_id); - unique_type_id.push_str(inner_type_id.as_slice()); + unique_type_id.push_str(inner_type_id[]); }, ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => { unique_type_id.push('*'); @@ -395,7 +395,7 @@ impl<'tcx> TypeMap<'tcx> { let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type); let inner_type_id = self.get_unique_type_id_as_string(inner_type_id); - unique_type_id.push_str(inner_type_id.as_slice()); + unique_type_id.push_str(inner_type_id[]); }, ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => { unique_type_id.push('&'); @@ -405,12 +405,12 @@ impl<'tcx> TypeMap<'tcx> { let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type); let inner_type_id = self.get_unique_type_id_as_string(inner_type_id); - unique_type_id.push_str(inner_type_id.as_slice()); + unique_type_id.push_str(inner_type_id[]); }, ty::ty_vec(inner_type, optional_length) => { match optional_length { Some(len) => { - unique_type_id.push_str(format!("[{}]", len).as_slice()); + unique_type_id.push_str(format!("[{}]", len)[]); } None => { unique_type_id.push_str("[]"); @@ -419,7 +419,7 @@ impl<'tcx> TypeMap<'tcx> { let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type); let inner_type_id = self.get_unique_type_id_as_string(inner_type_id); - unique_type_id.push_str(inner_type_id.as_slice()); + unique_type_id.push_str(inner_type_id[]); }, ty::ty_trait(ref trait_data) => { unique_type_id.push_str("trait "); @@ -444,7 +444,7 @@ impl<'tcx> TypeMap<'tcx> { self.get_unique_type_id_of_type(cx, parameter_type); let parameter_type_id = self.get_unique_type_id_as_string(parameter_type_id); - unique_type_id.push_str(parameter_type_id.as_slice()); + unique_type_id.push_str(parameter_type_id[]); unique_type_id.push(','); } @@ -457,7 +457,7 @@ impl<'tcx> TypeMap<'tcx> { ty::FnConverging(ret_ty) => { let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty); let return_type_id = self.get_unique_type_id_as_string(return_type_id); - unique_type_id.push_str(return_type_id.as_slice()); + unique_type_id.push_str(return_type_id[]); } ty::FnDiverging => { unique_type_id.push_str("!"); @@ -478,8 +478,8 @@ impl<'tcx> TypeMap<'tcx> { }, _ => { cx.sess().bug(format!("get_unique_type_id_of_type() - unexpected type: {}, {}", - ppaux::ty_to_string(cx.tcx(), type_).as_slice(), - type_.sty).as_slice()) + ppaux::ty_to_string(cx.tcx(), type_)[], + type_.sty)[]) } }; @@ -522,7 +522,7 @@ impl<'tcx> TypeMap<'tcx> { output.push_str(crate_hash.as_str()); output.push_str("/"); - output.push_str(format!("{:x}", def_id.node).as_slice()); + output.push_str(format!("{:x}", def_id.node)[]); // Maybe check that there is no self type here. @@ -535,7 +535,7 @@ impl<'tcx> TypeMap<'tcx> { type_map.get_unique_type_id_of_type(cx, type_parameter); let param_type_id = type_map.get_unique_type_id_as_string(param_type_id); - output.push_str(param_type_id.as_slice()); + output.push_str(param_type_id[]); output.push(','); } @@ -577,7 +577,7 @@ impl<'tcx> TypeMap<'tcx> { self.get_unique_type_id_of_type(cx, parameter_type); let parameter_type_id = self.get_unique_type_id_as_string(parameter_type_id); - unique_type_id.push_str(parameter_type_id.as_slice()); + unique_type_id.push_str(parameter_type_id[]); unique_type_id.push(','); } @@ -591,7 +591,7 @@ impl<'tcx> TypeMap<'tcx> { ty::FnConverging(ret_ty) => { let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty); let return_type_id = self.get_unique_type_id_as_string(return_type_id); - unique_type_id.push_str(return_type_id.as_slice()); + unique_type_id.push_str(return_type_id[]); } ty::FnDiverging => { unique_type_id.push_str("!"); @@ -622,7 +622,7 @@ impl<'tcx> TypeMap<'tcx> { let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type); let enum_variant_type_id = format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id) - .as_slice(), + [], variant_name); let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id)); UniqueTypeId(interner_key) @@ -793,19 +793,19 @@ pub fn create_global_var_metadata(cx: &CrateContext, create_global_var_metadata() - Captured var-id refers to \ unexpected ast_item variant: {}", - var_item).as_slice()) + var_item)[]) } } }, _ => cx.sess().bug(format!("debuginfo::create_global_var_metadata() \ - Captured var-id refers to unexpected \ ast_map variant: {}", - var_item).as_slice()) + var_item)[]) }; let (file_metadata, line_number) = if span != codemap::DUMMY_SP { let loc = span_start(cx, span); - (file_metadata(cx, loc.file.name.as_slice()), loc.line as c_uint) + (file_metadata(cx, loc.file.name[]), loc.line as c_uint) } else { (UNKNOWN_FILE_METADATA, UNKNOWN_LINE_NUMBER) }; @@ -816,7 +816,7 @@ pub fn create_global_var_metadata(cx: &CrateContext, let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id)); let var_name = token::get_ident(ident).get().to_string(); let linkage_name = - namespace_node.mangled_name_of_contained_item(var_name.as_slice()); + namespace_node.mangled_name_of_contained_item(var_name[]); let var_scope = namespace_node.scope; var_name.with_c_str(|var_name| { @@ -857,7 +857,7 @@ pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) { None => { bcx.sess().span_bug(span, format!("no entry in lllocals table for {}", - node_id).as_slice()); + node_id)[]); } }; @@ -911,7 +911,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, "debuginfo::create_captured_var_metadata() - \ Captured var-id refers to unexpected \ ast_map variant: {}", - ast_item).as_slice()); + ast_item)[]); } } } @@ -921,7 +921,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, format!("debuginfo::create_captured_var_metadata() - \ Captured var-id refers to unexpected \ ast_map variant: {}", - ast_item).as_slice()); + ast_item)[]); } }; @@ -1028,7 +1028,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) { None => { bcx.sess().span_bug(span, format!("no entry in lllocals table for {}", - node_id).as_slice()); + node_id)[]); } }; @@ -1286,7 +1286,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, match expr.node { ast::ExprClosure(_, _, ref fn_decl, ref top_level_block) => { let name = format!("fn{}", token::gensym("fn")); - let name = token::str_to_ident(name.as_slice()); + let name = token::str_to_ident(name[]); (name, &**fn_decl, // This is not quite right. It should actually inherit // the generics of the enclosing function. @@ -1318,7 +1318,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, cx.sess() .bug(format!("create_function_debug_context: \ unexpected sort of node: {}", - fnitem).as_slice()) + fnitem)[]) } } } @@ -1329,7 +1329,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } _ => cx.sess().bug(format!("create_function_debug_context: \ unexpected sort of node: {}", - fnitem).as_slice()) + fnitem)[]) }; // This can be the case for functions inlined from another crate @@ -1338,7 +1338,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } let loc = span_start(cx, span); - let file_metadata = file_metadata(cx, loc.file.name.as_slice()); + let file_metadata = file_metadata(cx, loc.file.name[]); let function_type_metadata = unsafe { let fn_signature = get_function_signature(cx, @@ -1365,7 +1365,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let (linkage_name, containing_scope) = if has_path { let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id)); let linkage_name = namespace_node.mangled_name_of_contained_item( - function_name.as_slice()); + function_name[]); let containing_scope = namespace_node.scope; (linkage_name, containing_scope) } else { @@ -1451,7 +1451,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP)); } - return create_DIArray(DIB(cx), signature.as_slice()); + return create_DIArray(DIB(cx), signature[]); } fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, @@ -1484,7 +1484,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, actual_self_type, true); - name_to_append_suffix_to.push_str(actual_self_type_name.as_slice()); + name_to_append_suffix_to.push_str(actual_self_type_name[]); if generics.is_type_parameterized() { name_to_append_suffix_to.push_str(","); @@ -1524,7 +1524,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let actual_type_name = compute_debuginfo_type_name(cx, actual_type, true); - name_to_append_suffix_to.push_str(actual_type_name.as_slice()); + name_to_append_suffix_to.push_str(actual_type_name[]); if index != generics.ty_params.len() - 1 { name_to_append_suffix_to.push_str(","); @@ -1552,7 +1552,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, name_to_append_suffix_to.push('>'); - return create_DIArray(DIB(cx), template_params.as_slice()); + return create_DIArray(DIB(cx), template_params[]); } } @@ -1650,7 +1650,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let cx: &CrateContext = bcx.ccx(); let filename = span_start(cx, span).file.name.clone(); - let file_metadata = file_metadata(cx, filename.as_slice()); + let file_metadata = file_metadata(cx, filename[]); let name = token::get_ident(variable_ident); let loc = span_start(cx, span); @@ -1737,7 +1737,7 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile { let work_dir = cx.sess().working_dir.as_str().unwrap(); let file_name = if full_path.starts_with(work_dir) { - full_path.slice(work_dir.len() + 1u, full_path.len()) + full_path[work_dir.len() + 1u..full_path.len()] } else { full_path }; @@ -1771,7 +1771,7 @@ fn scope_metadata(fcx: &FunctionContext, fcx.ccx.sess().span_bug(error_reporting_span, format!("debuginfo: Could not find scope info for node {}", - node).as_slice()); + node)[]); } } } @@ -1971,7 +1971,7 @@ impl<'tcx> RecursiveTypeDescription<'tcx> { cx.sess().bug(format!("Forward declaration of potentially recursive type \ '{}' was not found in TypeMap!", ppaux::ty_to_string(cx.tcx(), unfinished_type)) - .as_slice()); + []); } } @@ -1983,7 +1983,7 @@ impl<'tcx> RecursiveTypeDescription<'tcx> { set_members_of_composite_type(cx, metadata_stub, llvm_type, - member_descriptions.as_slice()); + member_descriptions[]); return MetadataCreationResult::new(metadata_stub, true); } } @@ -2055,7 +2055,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let struct_metadata_stub = create_struct_stub(cx, struct_llvm_type, - struct_name.as_slice(), + struct_name[], unique_type_id, containing_scope); @@ -2116,7 +2116,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, unique_type_id, create_struct_stub(cx, tuple_llvm_type, - tuple_name.as_slice(), + tuple_name[], unique_type_id, UNKNOWN_SCOPE_METADATA), tuple_llvm_type, @@ -2176,7 +2176,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { set_members_of_composite_type(cx, variant_type_metadata, variant_llvm_type, - member_descriptions.as_slice()); + member_descriptions[]); MemberDescription { name: "".to_string(), llvm_type: variant_llvm_type, @@ -2209,7 +2209,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { set_members_of_composite_type(cx, variant_type_metadata, variant_llvm_type, - member_descriptions.as_slice()); + member_descriptions[]); vec![ MemberDescription { name: "".to_string(), @@ -2309,7 +2309,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { set_members_of_composite_type(cx, variant_type_metadata, variant_llvm_type, - variant_member_descriptions.as_slice()); + variant_member_descriptions[]); // Encode the information about the null variant in the union // member's name. @@ -2388,7 +2388,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .iter() .map(|&t| type_of::type_of(cx, t)) .collect::>() - .as_slice(), + [], struct_def.packed); // Could do some consistency checks here: size, align, field count, discr type @@ -2412,7 +2412,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Some(ref names) => { names.iter() .map(|ident| { - token::get_ident(*ident).get().to_string().into_string() + token::get_ident(*ident).get().to_string() }).collect() } None => variant_info.args.iter().map(|_| "".to_string()).collect() @@ -2455,7 +2455,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id); let loc = span_start(cx, definition_span); - let file_metadata = file_metadata(cx, loc.file.name.as_slice()); + let file_metadata = file_metadata(cx, loc.file.name[]); let variants = ty::enum_variants(cx.tcx(), enum_def_id); @@ -2502,7 +2502,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, UNKNOWN_LINE_NUMBER, bytes_to_bits(discriminant_size), bytes_to_bits(discriminant_align), - create_DIArray(DIB(cx), enumerators_metadata.as_slice()), + create_DIArray(DIB(cx), enumerators_metadata[]), discriminant_base_type_metadata) } }); @@ -2644,7 +2644,7 @@ fn set_members_of_composite_type(cx: &CrateContext, Please use a rustc built with anewer \ version of LLVM.", llvm_version_major, - llvm_version_minor).as_slice()); + llvm_version_minor)[]); } else { cx.sess().bug("debuginfo::set_members_of_composite_type() - \ Already completed forward declaration re-encountered."); @@ -2683,7 +2683,7 @@ fn set_members_of_composite_type(cx: &CrateContext, .collect(); unsafe { - let type_array = create_DIArray(DIB(cx), member_metadata.as_slice()); + let type_array = create_DIArray(DIB(cx), member_metadata[]); llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array); } } @@ -2784,7 +2784,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let member_llvm_types = slice_llvm_type.field_types(); assert!(slice_layout_is_correct(cx, - member_llvm_types.as_slice(), + member_llvm_types[], element_type)); let member_descriptions = [ MemberDescription { @@ -2806,11 +2806,11 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, assert!(member_descriptions.len() == member_llvm_types.len()); let loc = span_start(cx, span); - let file_metadata = file_metadata(cx, loc.file.name.as_slice()); + let file_metadata = file_metadata(cx, loc.file.name[]); let metadata = composite_type_metadata(cx, slice_llvm_type, - slice_type_name.as_slice(), + slice_type_name[], unique_type_id, &member_descriptions, UNKNOWN_SCOPE_METADATA, @@ -2856,7 +2856,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, llvm::LLVMDIBuilderCreateSubroutineType( DIB(cx), UNKNOWN_FILE_METADATA, - create_DIArray(DIB(cx), signature_metadata.as_slice())) + create_DIArray(DIB(cx), signature_metadata[])) }, false); } @@ -2882,7 +2882,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type); cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {}", - pp_type_name.as_slice()).as_slice()); + pp_type_name[])[]); } }; @@ -2896,7 +2896,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, composite_type_metadata(cx, trait_llvm_type, - trait_type_name.as_slice(), + trait_type_name[], unique_type_id, &[], containing_scope, @@ -3019,13 +3019,13 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::ty_tup(ref elements) => { prepare_tuple_metadata(cx, t, - elements.as_slice(), + elements[], unique_type_id, usage_site_span).finalize(cx) } _ => { cx.sess().bug(format!("debuginfo: unexpected type in type_metadata: {}", - sty).as_slice()) + sty)[]) } }; @@ -3043,9 +3043,9 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, type id '{}' to already be in \ the debuginfo::TypeMap but it \ was not. (Ty = {})", - unique_type_id_str.as_slice(), + unique_type_id_str[], ppaux::ty_to_string(cx.tcx(), t)); - cx.sess().span_bug(usage_site_span, error_message.as_slice()); + cx.sess().span_bug(usage_site_span, error_message[]); } }; @@ -3058,9 +3058,9 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, UniqueTypeId maps in \ debuginfo::TypeMap. \ UniqueTypeId={}, Ty={}", - unique_type_id_str.as_slice(), + unique_type_id_str[], ppaux::ty_to_string(cx.tcx(), t)); - cx.sess().span_bug(usage_site_span, error_message.as_slice()); + cx.sess().span_bug(usage_site_span, error_message[]); } } None => { @@ -3266,7 +3266,7 @@ fn create_scope_map(cx: &CrateContext, { // Create a new lexical scope and push it onto the stack let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo); - let file_metadata = file_metadata(cx, loc.file.name.as_slice()); + let file_metadata = file_metadata(cx, loc.file.name[]); let parent_scope = scope_stack.last().unwrap().scope_metadata; let scope_metadata = unsafe { @@ -3391,7 +3391,7 @@ fn create_scope_map(cx: &CrateContext, let file_metadata = file_metadata(cx, loc.file .name - .as_slice()); + []); let parent_scope = scope_stack.last().unwrap().scope_metadata; let scope_metadata = unsafe { @@ -3925,7 +3925,7 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::ty_open(_) | ty::ty_param(_) => { cx.sess().bug(format!("debuginfo: Trying to create type name for \ - unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t)).as_slice()); + unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))[]); } } @@ -4008,13 +4008,13 @@ impl NamespaceTreeNode { None => {} } let string = token::get_name(node.name); - output.push_str(format!("{}", string.get().len()).as_slice()); + output.push_str(format!("{}", string.get().len())[]); output.push_str(string.get()); } let mut name = String::from_str("_ZN"); fill_nested(self, &mut name); - name.push_str(format!("{}", item_name.len()).as_slice()); + name.push_str(format!("{}", item_name.len())[]); name.push_str(item_name); name.push('E'); name @@ -4022,7 +4022,7 @@ impl NamespaceTreeNode { } fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str { - cx.link_meta().crate_name.as_slice() + cx.link_meta().crate_name[] } fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc { @@ -4099,7 +4099,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc { cx.sess().bug(format!("debuginfo::namespace_for_item(): \ path too short for {}", - def_id).as_slice()); + def_id)[]); } } }) diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 81892e5fa83..36f23f4a0ca 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -311,7 +311,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, unsized_info(bcx, k, id, ty_substs[tp_index], |t| t) } _ => bcx.sess().bug(format!("UnsizeStruct with bad sty: {}", - bcx.ty_to_string(unadjusted_ty)).as_slice()) + bcx.ty_to_string(unadjusted_ty))[]) }, &ty::UnsizeVtable(ty::TyTrait { ref principal, .. }, _) => { let substs = principal.substs().with_self_ty(unadjusted_ty).erase_regions(); @@ -442,7 +442,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let unboxed_ty = match datum_ty.sty { ty::ty_uniq(t) => t, _ => bcx.sess().bug(format!("Expected ty_uniq, found {}", - bcx.ty_to_string(datum_ty)).as_slice()) + bcx.ty_to_string(datum_ty))[]) }; let result_ty = ty::mk_uniq(tcx, ty::unsize_ty(tcx, unboxed_ty, k, expr.span)); @@ -660,7 +660,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr.span, format!("trans_rvalue_datum_unadjusted reached \ fall-through case: {}", - expr.node).as_slice()); + expr.node)[]); } } } @@ -1007,7 +1007,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr.span, format!("trans_rvalue_stmt_unadjusted reached \ fall-through case: {}", - expr.node).as_slice()); + expr.node)[]); } } } @@ -1033,14 +1033,14 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, controlflow::trans_if(bcx, expr.id, &**cond, &**thn, els.as_ref().map(|e| &**e), dest) } ast::ExprMatch(ref discr, ref arms, _) => { - _match::trans_match(bcx, expr, &**discr, arms.as_slice(), dest) + _match::trans_match(bcx, expr, &**discr, arms[], dest) } ast::ExprBlock(ref blk) => { controlflow::trans_block(bcx, &**blk, dest) } ast::ExprStruct(_, ref fields, ref base) => { trans_struct(bcx, - fields.as_slice(), + fields[], base.as_ref().map(|e| &**e), expr.span, expr.id, @@ -1052,7 +1052,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans_adt(bcx, expr_ty(bcx, expr), 0, - numbered_fields.as_slice(), + numbered_fields[], None, dest, Some(NodeInfo { id: expr.id, span: expr.span })) @@ -1096,13 +1096,13 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans_overloaded_call(bcx, expr, &**f, - args.as_slice(), + args[], Some(dest)) } else { callee::trans_call(bcx, expr, &**f, - callee::ArgExprs(args.as_slice()), + callee::ArgExprs(args[]), dest) } } @@ -1110,7 +1110,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, callee::trans_method_call(bcx, expr, &*args[0], - callee::ArgExprs(args.as_slice()), + callee::ArgExprs(args[]), dest) } ast::ExprBinary(op, ref lhs, ref rhs) => { @@ -1159,7 +1159,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr.span, format!("trans_rvalue_dps_unadjusted reached fall-through \ case: {}", - expr.node).as_slice()); + expr.node)[]); } } } @@ -1207,7 +1207,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => { bcx.tcx().sess.span_bug(ref_expr.span, format!( "Non-DPS def {} referened by {}", - def, bcx.node_id_to_string(ref_expr.id)).as_slice()); + def, bcx.node_id_to_string(ref_expr.id))[]); } } } @@ -1234,7 +1234,7 @@ fn trans_def_fn_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.tcx().sess.span_bug(ref_expr.span, format!( "trans_def_fn_unadjusted invoked on: {} for {}", def, - ref_expr.repr(bcx.tcx())).as_slice()); + ref_expr.repr(bcx.tcx()))[]); } }; @@ -1257,7 +1257,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, None => { bcx.sess().bug(format!( "trans_local_var: no llval for upvar {} found", - nid).as_slice()); + nid)[]); } } } @@ -1267,7 +1267,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, None => { bcx.sess().bug(format!( "trans_local_var: no datum for local/arg {} found", - nid).as_slice()); + nid)[]); } }; debug!("take_local(nid={}, v={}, ty={})", @@ -1277,7 +1277,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => { bcx.sess().unimpl(format!( "unsupported def type in trans_local_var: {}", - def).as_slice()); + def)[]); } } } @@ -1294,11 +1294,11 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, { match ty.sty { ty::ty_struct(did, ref substs) => { - op(0, struct_fields(tcx, did, substs).as_slice()) + op(0, struct_fields(tcx, did, substs)[]) } ty::ty_tup(ref v) => { - op(0, tup_fields(v.as_slice()).as_slice()) + op(0, tup_fields(v[])[]) } ty::ty_enum(_, ref substs) => { @@ -1308,7 +1308,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, tcx.sess.bug(format!( "cannot get field types from the enum type {} \ without a node ID", - ty.repr(tcx)).as_slice()); + ty.repr(tcx))[]); } Some(node_id) => { let def = tcx.def_map.borrow()[node_id].clone(); @@ -1319,7 +1319,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, op(variant_info.disr_val, struct_fields(tcx, variant_id, - substs).as_slice()) + substs)[]) } _ => { tcx.sess.bug("resolve didn't map this expr to a \ @@ -1333,7 +1333,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, _ => { tcx.sess.bug(format!( "cannot get field types from the type {}", - ty.repr(tcx)).as_slice()); + ty.repr(tcx))[]); } } } @@ -1388,7 +1388,7 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans_adt(bcx, ty, discr, - numbered_fields.as_slice(), + numbered_fields[], optbase, dest, Some(NodeInfo { id: expr_id, span: expr_span })) @@ -2025,7 +2025,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t_in.repr(bcx.tcx()), k_in, t_out.repr(bcx.tcx()), - k_out).as_slice()) + k_out)[]) } } } @@ -2034,7 +2034,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t_in.repr(bcx.tcx()), k_in, t_out.repr(bcx.tcx()), - k_out).as_slice()) + k_out)[]) }; return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock(); } @@ -2196,7 +2196,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.tcx().sess.span_bug( expr.span, format!("deref invoked on expr of illegal type {}", - datum.ty.repr(bcx.tcx())).as_slice()); + datum.ty.repr(bcx.tcx()))[]); } }; diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index d0720319930..d7e3476a470 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -106,7 +106,7 @@ pub fn register_static(ccx: &CrateContext, let llty = type_of::type_of(ccx, ty); let ident = link_name(foreign_item); - match attr::first_attr_value_str_by_name(foreign_item.attrs.as_slice(), + match attr::first_attr_value_str_by_name(foreign_item.attrs[], "linkage") { // If this is a static with a linkage specified, then we need to handle // it a little specially. The typesystem prevents things like &T and @@ -231,13 +231,13 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty::ty_bare_fn(ref fn_ty) => (fn_ty.abi, fn_ty.sig.clone()), _ => ccx.sess().bug("trans_native_call called on non-function type") }; - let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys.as_slice()); + let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys[]); let fn_type = cabi::compute_abi_info(ccx, - llsig.llarg_tys.as_slice(), + llsig.llarg_tys[], llsig.llret_ty, llsig.ret_def); - let arg_tys: &[cabi::ArgType] = fn_type.arg_tys.as_slice(); + let arg_tys: &[cabi::ArgType] = fn_type.arg_tys[]; let mut llargs_foreign = Vec::new(); @@ -363,7 +363,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llforeign_retval = CallWithConv(bcx, llfn, - llargs_foreign.as_slice(), + llargs_foreign[], cc, Some(attrs)); @@ -433,7 +433,7 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) { abi => { let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id); register_foreign_item_fn(ccx, abi, ty, - lname.get().as_slice()); + lname.get()[]); // Unlike for other items, we shouldn't call // `base::update_linkage` here. Foreign items have // special linkage requirements, which are handled @@ -563,7 +563,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.sess().bug(format!("build_rust_fn: extern fn {} has ty {}, \ expected a bare fn ty", ccx.tcx().map.path_to_string(id), - t.repr(tcx)).as_slice()); + t.repr(tcx))[]); } }; @@ -571,7 +571,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.tcx().map.path_to_string(id), id, t.repr(tcx)); - let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice()); + let llfn = base::decl_internal_rust_fn(ccx, t, ps[]); base::set_llvm_fn_attrs(ccx, attrs, llfn); base::trans_fn(ccx, decl, body, llfn, param_substs, id, &[]); llfn @@ -744,7 +744,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("calling llrustfn = {}, t = {}", ccx.tn().val_to_string(llrustfn), t.repr(ccx.tcx())); let attributes = base::get_fn_llvm_attributes(ccx, t); - let llrust_ret_val = builder.call(llrustfn, llrust_args.as_slice(), Some(attributes)); + let llrust_ret_val = builder.call(llrustfn, llrust_args[], Some(attributes)); // Get the return value where the foreign fn expects it. let llforeign_ret_ty = match tys.fn_ty.ret_ty.cast { @@ -811,9 +811,9 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // the massive simplifications that have occurred. pub fn link_name(i: &ast::ForeignItem) -> InternedString { - match attr::first_attr_value_str_by_name(i.attrs.as_slice(), "link_name") { + match attr::first_attr_value_str_by_name(i.attrs[], "link_name") { Some(ln) => ln.clone(), - None => match weak_lang_items::link_name(i.attrs.as_slice()) { + None => match weak_lang_items::link_name(i.attrs[]) { Some(name) => name, None => token::get_ident(i.ident), } @@ -854,7 +854,7 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, }; let llsig = foreign_signature(ccx, &fn_sig, fn_sig.0.inputs.as_slice()); let fn_ty = cabi::compute_abi_info(ccx, - llsig.llarg_tys.as_slice(), + llsig.llarg_tys[], llsig.llret_ty, llsig.ret_def); debug!("foreign_types_for_fn_ty(\ @@ -863,9 +863,9 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty={} -> {}, \ ret_def={}", ty.repr(ccx.tcx()), - ccx.tn().types_to_str(llsig.llarg_tys.as_slice()), + ccx.tn().types_to_str(llsig.llarg_tys[]), ccx.tn().type_to_string(llsig.llret_ty), - ccx.tn().types_to_str(fn_ty.arg_tys.iter().map(|t| t.ty).collect::>().as_slice()), + ccx.tn().types_to_str(fn_ty.arg_tys.iter().map(|t| t.ty).collect::>()[]), ccx.tn().type_to_string(fn_ty.ret_ty.ty), llsig.ret_def); @@ -915,7 +915,7 @@ fn lltype_for_fn_from_foreign_types(ccx: &CrateContext, tys: &ForeignTypes) -> T if tys.fn_sig.0.variadic { Type::variadic_func(llargument_tys.as_slice(), &llreturn_ty) } else { - Type::func(llargument_tys.as_slice(), &llreturn_ty) + Type::func(llargument_tys[], &llreturn_ty) } } diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index dea095ecaf5..c1089ea3ad1 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -160,7 +160,7 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val let (glue, new_sym) = match ccx.available_drop_glues().borrow().get(&t) { Some(old_sym) => { - let glue = decl_cdecl_fn(ccx, old_sym.as_slice(), llfnty, ty::mk_nil(ccx.tcx())); + let glue = decl_cdecl_fn(ccx, old_sym[], llfnty, ty::mk_nil(ccx.tcx())); (glue, None) }, None => { @@ -231,7 +231,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, f.sig.0.inputs[0] } _ => bcx.sess().bug(format!("Expected function type, found {}", - bcx.ty_to_string(fty)).as_slice()) + bcx.ty_to_string(fty))[]) }; let (struct_data, info) = if ty::type_is_sized(bcx.tcx(), t) { @@ -350,7 +350,7 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: (Mul(bcx, info, C_uint(bcx.ccx(), unit_size)), C_uint(bcx.ccx(), 8u)) } _ => bcx.sess().bug(format!("Unexpected unsized type, found {}", - bcx.ty_to_string(t)).as_slice()) + bcx.ty_to_string(t))[]) } } @@ -422,7 +422,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) bcx.sess().warn(format!("Ignoring drop flag in destructor for {}\ because the struct is unsized. See issue\ #16758", - bcx.ty_to_string(t)).as_slice()); + bcx.ty_to_string(t))[]); trans_struct_drop(bcx, t, v0, dtor, did, substs) } } @@ -504,7 +504,7 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) note_unique_llvm_symbol(ccx, name); let ty_name = token::intern_and_get_ident( - ppaux::ty_to_string(ccx.tcx(), t).as_slice()); + ppaux::ty_to_string(ccx.tcx(), t)[]); let ty_name = C_str_slice(ccx, ty_name); debug!("--- declare_tydesc {}", ppaux::ty_to_string(ccx.tcx(), t)); @@ -523,8 +523,8 @@ fn declare_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, let fn_nm = mangle_internal_name_by_type_and_seq( ccx, t, - format!("glue_{}", name).as_slice()); - let llfn = decl_cdecl_fn(ccx, fn_nm.as_slice(), llfnty, ty::mk_nil(ccx.tcx())); + format!("glue_{}", name)[]); + let llfn = decl_cdecl_fn(ccx, fn_nm[], llfnty, ty::mk_nil(ccx.tcx())); note_unique_llvm_symbol(ccx, fn_nm.clone()); return (fn_nm, llfn); } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index a6f7c849f4d..cc506e409c5 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -118,7 +118,7 @@ pub fn check_intrinsics(ccx: &CrateContext) { "" } else { "s" - }).as_slice()); + })[]); } if ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.to) || ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.from) { diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 15f6d7bc3f4..25b8cefa68f 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -77,7 +77,7 @@ pub fn trans_impl(ccx: &CrateContext, match *impl_item { ast::MethodImplItem(ref method) => { if method.pe_generics().ty_params.len() == 0u { - let trans_everywhere = attr::requests_inline(method.attrs.as_slice()); + let trans_everywhere = attr::requests_inline(method.attrs[]); for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) { let llfn = get_item_val(ccx, method.id); trans_fn(ccx, @@ -293,7 +293,7 @@ pub fn trans_static_method_callee(bcx: Block, _ => { bcx.tcx().sess.bug( format!("static call to invalid vtable: {}", - vtbl.repr(bcx.tcx())).as_slice()); + vtbl.repr(bcx.tcx()))[]); } } } @@ -375,7 +375,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, traits::VtableParam(..) => { bcx.sess().bug( format!("resolved vtable bad vtable {} in trans", - vtable.repr(bcx.tcx())).as_slice()); + vtable.repr(bcx.tcx()))[]); } } } @@ -566,7 +566,7 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.sess().bug( format!("resolved vtable for {} to bad vtable {} in trans", trait_ref.repr(bcx.tcx()), - vtable.repr(bcx.tcx())).as_slice()); + vtable.repr(bcx.tcx()))[]); } } }); @@ -598,7 +598,7 @@ pub fn make_vtable>(ccx: &CrateContext, let components: Vec<_> = head.into_iter().chain(ptrs).collect(); unsafe { - let tbl = C_struct(ccx, components.as_slice(), false); + let tbl = C_struct(ccx, components[], false); let sym = token::gensym("vtable"); let vt_gvar = format!("vtable{}", sym.uint()).with_c_str(|buf| { llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(), buf) diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index cb3c56ad277..2a6aff56513 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -122,7 +122,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, hash = format!("h{}", state.result()); ccx.tcx().map.with_path(fn_id.node, |path| { - exported_name(path, hash.as_slice()) + exported_name(path, hash[]) }) }; @@ -132,9 +132,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let mut hash_id = Some(hash_id); let mk_lldecl = |abi: abi::Abi| { let lldecl = if abi != abi::Rust { - foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, s.as_slice()) + foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, s[]) } else { - decl_internal_rust_fn(ccx, mono_ty, s.as_slice()) + decl_internal_rust_fn(ccx, mono_ty, s[]) }; ccx.monomorphized().borrow_mut().insert(hash_id.take().unwrap(), lldecl); @@ -168,12 +168,12 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, .. } => { let d = mk_lldecl(abi); - let needs_body = setup_lldecl(d, i.attrs.as_slice()); + let needs_body = setup_lldecl(d, i.attrs[]); if needs_body { if abi != abi::Rust { foreign::trans_rust_fn_with_foreign_abi( ccx, &**decl, &**body, &[], d, psubsts, fn_id.node, - Some(hash.as_slice())); + Some(hash[])); } else { trans_fn(ccx, &**decl, &**body, d, psubsts, fn_id.node, &[]); } @@ -197,7 +197,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trans_enum_variant(ccx, parent, &*v, - args.as_slice(), + args[], this_tv.disr_val, psubsts, d); @@ -211,7 +211,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, match *ii { ast::MethodImplItem(ref mth) => { let d = mk_lldecl(abi::Rust); - let needs_body = setup_lldecl(d, mth.attrs.as_slice()); + let needs_body = setup_lldecl(d, mth.attrs[]); if needs_body { trans_fn(ccx, mth.pe_fn_decl(), @@ -232,7 +232,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, match *method { ast::ProvidedMethod(ref mth) => { let d = mk_lldecl(abi::Rust); - let needs_body = setup_lldecl(d, mth.attrs.as_slice()); + let needs_body = setup_lldecl(d, mth.attrs[]); if needs_body { trans_fn(ccx, mth.pe_fn_decl(), mth.pe_body(), d, psubsts, mth.id, &[]); @@ -241,7 +241,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } _ => { ccx.sess().bug(format!("can't monomorphize a {}", - map_node).as_slice()) + map_node)[]) } } } @@ -249,7 +249,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let d = mk_lldecl(abi::Rust); set_inline_hint(d); base::trans_tuple_struct(ccx, - struct_def.fields.as_slice(), + struct_def.fields[], struct_def.ctor_id.expect("ast-mapped tuple struct \ didn't have a ctor id"), psubsts, @@ -267,7 +267,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ast_map::NodePat(..) | ast_map::NodeLocal(..) => { ccx.sess().bug(format!("can't monomorphize a {}", - map_node).as_slice()) + map_node)[]) } }; diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index 51a0533a7bb..45a2a343066 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -102,7 +102,7 @@ impl Type { } pub fn int(ccx: &CrateContext) -> Type { - match ccx.tcx().sess.target.target.target_word_size.as_slice() { + match ccx.tcx().sess.target.target.target_word_size[] { "32" => Type::i32(ccx), "64" => Type::i64(ccx), tws => panic!("Unsupported target word size for int: {}", tws), diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 2801e0ccead..2ef0006814a 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -137,7 +137,7 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let input_tys = inputs.iter().map(|&arg_ty| type_of_explicit_arg(cx, arg_ty)); atys.extend(input_tys); - Type::func(atys.as_slice(), &lloutputtype) + Type::func(atys[], &lloutputtype) } // Given a function type and a count of ty params, construct an llvm type @@ -187,7 +187,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ let llsizingty = match t.sty { _ if !ty::lltype_is_sized(cx.tcx(), t) => { cx.sess().bug(format!("trying to take the sizing type of {}, an unsized type", - ppaux::ty_to_string(cx.tcx(), t)).as_slice()) + ppaux::ty_to_string(cx.tcx(), t))[]) } ty::ty_bool => Type::bool(cx), @@ -241,7 +241,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => { cx.sess().bug(format!("fictitious type {} in sizing_type_of()", - ppaux::ty_to_string(cx.tcx(), t)).as_slice()) + ppaux::ty_to_string(cx.tcx(), t))[]) } ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable") }; @@ -318,7 +318,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { let repr = adt::represent_type(cx, t); let tps = substs.types.get_slice(subst::TypeSpace); let name = llvm_type_name(cx, an_enum, did, tps); - adt::incomplete_type_of(cx, &*repr, name.as_slice()) + adt::incomplete_type_of(cx, &*repr, name[]) } ty::ty_unboxed_closure(did, _, ref substs) => { // Only create the named struct, but don't fill it in. We @@ -329,7 +329,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // contents of the VecPerParamSpace to to construct the llvm // name let name = llvm_type_name(cx, an_unboxed_closure, did, substs.types.as_slice()); - adt::incomplete_type_of(cx, &*repr, name.as_slice()) + adt::incomplete_type_of(cx, &*repr, name[]) } ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => { @@ -389,7 +389,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { let repr = adt::represent_type(cx, t); let tps = substs.types.get_slice(subst::TypeSpace); let name = llvm_type_name(cx, a_struct, did, tps); - adt::incomplete_type_of(cx, &*repr, name.as_slice()) + adt::incomplete_type_of(cx, &*repr, name[]) } } @@ -408,7 +408,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { } ty::ty_trait(..) => Type::opaque_trait(cx), _ => cx.sess().bug(format!("ty_open with sized type: {}", - ppaux::ty_to_string(cx.tcx(), t)).as_slice()) + ppaux::ty_to_string(cx.tcx(), t))[]) }, ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 175763c874e..8e7452f30d3 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -168,7 +168,7 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( format!("`{}`", name) } else { format!("one of `{}`'s {} elided lifetimes", name, n) - }.as_slice()); + }[]); if len == 2 && i == 0 { m.push_str(" or "); @@ -323,7 +323,7 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( format!("wrong number of type arguments: {} {}, found {}", expected, required_ty_param_count, - supplied_ty_param_count).as_slice()); + supplied_ty_param_count)[]); } else if supplied_ty_param_count > formal_ty_param_count { let expected = if required_ty_param_count < formal_ty_param_count { "expected at most" @@ -334,7 +334,7 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( format!("wrong number of type arguments: {} {}, found {}", expected, formal_ty_param_count, - supplied_ty_param_count).as_slice()); + supplied_ty_param_count)[]); } if supplied_ty_param_count > required_ty_param_count @@ -723,7 +723,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( .sess .span_bug(ast_ty.span, format!("unbound path {}", - path.repr(this.tcx())).as_slice()) + path.repr(this.tcx()))[]) } Some(&d) => d }; @@ -920,10 +920,10 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None) } ast::TyObjectSum(ref ty, ref bounds) => { - match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) { + match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) { Ok(trait_ref) => { trait_ref_to_object_type(this, rscope, ast_ty.span, - trait_ref, bounds.as_slice()) + trait_ref, bounds[]) } Err(ErrorReported) => { ty::mk_err() @@ -977,7 +977,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ty::mk_closure(tcx, fn_decl) } ast::TyPolyTraitRef(ref bounds) => { - conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice()) + conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds[]) } ast::TyPath(ref path, id) => { let a_def = match tcx.def_map.borrow().get(&id) { @@ -985,7 +985,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( tcx.sess .span_bug(ast_ty.span, format!("unbound path {}", - path.repr(tcx)).as_slice()) + path.repr(tcx))[]) } Some(&d) => d }; @@ -1019,7 +1019,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( def::DefMod(id) => { tcx.sess.span_fatal(ast_ty.span, format!("found module name used as a type: {}", - tcx.map.node_to_string(id.node)).as_slice()); + tcx.map.node_to_string(id.node))[]); } def::DefPrimTy(_) => { panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); @@ -1038,7 +1038,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( .last() .unwrap() .identifier) - .get()).as_slice()); + .get())[]); ty::mk_err() } def::DefAssociatedPath(typ, assoc_ident) => { @@ -1084,7 +1084,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( tcx.sess.span_fatal(ast_ty.span, format!("found value name used \ as a type: {}", - a_def).as_slice()); + a_def)[]); } } } @@ -1112,7 +1112,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast_ty.span, format!("expected constant expr for array \ length: {}", - *r).as_slice()); + *r)[]); } } } @@ -1235,7 +1235,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( let input_params = if self_ty.is_some() { decl.inputs.slice_from(1) } else { - decl.inputs.as_slice() + decl.inputs[] }; let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None)); let input_pats: Vec = input_params.iter() @@ -1502,7 +1502,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( this.tcx().sess.span_err( b.trait_ref.path.span, format!("only the builtin traits can be used \ - as closure or object bounds").as_slice()); + as closure or object bounds")[]); } let region_bound = compute_region_bound(this, @@ -1572,7 +1572,7 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>, tcx.sess.span_err( span, format!("ambiguous lifetime bound, \ - explicit lifetime bound required").as_slice()); + explicit lifetime bound required")[]); } return Some(r); } @@ -1598,7 +1598,7 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( None => { this.tcx().sess.span_err( span, - format!("explicit lifetime bound required").as_slice()); + format!("explicit lifetime bound required")[]); ty::ReStatic } } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 3b7eb22e56c..74e690bf68f 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -269,7 +269,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, span, format!( "trait method is &self but first arg is: {}", - transformed_self_ty.repr(fcx.tcx())).as_slice()); + transformed_self_ty.repr(fcx.tcx()))[]); } } } @@ -279,7 +279,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, span, format!( "unexpected explicit self type in operator method: {}", - method_ty.explicit_self).as_slice()); + method_ty.explicit_self)[]); } } } @@ -333,7 +333,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if is_field { cx.sess.span_note(span, format!("use `(s.{0})(...)` if you meant to call the \ - function stored in the `{0}` field", method_ustring).as_slice()); + function stored in the `{0}` field", method_ustring)[]); } if static_sources.len() > 0 { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b5776f9aeb3..961b664e404 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -557,7 +557,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { self.tcx().sess.span_bug( self.span, format!("No entry for unboxed closure: {}", - closure_def_id.repr(self.tcx())).as_slice()); + closure_def_id.repr(self.tcx()))[]); } }; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index cd9a09efe08..6b7ca399ad2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -518,7 +518,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, // The free region references will be bound the node_id of the body block. let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig); - let arg_tys = fn_sig.inputs.as_slice(); + let arg_tys = fn_sig.inputs[]; let ret_ty = fn_sig.output; debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})", @@ -616,7 +616,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { ast::ItemEnum(ref enum_definition, _) => { check_enum_variants(ccx, it.span, - enum_definition.variants.as_slice(), + enum_definition.variants[], it.id); } ast::ItemFn(ref decl, _, _, _, ref body) => { @@ -915,7 +915,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, but not in the trait", token::get_name(trait_m.name), ppaux::explicit_self_category_to_str( - &impl_m.explicit_self)).as_slice()); + &impl_m.explicit_self))[]); return; } (_, &ty::StaticExplicitSelfCategory) => { @@ -925,7 +925,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, but not in the impl", token::get_name(trait_m.name), ppaux::explicit_self_category_to_str( - &trait_m.explicit_self)).as_slice()); + &trait_m.explicit_self))[]); return; } _ => { @@ -1229,7 +1229,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, span, format!("lifetime parameters or bounds on method `{}` do \ not match the trait declaration", - token::get_name(impl_m.name)).as_slice()); + token::get_name(impl_m.name))[]); return false; } @@ -1281,7 +1281,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, from its counterpart `{}` \ declared in the trait", impl_param.name.user_string(tcx), - trait_param.name.user_string(tcx)).as_slice()); + trait_param.name.user_string(tcx))[]); true } else { false @@ -1291,14 +1291,14 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, tcx.sess.span_note( span, format!("the impl is missing the following bounds: `{}`", - missing.user_string(tcx)).as_slice()); + missing.user_string(tcx))[]); } if extra.len() != 0 { tcx.sess.span_note( span, format!("the impl has the following extra bounds: `{}`", - extra.user_string(tcx)).as_slice()); + extra.user_string(tcx))[]); } if err { @@ -1557,7 +1557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx().sess.span_bug( span, format!("no type for local variable {}", - nid).as_slice()); + nid)[]); } } } @@ -1805,7 +1805,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(&t) => t, None => { self.tcx().sess.bug(format!("no type for expr in fcx {}", - self.tag()).as_slice()); + self.tag())[]); } } } @@ -1835,7 +1835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx().sess.bug( format!("no type for node {}: {} in fcx {}", id, self.tcx().map.node_to_string(id), - self.tag()).as_slice()); + self.tag())[]); } } } @@ -2392,7 +2392,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, Ok(trait_did) => trait_did, Err(ref err_string) => { fcx.tcx().sess.span_err(iterator_expr.span, - err_string.as_slice()); + err_string[]); return ty::mk_err() } }; @@ -2419,7 +2419,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, format!("`for` loop expression has type `{}` which does \ not implement the `Iterator` trait; \ maybe try .iter()", - ty_string).as_slice()); + ty_string)[]); } ty::mk_err() } @@ -2457,7 +2457,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, format!("`next` method of the `Iterator` \ trait has an unexpected type `{}`", fcx.infcx().ty_to_string(return_type)) - .as_slice()); + []); ty::mk_err() } } @@ -2484,7 +2484,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, check_argument_types(fcx, sp, - err_inputs.as_slice(), + err_inputs[], callee_expr, args_no_rcvr, autoref_args, @@ -2941,7 +2941,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, // Call the generic checker. check_argument_types(fcx, call_expr.span, - fn_sig.inputs.as_slice(), + fn_sig.inputs[], f, args, AutorefArgs::No, @@ -3306,7 +3306,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ty::ty_struct(base_id, ref substs) => { debug!("struct named {}", ppaux::ty_to_string(tcx, base_t)); let fields = ty::lookup_struct_fields(tcx, base_id); - lookup_field_ty(tcx, base_id, fields.as_slice(), + lookup_field_ty(tcx, base_id, fields[], field.node.name, &(*substs)) } _ => None @@ -3369,7 +3369,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, if tuple_like { debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t)); let fields = ty::lookup_struct_fields(tcx, base_id); - lookup_tup_field_ty(tcx, base_id, fields.as_slice(), + lookup_tup_field_ty(tcx, base_id, fields[], idx.node, &(*substs)) } else { None @@ -3522,7 +3522,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, class_id, id, struct_substs, - class_fields.as_slice(), + class_fields[], fields, base_expr.is_none()); if ty::type_is_error(fcx.node_ty(id)) { @@ -3564,7 +3564,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, variant_id, id, substitutions, - variant_fields.as_slice(), + variant_fields[], fields, true); fcx.write_ty(id, enum_type); @@ -3936,8 +3936,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let f_ty = fcx.expr_ty(&**f); let args: Vec<_> = args.iter().map(|x| x).collect(); - if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) { - check_call(fcx, expr, &**f, args.as_slice()); + if !try_overloaded_call(fcx, expr, &**f, f_ty, args[]) { + check_call(fcx, expr, &**f, args[]); let args_err = args.iter().fold(false, |rest_err, a| { // is this not working? @@ -3949,7 +3949,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } } ast::ExprMethodCall(ident, ref tps, ref args) => { - check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice(), lvalue_pref); + check_method_call(fcx, expr, ident, args[], tps[], lvalue_pref); let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a)); let args_err = arg_tys.fold(false, |rest_err, a| { @@ -4074,7 +4074,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let struct_id = match def { Some(def::DefVariant(enum_id, variant_id, true)) => { check_struct_enum_variant(fcx, id, expr.span, enum_id, - variant_id, fields.as_slice()); + variant_id, fields[]); enum_id } Some(def::DefTrait(def_id)) => { @@ -4083,7 +4083,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, pprust::path_to_string(path)); check_struct_fields_on_error(fcx, id, - fields.as_slice(), + fields[], base_expr); def_id }, @@ -4096,7 +4096,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, id, expr.span, struct_did, - fields.as_slice(), + fields[], base_expr.as_ref().map(|e| &**e)); } _ => { @@ -4105,7 +4105,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, pprust::path_to_string(path)); check_struct_fields_on_error(fcx, id, - fields.as_slice(), + fields[], base_expr); } } @@ -4146,7 +4146,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.infcx() .ty_to_string( actual_structure_type), - type_error_description).as_slice()); + type_error_description)[]); ty::note_and_explain_type_err(tcx, &type_error); } } @@ -4755,7 +4755,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt, } let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id }) - .as_slice().get(0).unwrap_or(&attr::ReprAny); + [].get(0).unwrap_or(&attr::ReprAny); if hint != attr::ReprAny && vs.len() <= 1 { if vs.len() == 1 { @@ -5438,7 +5438,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { "get_tydesc" => { let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) { Ok(t) => t, - Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); } + Err(s) => { tcx.sess.span_fatal(it.span, s[]); } }; let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { ty: tydesc_ty, @@ -5454,7 +5454,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { ty::mk_struct(ccx.tcx, did, subst::Substs::empty())), Err(msg) => { - tcx.sess.span_fatal(it.span, msg.as_slice()); + tcx.sess.span_fatal(it.span, msg[]); } } }, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 8e70b8ff0da..22502c0dd1a 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -251,7 +251,7 @@ fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region { } _ => { tcx.sess.bug(format!("unexpected def in region_of_def: {}", - def).as_slice()) + def)[]) } } } @@ -345,13 +345,13 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { Some(f) => f, None => { self.tcx().sess.bug( - format!("No fn-sig entry for id={}", id).as_slice()); + format!("No fn-sig entry for id={}", id)[]); } }; let len = self.region_param_pairs.len(); - self.relate_free_regions(fn_sig.as_slice(), body.id); - link_fn_args(self, CodeExtent::from_node_id(body.id), fn_decl.inputs.as_slice()); + self.relate_free_regions(fn_sig[], body.id); + link_fn_args(self, CodeExtent::from_node_id(body.id), fn_decl.inputs[]); self.visit_block(body); self.visit_region_obligations(body.id); self.region_param_pairs.truncate(len); @@ -738,7 +738,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { } ast::ExprMatch(ref discr, ref arms, _) => { - link_match(rcx, &**discr, arms.as_slice()); + link_match(rcx, &**discr, arms[]); visit::walk_expr(rcx, expr); } @@ -1186,7 +1186,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, ty::ty_rptr(r, ref m) => (m.mutbl, r), _ => rcx.tcx().sess.span_bug(deref_expr.span, format!("bad overloaded deref type {}", - method.ty.repr(rcx.tcx())).as_slice()) + method.ty.repr(rcx.tcx()))[]) }; { let mc = mc::MemCategorizationContext::new(rcx); @@ -1560,7 +1560,7 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, span, format!("Illegal upvar id: {}", upvar_id.repr( - rcx.tcx())).as_slice()); + rcx.tcx()))[]); } } } diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs index 112ad1fb5b9..eaf638e388e 100644 --- a/src/librustc_typeck/check/regionmanip.rs +++ b/src/librustc_typeck/check/regionmanip.rs @@ -138,7 +138,7 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { ty::ty_open(_) => { self.tcx.sess.bug( format!("Unexpected type encountered while doing wf check: {}", - ty.repr(self.tcx)).as_slice()); + ty.repr(self.tcx))[]); } } } diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 4db795a1fda..e23bf46b564 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -77,7 +77,7 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, source_expr.span, format!("can only cast an boxed pointer \ to a boxed object, not a {}", - ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice()); + ty::ty_sort_string(fcx.tcx(), source_ty))[]); } (_, &ty::ty_rptr(..)) => { @@ -85,7 +85,7 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, source_expr.span, format!("can only cast a &-pointer \ to an &-object, not a {}", - ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice()); + ty::ty_sort_string(fcx.tcx(), source_ty))[]); } _ => { @@ -164,7 +164,7 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>, trait_name); for msg in errors { - tcx.sess.note(msg.as_slice()); + tcx.sess.note(msg[]); } } @@ -455,7 +455,7 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, format!( "unable to infer enough type information about `{}`; type annotations \ required", - self_ty.user_string(fcx.tcx())).as_slice()); + self_ty.user_string(fcx.tcx()))[]); } else { fcx.tcx().sess.span_err( obligation.cause.span, @@ -464,7 +464,7 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, locate the impl of the trait `{}` for \ the type `{}`; type annotations required", trait_ref.user_string(fcx.tcx()), - self_ty.user_string(fcx.tcx())).as_slice()); + self_ty.user_string(fcx.tcx()))[]); note_obligation_cause(fcx, obligation); } } @@ -477,7 +477,7 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cannot locate the impl of the trait `{}` for \ the type `{}`", trait_ref.user_string(fcx.tcx()), - self_ty.user_string(fcx.tcx())).as_slice()); + self_ty.user_string(fcx.tcx()))[]); } } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 5d0bb6622c2..c08eeb6e13e 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -488,7 +488,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { format!("the trait `Copy` may not be \ implemented for this type; field \ `{}` does not implement `Copy`", - token::get_name(name)).as_slice()) + token::get_name(name))[]) } Err(ty::VariantDoesNotImplementCopy(name)) => { tcx.sess @@ -496,7 +496,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { format!("the trait `Copy` may not be \ implemented for this type; variant \ `{}` does not implement `Copy`", - token::get_name(name)).as_slice()) + token::get_name(name))[]) } Err(ty::TypeIsStructural) => { tcx.sess diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3f59b50337f..22c9a2e7b32 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -171,7 +171,7 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> { x => { self.tcx.sess.bug(format!("unexpected sort of node \ in get_item_ty(): {}", - x).as_slice()); + x)[]); } } } @@ -217,7 +217,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ast::TupleVariantKind(ref args) if args.len() > 0 => { let rs = ExplicitRscope; let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect(); - ty::mk_ctor_fn(tcx, input_tys.as_slice(), enum_ty) + ty::mk_ctor_fn(tcx, input_tys[], enum_ty) } ast::TupleVariantKind(_) => { @@ -270,7 +270,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ccx, trait_id, &trait_def.generics, - trait_items.as_slice(), + trait_items[], &m.id, &m.ident.name, &m.explicit_self, @@ -284,7 +284,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ccx, trait_id, &trait_def.generics, - trait_items.as_slice(), + trait_items[], &m.id, &m.pe_ident().name, m.pe_explicit_self(), @@ -379,7 +379,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let tmcx = TraitMethodCtxt { ccx: ccx, trait_id: local_def(trait_id), - trait_items: trait_items.as_slice(), + trait_items: trait_items[], method_generics: &ty_generics, }; let trait_self_ty = ty::mk_self_type(tmcx.tcx(), @@ -1040,7 +1040,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { write_ty_to_tcx(tcx, it.id, pty.ty); get_enum_variant_types(ccx, pty.ty, - enum_definition.variants.as_slice(), + enum_definition.variants[], generics); }, ast::ItemImpl(_, @@ -1086,7 +1086,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { ast_trait_ref.ref_id).def_id()) } }, - impl_items: impl_items.as_slice(), + impl_items: impl_items[], impl_generics: &ty_generics, }; @@ -1184,7 +1184,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { local_def(it.id)); let convert_method_context = TraitConvertMethodContext(local_def(it.id), - trait_methods.as_slice()); + trait_methods[]); convert_methods(ccx, convert_method_context, TraitContainer(local_def(it.id)), @@ -1279,7 +1279,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, |field| (*tcx.tcache.borrow())[ local_def(field.node.id)].ty).collect(); let ctor_fn_ty = ty::mk_ctor_fn(tcx, - inputs.as_slice(), + inputs[], selfty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); tcx.tcache.borrow_mut().insert(local_def(ctor_id), @@ -1320,7 +1320,7 @@ fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item), _ => { ccx.tcx.sess.bug(format!("get_trait_def({}): not an item", - trait_id.node).as_slice()) + trait_id.node)[]) } } } @@ -1345,7 +1345,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ref s => { tcx.sess.span_bug( it.span, - format!("trait_def_of_item invoked on {}", s).as_slice()); + format!("trait_def_of_item invoked on {}", s)[]); } }; @@ -1585,8 +1585,8 @@ fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, -> ty::Generics<'tcx> { ty_generics(ccx, subst::TypeSpace, - generics.lifetimes.as_slice(), - generics.ty_params.as_slice(), + generics.lifetimes[], + generics.ty_params[], ty::Generics::empty(), &generics.where_clause, create_type_parameters_for_associated_types) @@ -1602,8 +1602,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut generics = ty_generics(ccx, subst::TypeSpace, - ast_generics.lifetimes.as_slice(), - ast_generics.ty_params.as_slice(), + ast_generics.lifetimes[], + ast_generics.ty_params[], ty::Generics::empty(), &ast_generics.where_clause, DontCreateTypeParametersForAssociatedTypes); @@ -1672,8 +1672,8 @@ fn ty_generics_for_fn_or_method<'tcx,AC>( let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics); ty_generics(this, subst::FnSpace, - early_lifetimes.as_slice(), - generics.ty_params.as_slice(), + early_lifetimes[], + generics.ty_params[], base_generics, &generics.where_clause, create_type_parameters_for_associated_types) @@ -1701,7 +1701,7 @@ fn add_unsized_bound<'tcx,AC>(this: &AC, a default. \ Only `Sized?` is \ supported", - desc).as_slice()); + desc)[]); ty::try_add_builtin_trait(this.tcx(), kind_id, bounds); @@ -1973,7 +1973,7 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC, let bounds = compute_bounds(this, param.ident.name, param_ty, - param.bounds.as_slice(), + param.bounds[], ¶m.unbound, param.span); let default = match param.default { @@ -2054,7 +2054,7 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>, if !param_bounds.builtin_bounds.contains(&ty::BoundSized) { ty::each_bound_trait_and_supertraits( tcx, - param_bounds.trait_bounds.as_slice(), + param_bounds.trait_bounds[], |trait_ref| { let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id()); if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 49c5f13fa73..5a8f58274cc 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -196,7 +196,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>, format!("{}: {}", msg(), ty::type_err_to_str(tcx, - terr)).as_slice()); + terr))[]); ty::note_and_explain_type_err(tcx, terr); false } @@ -245,7 +245,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, format!("main has a non-function type: found \ `{}`", ppaux::ty_to_string(tcx, - main_t)).as_slice()); + main_t))[]); } } } @@ -296,8 +296,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, tcx.sess.span_bug(start_span, format!("start has a non-function type: found \ `{}`", - ppaux::ty_to_string(tcx, - start_t)).as_slice()); + ppaux::ty_to_string(tcx, start_t))[]); } } } diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index ef0d1bc3859..754294a3b8e 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -556,7 +556,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { None => { self.tcx().sess.bug(format!( "no inferred index entry for {}", - self.tcx().map.node_to_string(param_id)).as_slice()); + self.tcx().map.node_to_string(param_id))[]); } } } @@ -834,7 +834,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.tcx().sess.bug( format!("unexpected type encountered in \ variance inference: {}", - ty.repr(self.tcx())).as_slice()); + ty.repr(self.tcx()))[]); } } } @@ -911,7 +911,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { .sess .bug(format!("unexpected region encountered in variance \ inference: {}", - region.repr(self.tcx())).as_slice()); + region.repr(self.tcx()))[]); } } } @@ -1046,7 +1046,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { // attribute and report an error with various results if found. if ty::has_attr(tcx, item_def_id, "rustc_variance") { let found = item_variances.repr(tcx); - tcx.sess.span_err(tcx.map.span(item_id), found.as_slice()); + tcx.sess.span_err(tcx.map.span(item_id), found[]); } let newly_added = tcx.item_variance_map.borrow_mut() diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 08fb94a801c..25a20e5998b 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -36,7 +36,7 @@ impl ExternalHtml { pub fn load_string(input: &Path) -> io::IoResult> { let mut f = try!(io::File::open(input)); let d = try!(f.read_to_end()); - Ok(str::from_utf8(d.as_slice()).map(|s| s.to_string())) + Ok(str::from_utf8(d.as_slice()).map(|s| s.to_string()).ok()) } macro_rules! load_or_return { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index e01cbbc812b..a2d5530692c 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -16,7 +16,7 @@ //! them in the future to instead emit any format desired. use std::fmt; -use std::string::String; +use std::iter::repeat; use syntax::ast; use syntax::ast_util; @@ -198,12 +198,12 @@ fn resolved_path(w: &mut fmt::Formatter, did: ast::DefId, p: &clean::Path, path(w, p, print_all, |cache, loc| { if ast_util::is_local(did) || cache.inlined.contains(&did) { - Some(("../".repeat(loc.len())).to_string()) + Some(repeat("../").take(loc.len()).collect::()) } else { match cache.extern_locations[did.krate] { render::Remote(ref s) => Some(s.to_string()), render::Local => { - Some(("../".repeat(loc.len())).to_string()) + Some(repeat("../").take(loc.len()).collect::()) } render::Unknown => None, } @@ -324,7 +324,7 @@ fn primitive_link(f: &mut fmt::Formatter, let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); let len = if len == 0 {0} else {len - 1}; try!(write!(f, "", - "../".repeat(len), + repeat("../").take(len).collect::(), prim.to_url_str())); needs_termination = true; } @@ -337,7 +337,7 @@ fn primitive_link(f: &mut fmt::Formatter, render::Remote(ref s) => Some(s.to_string()), render::Local => { let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); - Some("../".repeat(len)) + Some(repeat("../").take(len).collect::()) } render::Unknown => None, }; diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 111650f565c..c936f6a0819 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -34,7 +34,7 @@ pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String { class, id, &mut out).unwrap(); - String::from_utf8_lossy(out[]).into_string() + String::from_utf8_lossy(out[]).into_owned() } /// Exhausts the `lexer` writing the output into `out`. diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index efec620bca7..dc31cfae99c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -42,8 +42,8 @@ use std::fmt; use std::io::fs::PathExtensions; use std::io::{fs, File, BufferedWriter, BufferedReader}; use std::io; +use std::iter::repeat; use std::str; -use std::string::String; use std::sync::Arc; use externalfiles::ExternalHtml; @@ -1186,7 +1186,8 @@ impl Context { &Sidebar{ cx: cx, item: it }, &Item{ cx: cx, item: it })); } else { - let mut url = "../".repeat(cx.current.len()); + let mut url = repeat("../").take(cx.current.len()) + .collect::(); match cache().paths.get(&it.def_id) { Some(&(ref names, _)) => { for name in names[..names.len() - 1].iter() { @@ -1382,7 +1383,8 @@ impl<'a> fmt::Show for Item<'a> { let amt = if self.ismodule() { cur.len() - 1 } else { cur.len() }; for (i, component) in cur.iter().enumerate().take(amt) { try!(write!(fmt, "{}::", - "../".repeat(cur.len() - i - 1), + repeat("../").take(cur.len() - i - 1) + .collect::(), component.as_slice())); } } diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index e368d7f9332..9a67b479106 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -319,7 +319,7 @@ pub fn unindent(s: &str) -> String { let ignore_previous_indents = saw_first_line && !saw_second_line && - !line.is_whitespace(); + !line.chars().all(|c| c.is_whitespace()); let min_indent = if ignore_previous_indents { uint::MAX @@ -331,7 +331,7 @@ pub fn unindent(s: &str) -> String { saw_second_line = true; } - if line.is_whitespace() { + if line.chars().all(|c| c.is_whitespace()) { min_indent } else { saw_first_line = true; @@ -353,7 +353,7 @@ pub fn unindent(s: &str) -> String { if lines.len() >= 1 { let mut unindented = vec![ lines[0].trim().to_string() ]; unindented.push_all(lines.tail().iter().map(|&line| { - if line.is_whitespace() { + if line.chars().all(|c| c.is_whitespace()) { line.to_string() } else { assert!(line.len() >= min_indent); diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 3181e28a121..c4f071994dc 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -202,10 +202,11 @@ use std::collections::{HashMap, BTreeMap}; use std::{char, f64, fmt, io, num, str}; use std::mem::{swap, transmute}; use std::num::{Float, FPNaN, FPInfinite, Int}; -use std::str::{FromStr, ScalarValue}; +use std::str::{FromStr}; use std::string; -use std::vec::Vec; use std::ops; +use unicode::str as unicode_str; +use unicode::str::Utf16Item; use Encodable; @@ -1001,7 +1002,7 @@ impl Json { /// Returns None otherwise. pub fn as_string<'a>(&'a self) -> Option<&'a str> { match *self { - Json::String(ref s) => Some(s.as_slice()), + Json::String(ref s) => Some(s[]), _ => None } } @@ -1585,8 +1586,8 @@ impl> Parser { } let buf = [n1, try!(self.decode_hex_escape())]; - match str::utf16_items(buf.as_slice()).next() { - Some(ScalarValue(c)) => res.push(c), + match unicode_str::utf16_items(&buf).next() { + Some(Utf16Item::ScalarValue(c)) => res.push(c), _ => return self.error(LoneLeadingSurrogateInHexEscape), } } @@ -1934,7 +1935,7 @@ pub fn from_reader(rdr: &mut io::Reader) -> Result { Ok(c) => c, Err(e) => return Err(io_error_to_error(e)) }; - let s = match str::from_utf8(contents.as_slice()) { + let s = match str::from_utf8(contents.as_slice()).ok() { Some(s) => s, _ => return Err(SyntaxError(NotUtf8, 0, 0)) }; @@ -1970,7 +1971,7 @@ macro_rules! expect { ($e:expr, Null) => ({ match $e { Json::Null => Ok(()), - other => Err(ExpectedError("Null".into_string(), + other => Err(ExpectedError("Null".to_string(), format!("{}", other))) } }); @@ -1991,20 +1992,20 @@ macro_rules! read_primitive { match self.pop() { Json::I64(f) => match num::cast(f) { Some(f) => Ok(f), - None => Err(ExpectedError("Number".into_string(), format!("{}", f))), + None => Err(ExpectedError("Number".to_string(), format!("{}", f))), }, Json::U64(f) => match num::cast(f) { Some(f) => Ok(f), - None => Err(ExpectedError("Number".into_string(), format!("{}", f))), + None => Err(ExpectedError("Number".to_string(), format!("{}", f))), }, - Json::F64(f) => Err(ExpectedError("Integer".into_string(), format!("{}", f))), + Json::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))), // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. Json::String(s) => match std::str::from_str(s.as_slice()) { Some(f) => Ok(f), - None => Err(ExpectedError("Number".into_string(), s)), + None => Err(ExpectedError("Number".to_string(), s)), }, - value => Err(ExpectedError("Number".into_string(), format!("{}", value))), + value => Err(ExpectedError("Number".to_string(), format!("{}", value))), } } } @@ -2036,13 +2037,13 @@ impl ::Decoder for Decoder { Json::String(s) => { // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. - match std::str::from_str(s.as_slice()) { + match s.parse() { Some(f) => Ok(f), - None => Err(ExpectedError("Number".into_string(), s)), + None => Err(ExpectedError("Number".to_string(), s)), } }, Json::Null => Ok(f64::NAN), - value => Err(ExpectedError("Number".into_string(), format!("{}", value))) + value => Err(ExpectedError("Number".to_string(), format!("{}", value))) } } @@ -2060,7 +2061,7 @@ impl ::Decoder for Decoder { _ => () } } - Err(ExpectedError("single character string".into_string(), format!("{}", s))) + Err(ExpectedError("single character string".to_string(), format!("{}", s))) } fn read_str(&mut self) -> DecodeResult { @@ -2080,36 +2081,35 @@ impl ::Decoder for Decoder { let name = match self.pop() { Json::String(s) => s, Json::Object(mut o) => { - let n = match o.remove(&"variant".into_string()) { + let n = match o.remove(&"variant".to_string()) { Some(Json::String(s)) => s, Some(val) => { - return Err(ExpectedError("String".into_string(), format!("{}", val))) + return Err(ExpectedError("String".to_string(), format!("{}", val))) } None => { - return Err(MissingFieldError("variant".into_string())) + return Err(MissingFieldError("variant".to_string())) } }; - match o.remove(&"fields".into_string()) { + match o.remove(&"fields".to_string()) { Some(Json::Array(l)) => { for field in l.into_iter().rev() { self.stack.push(field); } }, Some(val) => { - return Err(ExpectedError("Array".into_string(), format!("{}", val))) + return Err(ExpectedError("Array".to_string(), format!("{}", val))) } None => { - return Err(MissingFieldError("fields".into_string())) + return Err(MissingFieldError("fields".to_string())) } } n } json => { - return Err(ExpectedError("String or Object".into_string(), format!("{}", json))) + return Err(ExpectedError("String or Object".to_string(), format!("{}", json))) } }; - let idx = match names.iter() - .position(|n| str::eq_slice(*n, name.as_slice())) { + let idx = match names.iter().position(|n| *n == name[]) { Some(idx) => idx, None => return Err(UnknownVariantError(name)) }; @@ -2319,7 +2319,7 @@ impl ToJson for bool { } impl ToJson for str { - fn to_json(&self) -> Json { Json::String(self.into_string()) } + fn to_json(&self) -> Json { Json::String(self.to_string()) } } impl ToJson for string::String { @@ -2450,9 +2450,9 @@ mod tests { #[test] fn test_decode_option_malformed() { check_err::("{ \"opt\": [] }", - ExpectedError("Number".into_string(), "[]".into_string())); + ExpectedError("Number".to_string(), "[]".to_string())); check_err::("{ \"opt\": false }", - ExpectedError("Number".into_string(), "false".into_string())); + ExpectedError("Number".to_string(), "false".to_string())); } #[deriving(PartialEq, Encodable, Decodable, Show)] @@ -2538,11 +2538,11 @@ mod tests { #[test] fn test_write_str() { - assert_eq!(String("".into_string()).to_string(), "\"\""); - assert_eq!(String("".into_string()).to_pretty_str(), "\"\""); + assert_eq!(String("".to_string()).to_string(), "\"\""); + assert_eq!(String("".to_string()).to_pretty_str(), "\"\""); - assert_eq!(String("homura".into_string()).to_string(), "\"homura\""); - assert_eq!(String("madoka".into_string()).to_pretty_str(), "\"madoka\""); + assert_eq!(String("homura".to_string()).to_string(), "\"homura\""); + assert_eq!(String("madoka".to_string()).to_pretty_str(), "\"madoka\""); } #[test] @@ -2571,7 +2571,7 @@ mod tests { let long_test_array = Array(vec![ Boolean(false), Null, - Array(vec![String("foo\nbar".into_string()), F64(3.5)])]); + Array(vec![String("foo\nbar".to_string()), F64(3.5)])]); assert_eq!(long_test_array.to_string(), "[false,null,[\"foo\\nbar\",3.5]]"); @@ -2596,12 +2596,12 @@ mod tests { assert_eq!( mk_object(&[ - ("a".into_string(), Boolean(true)) + ("a".to_string(), Boolean(true)) ]).to_string(), "{\"a\":true}" ); assert_eq!( - mk_object(&[("a".into_string(), Boolean(true))]).to_pretty_str(), + mk_object(&[("a".to_string(), Boolean(true))]).to_pretty_str(), "\ {\n \ \"a\": true\n\ @@ -2609,9 +2609,9 @@ mod tests { ); let complex_obj = mk_object(&[ - ("b".into_string(), Array(vec![ - mk_object(&[("c".into_string(), String("\x0c\r".into_string()))]), - mk_object(&[("d".into_string(), String("".into_string()))]) + ("b".to_string(), Array(vec![ + mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))]) ])) ]); @@ -2640,10 +2640,10 @@ mod tests { ); let a = mk_object(&[ - ("a".into_string(), Boolean(true)), - ("b".into_string(), Array(vec![ - mk_object(&[("c".into_string(), String("\x0c\r".into_string()))]), - mk_object(&[("d".into_string(), String("".into_string()))]) + ("a".to_string(), Boolean(true)), + ("b".to_string(), Array(vec![ + mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))]) ])) ]); @@ -2678,7 +2678,7 @@ mod tests { "\"Dog\"" ); - let animal = Frog("Henry".into_string(), 349); + let animal = Frog("Henry".to_string(), 349); assert_eq!( with_str_writer(|writer| { let mut encoder = Encoder::new(writer); @@ -2731,7 +2731,7 @@ mod tests { fn test_write_char() { check_encoder_for_simple!('a', "\"a\""); check_encoder_for_simple!('\t', "\"\\t\""); - check_encoder_for_simple!('\u{00a0}', "\"\u{00a0}\""); + check_encoder_for_simple!('\u{a0}', "\"\u{a0}\""); check_encoder_for_simple!('\u{abcd}', "\"\u{abcd}\""); check_encoder_for_simple!('\u{10ffff}', "\"\u{10ffff}\""); } @@ -2839,7 +2839,7 @@ mod tests { assert_eq!(v, i64::MAX); let res: DecodeResult = super::decode("765.25252"); - assert_eq!(res, Err(ExpectedError("Integer".into_string(), "765.25252".into_string()))); + assert_eq!(res, Err(ExpectedError("Integer".to_string(), "765.25252".to_string()))); } #[test] @@ -2847,16 +2847,16 @@ mod tests { assert_eq!(from_str("\""), Err(SyntaxError(EOFWhileParsingString, 1, 2))); assert_eq!(from_str("\"lol"), Err(SyntaxError(EOFWhileParsingString, 1, 5))); - assert_eq!(from_str("\"\""), Ok(String("".into_string()))); - assert_eq!(from_str("\"foo\""), Ok(String("foo".into_string()))); - assert_eq!(from_str("\"\\\"\""), Ok(String("\"".into_string()))); - assert_eq!(from_str("\"\\b\""), Ok(String("\x08".into_string()))); - assert_eq!(from_str("\"\\n\""), Ok(String("\n".into_string()))); - assert_eq!(from_str("\"\\r\""), Ok(String("\r".into_string()))); - assert_eq!(from_str("\"\\t\""), Ok(String("\t".into_string()))); - assert_eq!(from_str(" \"foo\" "), Ok(String("foo".into_string()))); - assert_eq!(from_str("\"\\u12ab\""), Ok(String("\u{12ab}".into_string()))); - assert_eq!(from_str("\"\\uAB12\""), Ok(String("\u{AB12}".into_string()))); + assert_eq!(from_str("\"\""), Ok(String("".to_string()))); + assert_eq!(from_str("\"foo\""), Ok(String("foo".to_string()))); + assert_eq!(from_str("\"\\\"\""), Ok(String("\"".to_string()))); + assert_eq!(from_str("\"\\b\""), Ok(String("\x08".to_string()))); + assert_eq!(from_str("\"\\n\""), Ok(String("\n".to_string()))); + assert_eq!(from_str("\"\\r\""), Ok(String("\r".to_string()))); + assert_eq!(from_str("\"\\t\""), Ok(String("\t".to_string()))); + assert_eq!(from_str(" \"foo\" "), Ok(String("foo".to_string()))); + assert_eq!(from_str("\"\\u12ab\""), Ok(String("\u{12ab}".to_string()))); + assert_eq!(from_str("\"\\uAB12\""), Ok(String("\u{AB12}".to_string()))); } #[test] @@ -2922,7 +2922,7 @@ mod tests { assert_eq!(t, (1u, 2, 3)); let t: (uint, string::String) = super::decode("[1, \"two\"]").unwrap(); - assert_eq!(t, (1u, "two".into_string())); + assert_eq!(t, (1u, "two".to_string())); } #[test] @@ -2952,22 +2952,22 @@ mod tests { assert_eq!(from_str("{}").unwrap(), mk_object(&[])); assert_eq!(from_str("{\"a\": 3}").unwrap(), - mk_object(&[("a".into_string(), U64(3))])); + mk_object(&[("a".to_string(), U64(3))])); assert_eq!(from_str( "{ \"a\": null, \"b\" : true }").unwrap(), mk_object(&[ - ("a".into_string(), Null), - ("b".into_string(), Boolean(true))])); + ("a".to_string(), Null), + ("b".to_string(), Boolean(true))])); assert_eq!(from_str("\n{ \"a\": null, \"b\" : true }\n").unwrap(), mk_object(&[ - ("a".into_string(), Null), - ("b".into_string(), Boolean(true))])); + ("a".to_string(), Null), + ("b".to_string(), Boolean(true))])); assert_eq!(from_str( "{\"a\" : 1.0 ,\"b\": [ true ]}").unwrap(), mk_object(&[ - ("a".into_string(), F64(1.0)), - ("b".into_string(), Array(vec![Boolean(true)])) + ("a".to_string(), F64(1.0)), + ("b".to_string(), Array(vec![Boolean(true)])) ])); assert_eq!(from_str( "{\ @@ -2979,12 +2979,12 @@ mod tests { ]\ }").unwrap(), mk_object(&[ - ("a".into_string(), F64(1.0)), - ("b".into_string(), Array(vec![ + ("a".to_string(), F64(1.0)), + ("b".to_string(), Array(vec![ Boolean(true), - String("foo\nbar".into_string()), + String("foo\nbar".to_string()), mk_object(&[ - ("c".into_string(), mk_object(&[("d".into_string(), Null)])) + ("c".to_string(), mk_object(&[("d".to_string(), Null)])) ]) ])) ])); @@ -3003,7 +3003,7 @@ mod tests { v, Outer { inner: vec![ - Inner { a: (), b: 2, c: vec!["abc".into_string(), "xyz".into_string()] } + Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] } ] } ); @@ -3029,7 +3029,7 @@ mod tests { assert_eq!(value, None); let value: Option = super::decode("\"jodhpurs\"").unwrap(); - assert_eq!(value, Some("jodhpurs".into_string())); + assert_eq!(value, Some("jodhpurs".to_string())); } #[test] @@ -3039,7 +3039,7 @@ mod tests { let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"; let value: Animal = super::decode(s).unwrap(); - assert_eq!(value, Frog("Henry".into_string(), 349)); + assert_eq!(value, Frog("Henry".to_string(), 349)); } #[test] @@ -3048,8 +3048,8 @@ mod tests { \"fields\":[\"Henry\", 349]}}"; let mut map: BTreeMap = super::decode(s).unwrap(); - assert_eq!(map.remove(&"a".into_string()), Some(Dog)); - assert_eq!(map.remove(&"b".into_string()), Some(Frog("Henry".into_string(), 349))); + assert_eq!(map.remove(&"a".to_string()), Some(Dog)); + assert_eq!(map.remove(&"b".to_string()), Some(Frog("Henry".to_string(), 349))); } #[test] @@ -3089,30 +3089,30 @@ mod tests { } #[test] fn test_decode_errors_struct() { - check_err::("[]", ExpectedError("Object".into_string(), "[]".into_string())); + check_err::("[]", ExpectedError("Object".to_string(), "[]".to_string())); check_err::("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}", - ExpectedError("Number".into_string(), "true".into_string())); + ExpectedError("Number".to_string(), "true".to_string())); check_err::("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}", - ExpectedError("Boolean".into_string(), "[]".into_string())); + ExpectedError("Boolean".to_string(), "[]".to_string())); check_err::("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}", - ExpectedError("String".into_string(), "{}".into_string())); + ExpectedError("String".to_string(), "{}".to_string())); check_err::("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}", - ExpectedError("Array".into_string(), "null".into_string())); + ExpectedError("Array".to_string(), "null".to_string())); check_err::("{\"x\": 1, \"y\": true, \"z\": \"\"}", - MissingFieldError("w".into_string())); + MissingFieldError("w".to_string())); } #[test] fn test_decode_errors_enum() { check_err::("{}", - MissingFieldError("variant".into_string())); + MissingFieldError("variant".to_string())); check_err::("{\"variant\": 1}", - ExpectedError("String".into_string(), "1".into_string())); + ExpectedError("String".to_string(), "1".to_string())); check_err::("{\"variant\": \"A\"}", - MissingFieldError("fields".into_string())); + MissingFieldError("fields".to_string())); check_err::("{\"variant\": \"A\", \"fields\": null}", - ExpectedError("Array".into_string(), "null".into_string())); + ExpectedError("Array".to_string(), "null".to_string())); check_err::("{\"variant\": \"C\", \"fields\": []}", - UnknownVariantError("C".into_string())); + UnknownVariantError("C".to_string())); } #[test] @@ -3325,15 +3325,15 @@ mod tests { let mut tree = BTreeMap::new(); - tree.insert("hello".into_string(), String("guten tag".into_string())); - tree.insert("goodbye".into_string(), String("sayonara".into_string())); + tree.insert("hello".to_string(), String("guten tag".to_string())); + tree.insert("goodbye".to_string(), String("sayonara".to_string())); let json = Array( // The following layout below should look a lot like // the pretty-printed JSON (indent * x) vec! ( // 0x - String("greetings".into_string()), // 1x + String("greetings".to_string()), // 1x Object(tree), // 1x + 2x + 2x + 1x ) // 0x // End JSON array (7 lines) @@ -3397,7 +3397,7 @@ mod tests { }; let mut decoder = Decoder::new(json_obj); let result: Result, DecoderError> = Decodable::decode(&mut decoder); - assert_eq!(result, Err(ExpectedError("Number".into_string(), "a".into_string()))); + assert_eq!(result, Err(ExpectedError("Number".to_string(), "a".to_string()))); } fn assert_stream_equal(src: &str, @@ -3424,7 +3424,7 @@ mod tests { r#"{ "foo":"bar", "array" : [0, 1, 2, 3, 4, 5], "idents":[null,true,false]}"#, vec![ (ObjectStart, vec![]), - (StringValue("bar".into_string()), vec![Key("foo")]), + (StringValue("bar".to_string()), vec![Key("foo")]), (ArrayStart, vec![Key("array")]), (U64Value(0), vec![Key("array"), Index(0)]), (U64Value(1), vec![Key("array"), Index(1)]), @@ -3515,7 +3515,7 @@ mod tests { (F64Value(1.0), vec![Key("a")]), (ArrayStart, vec![Key("b")]), (BooleanValue(true), vec![Key("b"), Index(0)]), - (StringValue("foo\nbar".into_string()), vec![Key("b"), Index(1)]), + (StringValue("foo\nbar".to_string()), vec![Key("b"), Index(1)]), (ObjectStart, vec![Key("b"), Index(2)]), (ObjectStart, vec![Key("b"), Index(2), Key("c")]), (NullValue, vec![Key("b"), Index(2), Key("c"), Key("d")]), @@ -3648,7 +3648,7 @@ mod tests { assert!(stack.last_is_index()); assert!(stack.get(0) == Index(1)); - stack.push_key("foo".into_string()); + stack.push_key("foo".to_string()); assert!(stack.len() == 2); assert!(stack.is_equal_to(&[Index(1), Key("foo")])); @@ -3660,7 +3660,7 @@ mod tests { assert!(stack.get(0) == Index(1)); assert!(stack.get(1) == Key("foo")); - stack.push_key("bar".into_string()); + stack.push_key("bar".to_string()); assert!(stack.len() == 3); assert!(stack.is_equal_to(&[Index(1), Key("foo"), Key("bar")])); @@ -3721,8 +3721,8 @@ mod tests { assert_eq!(f64::NAN.to_json(), Null); assert_eq!(true.to_json(), Boolean(true)); assert_eq!(false.to_json(), Boolean(false)); - assert_eq!("abc".to_json(), String("abc".into_string())); - assert_eq!("abc".into_string().to_json(), String("abc".into_string())); + assert_eq!("abc".to_json(), String("abc".to_string())); + assert_eq!("abc".to_string().to_json(), String("abc".to_string())); assert_eq!((1u, 2u).to_json(), array2); assert_eq!((1u, 2u, 3u).to_json(), array3); assert_eq!([1u, 2].to_json(), array2); @@ -3734,8 +3734,8 @@ mod tests { tree_map.insert("b".into_string(), 2); assert_eq!(tree_map.to_json(), object); let mut hash_map = HashMap::new(); - hash_map.insert("a".into_string(), 1u); - hash_map.insert("b".into_string(), 2); + hash_map.insert("a".to_string(), 1u); + hash_map.insert("b".to_string(), 2); assert_eq!(hash_map.to_json(), object); assert_eq!(Some(15i).to_json(), I64(15)); assert_eq!(Some(15u).to_json(), U64(15)); @@ -3778,7 +3778,7 @@ mod tests { } fn big_json() -> string::String { - let mut src = "[\n".into_string(); + let mut src = "[\n".to_string(); for _ in range(0i, 500) { src.push_str(r#"{ "a": true, "b": null, "c":3.1415, "d": "Hello world", "e": \ [1,2,3]},"#); diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index e700d102fef..fdbc5051f72 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -32,6 +32,7 @@ extern crate test; #[phase(plugin, link)] extern crate log; +extern crate unicode; extern crate collections; diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 00c5158309e..558f9e603e1 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -308,13 +308,13 @@ impl> Encodable for str { impl> Encodable for String { fn encode(&self, s: &mut S) -> Result<(), E> { - s.emit_str(self.as_slice()) + s.emit_str(self[]) } } impl> Decodable for String { fn decode(d: &mut D) -> Result { - Ok(String::from_str(try!(d.read_str()).as_slice())) + d.read_str() } } diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 08b17f25e29..2c49beca98d 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -23,7 +23,7 @@ use ops::FnMut; use option::Option; use option::Option::{Some, None}; use slice::{SliceExt, AsSlice}; -use str::{Str, StrPrelude}; +use str::{Str, StrExt}; use string::{String, IntoString}; use vec::Vec; diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index f1c8e8950a2..fb44961017f 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -228,7 +228,7 @@ impl CString { #[inline] pub fn as_str<'a>(&'a self) -> Option<&'a str> { let buf = self.as_bytes_no_nul(); - str::from_utf8(buf) + str::from_utf8(buf).ok() } /// Return a CString iterator. diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 4d8c7d67b8c..368abe7cb12 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -280,7 +280,7 @@ pub mod dl { use result::Result; use result::Result::{Ok, Err}; use slice::SliceExt; - use str::StrPrelude; + use str::StrExt; use str; use string::String; use vec::Vec; diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs index 8e1e3dc4af9..7010eae6dba 100644 --- a/src/libstd/failure.rs +++ b/src/libstd/failure.rs @@ -41,7 +41,7 @@ pub fn on_fail(obj: &(Any+Send), file: &'static str, line: uint) { let msg = match obj.downcast_ref::<&'static str>() { Some(s) => *s, None => match obj.downcast_ref::() { - Some(s) => s.as_slice(), + Some(s) => s[], None => "Box", } }; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index dbf61b132e0..233ad781093 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -242,10 +242,11 @@ use result::Result; use result::Result::{Ok, Err}; use sys; use slice::SliceExt; -use str::StrPrelude; +use str::StrExt; use str; use string::String; use uint; +use unicode; use unicode::char::UnicodeChar; use vec::Vec; @@ -1505,7 +1506,7 @@ pub trait Buffer: Reader { /// valid utf-8 encoded codepoint as the next few bytes in the stream. fn read_char(&mut self) -> IoResult { let first_byte = try!(self.read_byte()); - let width = str::utf8_char_width(first_byte); + let width = unicode::str::utf8_char_width(first_byte); if width == 1 { return Ok(first_byte as char) } if width == 0 { return Err(standard_error(InvalidInput)) } // not utf8 let mut buf = [first_byte, 0, 0, 0]; @@ -1519,7 +1520,7 @@ pub trait Buffer: Reader { } } } - match str::from_utf8(buf[..width]) { + match str::from_utf8(buf[..width]).ok() { Some(s) => Ok(s.char_at(0)), None => Err(standard_error(InvalidInput)) } diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index 71776b6c46a..89a649d55bd 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -25,8 +25,8 @@ use ops::FnOnce; use option::Option; use option::Option::{None, Some}; use result::Result::{Ok, Err}; -use str::{FromStr, StrPrelude}; use slice::{CloneSliceExt, SliceExt}; +use str::{FromStr, StrExt}; use vec::Vec; pub type Port = u16; diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 9da1117f227..4a0a3936424 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -1082,7 +1082,7 @@ mod tests { let prog = env_cmd().env_set_all(new_env.as_slice()).spawn().unwrap(); let result = prog.wait_with_output().unwrap(); - let output = String::from_utf8_lossy(result.output.as_slice()).into_string(); + let output = String::from_utf8_lossy(result.output.as_slice()).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); @@ -1092,7 +1092,7 @@ mod tests { fn test_add_to_env() { let prog = env_cmd().env("RUN_TEST_NEW_ENV", "123").spawn().unwrap(); let result = prog.wait_with_output().unwrap(); - let output = String::from_utf8_lossy(result.output.as_slice()).into_string(); + let output = String::from_utf8_lossy(result.output.as_slice()).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 36dd5492356..1c5ceaf2450 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -43,7 +43,7 @@ use ops::{Deref, DerefMut, FnOnce}; use result::Result::{Ok, Err}; use rt; use slice::SliceExt; -use str::StrPrelude; +use str::StrExt; use string::String; use sys::{fs, tty}; use sync::{Arc, Mutex, MutexGuard, Once, ONCE_INIT}; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index b3e4dd52f89..d6331f3c718 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -20,7 +20,7 @@ use char::{mod, Char}; use num::{mod, Int, Float, FPNaN, FPInfinite, ToPrimitive}; use ops::FnMut; use slice::{SliceExt, CloneSliceExt}; -use str::StrPrelude; +use str::StrExt; use string::String; use vec::Vec; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index a16ee982f5c..ceb9a4102f6 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -52,7 +52,7 @@ use result::Result; use result::Result::{Err, Ok}; use slice::{AsSlice, SliceExt}; use slice::CloneSliceExt; -use str::{Str, StrPrelude, StrAllocating}; +use str::{Str, StrExt}; use string::{String, ToString}; use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; use vec::Vec; @@ -134,8 +134,8 @@ fn with_env_lock(f: F) -> T where /// ``` pub fn env() -> Vec<(String,String)> { env_as_bytes().into_iter().map(|(k,v)| { - let k = String::from_utf8_lossy(k.as_slice()).into_string(); - let v = String::from_utf8_lossy(v.as_slice()).into_string(); + let k = String::from_utf8_lossy(k.as_slice()).into_owned(); + let v = String::from_utf8_lossy(v.as_slice()).into_owned(); (k,v) }).collect() } @@ -185,7 +185,7 @@ pub fn env_as_bytes() -> Vec<(Vec,Vec)> { /// } /// ``` pub fn getenv(n: &str) -> Option { - getenv_as_bytes(n).map(|v| String::from_utf8_lossy(v.as_slice()).into_string()) + getenv_as_bytes(n).map(|v| String::from_utf8_lossy(v.as_slice()).into_owned()) } #[cfg(unix)] @@ -707,7 +707,7 @@ fn real_args_as_bytes() -> Vec> { fn real_args() -> Vec { real_args_as_bytes().into_iter() .map(|v| { - String::from_utf8_lossy(v.as_slice()).into_string() + String::from_utf8_lossy(v.as_slice()).into_owned() }).collect() } @@ -729,7 +729,7 @@ fn real_args() -> Vec { // Push it onto the list. let ptr = ptr as *const u16; let buf = slice::from_raw_buf(&ptr, len); - let opt_s = String::from_utf16(os_imp::truncate_utf16_at_nul(buf)); + let opt_s = String::from_utf16(sys::os::truncate_utf16_at_nul(buf)); opt_s.expect("CommandLineToArgvW returned invalid UTF-16") }); diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index ed4bb6ee081..30f3f56bc1c 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -69,7 +69,7 @@ use iter::IteratorExt; use option::Option; use option::Option::{None, Some}; use str; -use str::{CowString, MaybeOwned, Str, StrPrelude}; +use str::{CowString, MaybeOwned, Str, StrExt}; use string::String; use slice::{AsSlice, CloneSliceExt}; use slice::{PartialEqSliceExt, SliceExt}; @@ -197,7 +197,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// ``` #[inline] fn as_str<'a>(&'a self) -> Option<&'a str> { - str::from_utf8(self.as_vec()) + str::from_utf8(self.as_vec()).ok() } /// Returns the path as a byte vector @@ -293,7 +293,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// ``` #[inline] fn dirname_str<'a>(&'a self) -> Option<&'a str> { - str::from_utf8(self.dirname()) + str::from_utf8(self.dirname()).ok() } /// Returns the file component of `self`, as a byte vector. @@ -327,7 +327,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// ``` #[inline] fn filename_str<'a>(&'a self) -> Option<&'a str> { - self.filename().and_then(str::from_utf8) + self.filename().and_then(|s| str::from_utf8(s).ok()) } /// Returns the stem of the filename of `self`, as a byte vector. @@ -373,7 +373,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// ``` #[inline] fn filestem_str<'a>(&'a self) -> Option<&'a str> { - self.filestem().and_then(str::from_utf8) + self.filestem().and_then(|s| str::from_utf8(s).ok()) } /// Returns the extension of the filename of `self`, as an optional byte vector. @@ -420,7 +420,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// ``` #[inline] fn extension_str<'a>(&'a self) -> Option<&'a str> { - self.extension().and_then(str::from_utf8) + self.extension().and_then(|s| str::from_utf8(s).ok()) } /// Replaces the filename portion of the path with the given byte vector or string. @@ -793,7 +793,7 @@ pub trait BytesContainer for Sized? { /// Returns the receiver interpreted as a utf-8 string, if possible #[inline] fn container_as_str<'a>(&'a self) -> Option<&'a str> { - str::from_utf8(self.container_as_bytes()) + str::from_utf8(self.container_as_bytes()).ok() } /// Returns whether .container_as_str() is guaranteed to not fail // FIXME (#8888): Remove unused arg once :: works @@ -870,7 +870,7 @@ impl BytesContainer for String { } #[inline] fn container_as_str(&self) -> Option<&str> { - Some(self.as_slice()) + Some(self[]) } #[inline] fn is_str(_: Option<&String>) -> bool { true } @@ -886,7 +886,7 @@ impl BytesContainer for [u8] { impl BytesContainer for Vec { #[inline] fn container_as_bytes(&self) -> &[u8] { - self.as_slice() + self[] } } @@ -897,6 +897,7 @@ impl BytesContainer for CString { } } +#[allow(deprecated)] impl<'a> BytesContainer for str::MaybeOwned<'a> { #[inline] fn container_as_bytes<'b>(&'b self) -> &'b [u8] { diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 88907951673..a514837492a 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -401,7 +401,10 @@ impl Path { /// Returns an iterator that yields each component of the path as Option<&str>. /// See components() for details. pub fn str_components<'a>(&'a self) -> StrComponents<'a> { - self.components().map(str::from_utf8) + fn from_utf8(s: &[u8]) -> Option<&str> { + str::from_utf8(s).ok() + } + self.components().map(from_utf8) } } diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index c2c17103554..277c675c22d 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -25,9 +25,9 @@ use iter::{Iterator, IteratorExt, Map}; use mem; use option::Option; use option::Option::{Some, None}; -use slice::{AsSlice, SliceExt}; -use str::{CharSplits, FromStr, Str, StrAllocating, StrVector, StrPrelude}; -use string::String; +use slice::SliceExt; +use str::{CharSplits, FromStr, StrVector, StrExt}; +use string::{String, ToString}; use unicode::char::UnicodeChar; use vec::Vec; @@ -187,30 +187,30 @@ impl GenericPathUnsafe for Path { s.push_str(".."); s.push(SEP); s.push_str(filename); - self.update_normalized(s); + self.update_normalized(s[]); } None => { self.update_normalized(filename); } - Some((_,idxa,end)) if self.repr.slice(idxa,end) == ".." => { + Some((_,idxa,end)) if self.repr[idxa..end] == ".." => { let mut s = String::with_capacity(end + 1 + filename.len()); - s.push_str(self.repr.slice_to(end)); + s.push_str(self.repr[0..end]); s.push(SEP); s.push_str(filename); - self.update_normalized(s); + self.update_normalized(s[]); } Some((idxb,idxa,_)) if self.prefix == Some(DiskPrefix) && idxa == self.prefix_len() => { let mut s = String::with_capacity(idxb + filename.len()); - s.push_str(self.repr.slice_to(idxb)); + s.push_str(self.repr[0..idxb]); s.push_str(filename); - self.update_normalized(s); + self.update_normalized(s[]); } Some((idxb,_,_)) => { let mut s = String::with_capacity(idxb + 1 + filename.len()); - s.push_str(self.repr.slice_to(idxb)); + s.push_str(self.repr[0..idxb]); s.push(SEP); s.push_str(filename); - self.update_normalized(s); + self.update_normalized(s[]); } } } @@ -229,12 +229,12 @@ impl GenericPathUnsafe for Path { let path = path.container_as_str().unwrap(); fn is_vol_abs(path: &str, prefix: Option) -> bool { // assume prefix is Some(DiskPrefix) - let rest = path.slice_from(prefix_len(prefix)); + let rest = path[prefix_len(prefix)..]; !rest.is_empty() && rest.as_bytes()[0].is_ascii() && is_sep(rest.as_bytes()[0] as char) } fn shares_volume(me: &Path, path: &str) -> bool { // path is assumed to have a prefix of Some(DiskPrefix) - let repr = me.repr.as_slice(); + let repr = me.repr[]; match me.prefix { Some(DiskPrefix) => { repr.as_bytes()[0] == path.as_bytes()[0].to_ascii().to_uppercase().as_byte() @@ -266,7 +266,7 @@ impl GenericPathUnsafe for Path { else { None }; let pathlen = path_.as_ref().map_or(path.len(), |p| p.len()); let mut s = String::with_capacity(me.repr.len() + 1 + pathlen); - s.push_str(me.repr.as_slice()); + s.push_str(me.repr[]); let plen = me.prefix_len(); // if me is "C:" we don't want to add a path separator match me.prefix { @@ -278,9 +278,9 @@ impl GenericPathUnsafe for Path { } match path_ { None => s.push_str(path), - Some(p) => s.push_str(p.as_slice()) + Some(p) => s.push_str(p[]), }; - me.update_normalized(s) + me.update_normalized(s[]) } if !path.is_empty() { @@ -288,7 +288,7 @@ impl GenericPathUnsafe for Path { match prefix { Some(DiskPrefix) if !is_vol_abs(path, prefix) && shares_volume(self, path) => { // cwd-relative path, self is on the same volume - append_path(self, path.slice_from(prefix_len(prefix))); + append_path(self, path[prefix_len(prefix)..]); } Some(_) => { // absolute path, or cwd-relative and self is not same volume @@ -334,7 +334,7 @@ impl GenericPath for Path { /// Always returns a `Some` value. #[inline] fn as_str<'a>(&'a self) -> Option<&'a str> { - Some(self.repr.as_slice()) + Some(self.repr[]) } #[inline] @@ -356,21 +356,17 @@ impl GenericPath for Path { /// Always returns a `Some` value. fn dirname_str<'a>(&'a self) -> Option<&'a str> { Some(match self.sepidx_or_prefix_len() { - None if ".." == self.repr => self.repr.as_slice(), + None if ".." == self.repr => self.repr[], None => ".", - Some((_,idxa,end)) if self.repr.slice(idxa, end) == ".." => { - self.repr.as_slice() - } - Some((idxb,_,end)) if self.repr.slice(idxb, end) == "\\" => { - self.repr.as_slice() - } - Some((0,idxa,_)) => self.repr.slice_to(idxa), + Some((_,idxa,end)) if self.repr[idxa..end] == ".." => self.repr[], + Some((idxb,_,end)) if self.repr[idxb..end] == "\\" => self.repr[], + Some((0,idxa,_)) => self.repr[0..idxa], Some((idxb,idxa,_)) => { match self.prefix { Some(DiskPrefix) | Some(VerbatimDiskPrefix) if idxb == self.prefix_len() => { - self.repr.slice_to(idxa) + self.repr[0..idxa] } - _ => self.repr.slice_to(idxb) + _ => self.repr[0..idxb] } } }) @@ -384,13 +380,13 @@ impl GenericPath for Path { /// See `GenericPath::filename_str` for info. /// Always returns a `Some` value if `filename` returns a `Some` value. fn filename_str<'a>(&'a self) -> Option<&'a str> { - let repr = self.repr.as_slice(); + let repr = self.repr[]; match self.sepidx_or_prefix_len() { None if "." == repr || ".." == repr => None, None => Some(repr), - Some((_,idxa,end)) if repr.slice(idxa, end) == ".." => None, + Some((_,idxa,end)) if repr[idxa..end] == ".." => None, Some((_,idxa,end)) if idxa == end => None, - Some((_,idxa,end)) => Some(repr.slice(idxa, end)) + Some((_,idxa,end)) => Some(repr[idxa..end]) } } @@ -422,7 +418,7 @@ impl GenericPath for Path { true } Some((idxb,idxa,end)) if idxb == idxa && idxb == end => false, - Some((idxb,_,end)) if self.repr.slice(idxb, end) == "\\" => false, + Some((idxb,_,end)) if self.repr[idxb..end] == "\\" => false, Some((idxb,idxa,_)) => { let trunc = match self.prefix { Some(DiskPrefix) | Some(VerbatimDiskPrefix) | None => { @@ -442,15 +438,15 @@ impl GenericPath for Path { if self.prefix.is_some() { Some(Path::new(match self.prefix { Some(DiskPrefix) if self.is_absolute() => { - self.repr.slice_to(self.prefix_len()+1) + self.repr[0..self.prefix_len()+1] } Some(VerbatimDiskPrefix) => { - self.repr.slice_to(self.prefix_len()+1) + self.repr[0..self.prefix_len()+1] } - _ => self.repr.slice_to(self.prefix_len()) + _ => self.repr[0..self.prefix_len()] })) } else if is_vol_relative(self) { - Some(Path::new(self.repr.slice_to(1))) + Some(Path::new(self.repr[0..1])) } else { None } @@ -469,7 +465,7 @@ impl GenericPath for Path { fn is_absolute(&self) -> bool { match self.prefix { Some(DiskPrefix) => { - let rest = self.repr.slice_from(self.prefix_len()); + let rest = self.repr[self.prefix_len()..]; rest.len() > 0 && rest.as_bytes()[0] == SEP_BYTE } Some(_) => true, @@ -644,15 +640,15 @@ impl Path { /// Does not distinguish between absolute and cwd-relative paths, e.g. /// C:\foo and C:foo. pub fn str_components<'a>(&'a self) -> StrComponents<'a> { - let repr = self.repr.as_slice(); + let repr = self.repr[]; let s = match self.prefix { Some(_) => { let plen = self.prefix_len(); if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE { - repr.slice_from(plen+1) - } else { repr.slice_from(plen) } + repr[plen+1..] + } else { repr[plen..] } } - None if repr.as_bytes()[0] == SEP_BYTE => repr.slice_from(1), + None if repr.as_bytes()[0] == SEP_BYTE => repr[1..], None => repr }; let ret = s.split_terminator(SEP).map(Some); @@ -670,8 +666,8 @@ impl Path { } fn equiv_prefix(&self, other: &Path) -> bool { - let s_repr = self.repr.as_slice(); - let o_repr = other.repr.as_slice(); + let s_repr = self.repr[]; + let o_repr = other.repr[]; match (self.prefix, other.prefix) { (Some(DiskPrefix), Some(VerbatimDiskPrefix)) => { self.is_absolute() && @@ -688,28 +684,28 @@ impl Path { o_repr.as_bytes()[4].to_ascii().to_lowercase() } (Some(UNCPrefix(_,_)), Some(VerbatimUNCPrefix(_,_))) => { - s_repr.slice(2, self.prefix_len()) == o_repr.slice(8, other.prefix_len()) + s_repr[2..self.prefix_len()] == o_repr[8..other.prefix_len()] } (Some(VerbatimUNCPrefix(_,_)), Some(UNCPrefix(_,_))) => { - s_repr.slice(8, self.prefix_len()) == o_repr.slice(2, other.prefix_len()) + s_repr[8..self.prefix_len()] == o_repr[2..other.prefix_len()] } (None, None) => true, (a, b) if a == b => { - s_repr.slice_to(self.prefix_len()) == o_repr.slice_to(other.prefix_len()) + s_repr[0..self.prefix_len()] == o_repr[0..other.prefix_len()] } _ => false } } - fn normalize_(s: S) -> (Option, String) { + fn normalize_(s: &str) -> (Option, String) { // make borrowck happy let (prefix, val) = { - let prefix = parse_prefix(s.as_slice()); - let path = Path::normalize__(s.as_slice(), prefix); + let prefix = parse_prefix(s); + let path = Path::normalize__(s, prefix); (prefix, path) }; (prefix, match val { - None => s.into_string(), + None => s.to_string(), Some(val) => val }) } @@ -749,7 +745,7 @@ impl Path { match prefix.unwrap() { DiskPrefix => { let len = prefix_len(prefix) + is_abs as uint; - let mut s = String::from_str(s.slice_to(len)); + let mut s = String::from_str(s[0..len]); unsafe { let v = s.as_mut_vec(); v[0] = (*v)[0].to_ascii().to_uppercase().as_byte(); @@ -764,7 +760,7 @@ impl Path { } VerbatimDiskPrefix => { let len = prefix_len(prefix) + is_abs as uint; - let mut s = String::from_str(s.slice_to(len)); + let mut s = String::from_str(s[0..len]); unsafe { let v = s.as_mut_vec(); v[4] = (*v)[4].to_ascii().to_uppercase().as_byte(); @@ -774,14 +770,14 @@ impl Path { _ => { let plen = prefix_len(prefix); if s.len() > plen { - Some(String::from_str(s.slice_to(plen))) + Some(String::from_str(s[0..plen])) } else { None } } } } else if is_abs && comps.is_empty() { Some(String::from_char(1, SEP)) } else { - let prefix_ = s.slice_to(prefix_len(prefix)); + let prefix_ = s[0..prefix_len(prefix)]; let n = prefix_.len() + if is_abs { comps.len() } else { comps.len() - 1} + comps.iter().map(|v| v.len()).sum(); @@ -793,16 +789,16 @@ impl Path { s.push(':'); } Some(VerbatimDiskPrefix) => { - s.push_str(prefix_.slice_to(4)); + s.push_str(prefix_[0..4]); s.push(prefix_.as_bytes()[4].to_ascii() .to_uppercase().as_char()); - s.push_str(prefix_.slice_from(5)); + s.push_str(prefix_[5..]); } Some(UNCPrefix(a,b)) => { s.push_str("\\\\"); - s.push_str(prefix_.slice(2, a+2)); + s.push_str(prefix_[2..a+2]); s.push(SEP); - s.push_str(prefix_.slice(3+a, 3+a+b)); + s.push_str(prefix_[3+a..3+a+b]); } Some(_) => s.push_str(prefix_), None => () @@ -827,8 +823,8 @@ impl Path { fn update_sepidx(&mut self) { let s = if self.has_nonsemantic_trailing_slash() { - self.repr.slice_to(self.repr.len()-1) - } else { self.repr.as_slice() }; + self.repr[0..self.repr.len()-1] + } else { self.repr[] }; let idx = s.rfind(if !prefix_is_verbatim(self.prefix) { is_sep } else { is_sep_verbatim }); let prefixlen = self.prefix_len(); @@ -860,8 +856,8 @@ impl Path { self.repr.as_bytes()[self.repr.len()-1] == SEP_BYTE } - fn update_normalized(&mut self, s: S) { - let (prefix, path) = Path::normalize_(s.as_slice()); + fn update_normalized(&mut self, s: &str) { + let (prefix, path) = Path::normalize_(s); self.repr = path; self.prefix = prefix; self.update_sepidx(); @@ -903,17 +899,17 @@ pub fn is_verbatim(path: &Path) -> bool { /// non-verbatim, the non-verbatim version is returned. /// Otherwise, None is returned. pub fn make_non_verbatim(path: &Path) -> Option { - let repr = path.repr.as_slice(); + let repr = path.repr[]; let new_path = match path.prefix { Some(VerbatimPrefix(_)) | Some(DeviceNSPrefix(_)) => return None, Some(UNCPrefix(_,_)) | Some(DiskPrefix) | None => return Some(path.clone()), Some(VerbatimDiskPrefix) => { // \\?\D:\ - Path::new(repr.slice_from(4)) + Path::new(repr[4..]) } Some(VerbatimUNCPrefix(_,_)) => { // \\?\UNC\server\share - Path::new(format!(r"\{}", repr.slice_from(7))) + Path::new(format!(r"\{}", repr[7..])) } }; if new_path.prefix.is_none() { @@ -922,8 +918,8 @@ pub fn make_non_verbatim(path: &Path) -> Option { return None; } // now ensure normalization didn't change anything - if repr.slice_from(path.prefix_len()) == - new_path.repr.slice_from(new_path.prefix_len()) { + if repr[path.prefix_len()..] == + new_path.repr[new_path.prefix_len()..] { Some(new_path) } else { None @@ -988,13 +984,13 @@ pub enum PathPrefix { fn parse_prefix<'a>(mut path: &'a str) -> Option { if path.starts_with("\\\\") { // \\ - path = path.slice_from(2); + path = path[2..]; if path.starts_with("?\\") { // \\?\ - path = path.slice_from(2); + path = path[2..]; if path.starts_with("UNC\\") { // \\?\UNC\server\share - path = path.slice_from(4); + path = path[4..]; let (idx_a, idx_b) = match parse_two_comps(path, is_sep_verbatim) { Some(x) => x, None => (path.len(), 0) @@ -1015,7 +1011,7 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option { } } else if path.starts_with(".\\") { // \\.\path - path = path.slice_from(2); + path = path[2..]; let idx = path.find('\\').unwrap_or(path.len()); return Some(DeviceNSPrefix(idx)); } @@ -1040,7 +1036,7 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option { None => return None, Some(x) => x }; - path = path.slice_from(idx_a+1); + path = path[idx_a+1..]; let idx_b = path.find(f).unwrap_or(path.len()); Some((idx_a, idx_b)) } @@ -1050,8 +1046,8 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option { fn normalize_helper<'a>(s: &'a str, prefix: Option) -> (bool, Option>) { let f = if !prefix_is_verbatim(prefix) { is_sep } else { is_sep_verbatim }; let is_abs = s.len() > prefix_len(prefix) && f(s.char_at(prefix_len(prefix))); - let s_ = s.slice_from(prefix_len(prefix)); - let s_ = if is_abs { s_.slice_from(1) } else { s_ }; + let s_ = s[prefix_len(prefix)..]; + let s_ = if is_abs { s_[1..] } else { s_ }; if is_abs && s_.is_empty() { return (is_abs, match prefix { diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index f77627711a7..49b888d17f4 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -79,11 +79,11 @@ #[doc(no_inline)] pub use result::Result; #[doc(no_inline)] pub use result::Result::{Ok, Err}; #[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude}; -#[doc(no_inline)] pub use str::{Str, StrVector, StrPrelude}; -#[doc(no_inline)] pub use str::{StrAllocating, UnicodeStrPrelude}; #[doc(no_inline)] pub use core::prelude::{Tuple1, Tuple2, Tuple3, Tuple4}; #[doc(no_inline)] pub use core::prelude::{Tuple5, Tuple6, Tuple7, Tuple8}; #[doc(no_inline)] pub use core::prelude::{Tuple9, Tuple10, Tuple11, Tuple12}; +#[doc(no_inline)] pub use str::{Str, StrVector}; +#[doc(no_inline)] pub use str::StrExt; #[doc(no_inline)] pub use slice::AsSlice; #[doc(no_inline)] pub use slice::{VectorVector, PartialEqSliceExt}; #[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt, SliceExt}; diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 4a692bccf9e..775e9bb526f 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -12,7 +12,8 @@ #![allow(non_camel_case_types)] -use option::Option::{Some, None}; +use prelude::*; + use os; use sync::atomic; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 8d9c1268e7e..d64336569c6 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -91,7 +91,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { // created. Note that this isn't necessary in general for new threads, // but we just do this to name the main thread and to give it correct // info about the stack bounds. - let thread: Thread = NewThread::new(Some("
".into_string())); + let thread: Thread = NewThread::new(Some("
".to_string())); thread_info::set((my_stack_bottom, my_stack_top), sys::thread::guard::main(), thread); diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index f572141642c..eb15a7ba378 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -512,7 +512,7 @@ pub fn begin_unwind_fmt(msg: &fmt::Arguments, file_line: &(&'static str, uint)) let mut v = Vec::new(); let _ = write!(&mut VecWriter { v: &mut v }, "{}", msg); - let msg = box String::from_utf8_lossy(v.as_slice()).into_string(); + let msg = box String::from_utf8_lossy(v.as_slice()).into_owned(); begin_unwind_inner(msg, file_line) } diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 77500ca74d0..d8cd8455deb 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -10,16 +10,16 @@ // // ignore-lexer-test FIXME #15677 -use core::prelude::*; +use prelude::*; -use core::cmp; -use core::fmt; -use core::intrinsics; -use core::slice; -use core::str; - -use libc::{mod, uintptr_t}; +use cmp; +use fmt; +use intrinsics; +use libc::uintptr_t; +use libc; use os; +use slice; +use str; use sync::atomic; /// Dynamically inquire about whether we're running under V. @@ -52,7 +52,7 @@ pub fn min_stack() -> uint { 0 => {} n => return n - 1, } - let amt = os::getenv("RUST_MIN_STACK").and_then(|s| from_str(s.as_slice())); + let amt = os::getenv("RUST_MIN_STACK").and_then(|s| s.parse()); let amt = amt.unwrap_or(2 * 1024 * 1024); // 0 is our sentinel value, so ensure that we'll never see 0 after // initialization has run @@ -65,7 +65,7 @@ pub fn min_stack() -> uint { pub fn default_sched_threads() -> uint { match os::getenv("RUST_THREADS") { Some(nstr) => { - let opt_n: Option = from_str(nstr.as_slice()); + let opt_n: Option = nstr.parse(); match opt_n { Some(n) if n > 0 => n, _ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr) @@ -113,9 +113,8 @@ impl fmt::FormatWriter for Stdio { } pub fn dumb_print(args: &fmt::Arguments) { - use fmt::FormatWriter; let mut w = Stderr; - let _ = w.write_fmt(args); + let _ = write!(&mut w, "{}", args); } pub fn abort(args: &fmt::Arguments) -> ! { diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index a39c8d6d8fe..1d646eb06b1 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -8,12 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use io::{IoResult, Writer}; -use iter::{Iterator, IteratorExt}; -use option::Option::{Some, None}; -use result::Result::{Ok, Err}; -use str::{StrPrelude, from_str}; -use unicode::char::UnicodeChar; +use prelude::*; + +use io::IoResult; #[cfg(target_word_size = "64")] pub const HEX_WIDTH: uint = 18; #[cfg(target_word_size = "32")] pub const HEX_WIDTH: uint = 10; @@ -85,7 +82,7 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { while rest.char_at(0).is_numeric() { rest = rest.slice_from(1); } - let i: uint = from_str(inner.slice_to(inner.len() - rest.len())).unwrap(); + let i: uint = inner.slice_to(inner.len() - rest.len()).parse().unwrap(); inner = rest.slice_from(i); rest = rest.slice_to(i); while rest.len() > 0 { diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index f2f543dd969..42c8f7705e1 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -32,7 +32,7 @@ use path::Path; use result::Result::{Ok, Err}; use sync::{StaticMutex, MUTEX_INIT}; use slice::SliceExt; -use str::StrPrelude; +use str::StrExt; use dynamic_lib::DynamicLibrary; use sys_common::backtrace::*; diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index d5bf8c5b629..15eddd569be 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -23,6 +23,7 @@ use io; use prelude::*; use sys; +use sys::os; use sys_common::{keep_going, eof, mkerr_libc}; use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode}; @@ -262,7 +263,7 @@ pub fn readdir(p: &Path) -> IoResult> { let mut more_files = 1 as libc::BOOL; while more_files != 0 { { - let filename = str::truncate_utf16_at_nul(&wfd.cFileName); + let filename = os::truncate_utf16_at_nul(&wfd.cFileName); match String::from_utf16(filename) { Some(filename) => paths.push(Path::new(filename)), None => { diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index e1016048e58..e007b46b261 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -168,7 +168,7 @@ pub fn getcwd() -> IoResult { } } - match String::from_utf16(::str::truncate_utf16_at_nul(&buf)) { + match String::from_utf16(truncate_utf16_at_nul(&buf)) { Some(ref cwd) => Ok(Path::new(cwd)), None => Err(IoError { kind: OtherIoError, @@ -279,7 +279,7 @@ pub fn load_self() -> Option> { unsafe { fill_utf16_buf_and_decode(|buf, sz| { libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz) - }).map(|s| s.into_string().into_bytes()) + }).map(|s| s.to_string().into_bytes()) } } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 8945c155e66..0c2c76077dd 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -122,7 +122,7 @@ impl Process { use mem; use iter::{Iterator, IteratorExt}; - use str::StrPrelude; + use str::StrExt; if cfg.gid().is_some() || cfg.uid().is_some() { return Err(IoError { diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index 51679bb2003..f793de5bb57 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -111,7 +111,7 @@ impl TTY { } pub fn write(&mut self, buf: &[u8]) -> IoResult<()> { - let utf16 = match from_utf8(buf) { + let utf16 = match from_utf8(buf).ok() { Some(utf8) => { utf8.utf16_units().collect::>() } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a294706ef2c..3eea5b27f19 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -189,7 +189,7 @@ impl, E> Encodable for Ident { impl, E> Decodable for Ident { fn decode(d: &mut D) -> Result { - Ok(str_to_ident(try!(d.read_str()).as_slice())) + Ok(str_to_ident(try!(d.read_str())[])) } } diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index a95c9e19906..e3eeb453c26 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -95,7 +95,7 @@ pub fn path_to_string>(path: PI) -> String { if !s.is_empty() { s.push_str("::"); } - s.push_str(e.as_slice()); + s.push_str(e[]); s }).to_string() } @@ -472,20 +472,20 @@ impl<'ast> Map<'ast> { F: FnOnce(Option<&[Attribute]>) -> T, { let attrs = match self.get(id) { - NodeItem(i) => Some(i.attrs.as_slice()), - NodeForeignItem(fi) => Some(fi.attrs.as_slice()), + NodeItem(i) => Some(i.attrs[]), + NodeForeignItem(fi) => Some(fi.attrs[]), NodeTraitItem(ref tm) => match **tm { - RequiredMethod(ref type_m) => Some(type_m.attrs.as_slice()), - ProvidedMethod(ref m) => Some(m.attrs.as_slice()), - TypeTraitItem(ref typ) => Some(typ.attrs.as_slice()), + RequiredMethod(ref type_m) => Some(type_m.attrs[]), + ProvidedMethod(ref m) => Some(m.attrs[]), + TypeTraitItem(ref typ) => Some(typ.attrs[]), }, NodeImplItem(ref ii) => { match **ii { - MethodImplItem(ref m) => Some(m.attrs.as_slice()), - TypeImplItem(ref t) => Some(t.attrs.as_slice()), + MethodImplItem(ref m) => Some(m.attrs[]), + TypeImplItem(ref t) => Some(t.attrs[]), } } - NodeVariant(ref v) => Some(v.node.attrs.as_slice()), + NodeVariant(ref v) => Some(v.node.attrs[]), // unit/tuple structs take the attributes straight from // the struct definition. // FIXME(eddyb) make this work again (requires access to the map). @@ -504,8 +504,8 @@ impl<'ast> Map<'ast> { /// the iterator will produce node id's for items with paths /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and /// any other such items it can find in the map. - pub fn nodes_matching_suffix<'a, S:Str>(&'a self, parts: &'a [S]) - -> NodesMatchingSuffix<'a, 'ast, S> { + pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) + -> NodesMatchingSuffix<'a, 'ast> { NodesMatchingSuffix { map: self, item_name: parts.last().unwrap(), @@ -565,14 +565,14 @@ impl<'ast> Map<'ast> { } } -pub struct NodesMatchingSuffix<'a, 'ast:'a, S:'a> { +pub struct NodesMatchingSuffix<'a, 'ast:'a> { map: &'a Map<'ast>, - item_name: &'a S, - in_which: &'a [S], + item_name: &'a String, + in_which: &'a [String], idx: NodeId, } -impl<'a, 'ast, S:Str> NodesMatchingSuffix<'a, 'ast, S> { +impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> { /// Returns true only if some suffix of the module path for parent /// matches `self.in_which`. /// @@ -586,7 +586,7 @@ impl<'a, 'ast, S:Str> NodesMatchingSuffix<'a, 'ast, S> { None => return false, Some((node_id, name)) => (node_id, name), }; - if part.as_slice() != mod_name.as_str() { + if part[] != mod_name.as_str() { return false; } cursor = self.map.get_parent(mod_id); @@ -624,12 +624,12 @@ impl<'a, 'ast, S:Str> NodesMatchingSuffix<'a, 'ast, S> { // We are looking at some node `n` with a given name and parent // id; do their names match what I am seeking? fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool { - name.as_str() == self.item_name.as_slice() && + name.as_str() == self.item_name[] && self.suffix_matches(parent_of_n) } } -impl<'a, 'ast, S:Str> Iterator for NodesMatchingSuffix<'a, 'ast, S> { +impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> { fn next(&mut self) -> Option { loop { let idx = self.idx; @@ -1037,7 +1037,7 @@ impl<'a> NodePrinter for pprust::State<'a> { fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { let id_str = format!(" (id={})", id); - let id_str = if include_id { id_str.as_slice() } else { "" }; + let id_str = if include_id { id_str[] } else { "" }; match map.find(id) { Some(NodeItem(item)) => { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 02771809ae6..5727866d6ec 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -238,11 +238,11 @@ pub fn impl_pretty_name(trait_ref: &Option, ty: &Ty) -> Ident { match *trait_ref { Some(ref trait_ref) => { pretty.push('.'); - pretty.push_str(pprust::path_to_string(&trait_ref.path).as_slice()); + pretty.push_str(pprust::path_to_string(&trait_ref.path)[]); } None => {} } - token::gensym_ident(pretty.as_slice()) + token::gensym_ident(pretty[]) } pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod { @@ -700,7 +700,7 @@ pub fn pat_is_ident(pat: P) -> bool { pub fn path_name_eq(a : &ast::Path, b : &ast::Path) -> bool { (a.span == b.span) && (a.global == b.global) - && (segments_name_eq(a.segments.as_slice(), b.segments.as_slice())) + && (segments_name_eq(a.segments[], b.segments[])) } // are two arrays of segments equal when compared unhygienically? @@ -788,13 +788,13 @@ mod test { #[test] fn idents_name_eq_test() { assert!(segments_name_eq( [Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}] - .iter().map(ident_to_segment).collect::>().as_slice(), + .iter().map(ident_to_segment).collect::>()[], [Ident{name:Name(3),ctxt:104}, Ident{name:Name(78),ctxt:182}] - .iter().map(ident_to_segment).collect::>().as_slice())); + .iter().map(ident_to_segment).collect::>()[])); assert!(!segments_name_eq( [Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}] - .iter().map(ident_to_segment).collect::>().as_slice(), + .iter().map(ident_to_segment).collect::>()[], [Ident{name:Name(3),ctxt:104}, Ident{name:Name(77),ctxt:182}] - .iter().map(ident_to_segment).collect::>().as_slice())); + .iter().map(ident_to_segment).collect::>()[])); } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 127cc5ed51d..b1158917b72 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -97,7 +97,7 @@ impl AttrMetaMethods for MetaItem { fn meta_item_list<'a>(&'a self) -> Option<&'a [P]> { match self.node { - MetaList(_, ref l) => Some(l.as_slice()), + MetaList(_, ref l) => Some(l[]), _ => None } } @@ -136,7 +136,7 @@ impl AttributeMethods for Attribute { let meta = mk_name_value_item_str( InternedString::new("doc"), token::intern_and_get_ident(strip_doc_comment_decoration( - comment.get()).as_slice())); + comment.get())[])); if self.node.style == ast::AttrOuter { f(&mk_attr_outer(self.node.id, meta)) } else { @@ -296,9 +296,9 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { } MetaList(ref n, ref items) if *n == "inline" => { mark_used(attr); - if contains_name(items.as_slice(), "always") { + if contains_name(items[], "always") { InlineAlways - } else if contains_name(items.as_slice(), "never") { + } else if contains_name(items[], "never") { InlineNever } else { InlineHint @@ -332,7 +332,7 @@ pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P], cfg: &ast::Me !cfg_matches(diagnostic, cfgs, &*mis[0]) } ast::MetaList(ref pred, _) => { - diagnostic.span_err(cfg.span, format!("invalid predicate `{}`", pred).as_slice()); + diagnostic.span_err(cfg.span, format!("invalid predicate `{}`", pred)[]); false }, ast::MetaWord(_) | ast::MetaNameValue(..) => contains(cfgs, cfg), @@ -396,8 +396,7 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P]) { if !set.insert(name.clone()) { diagnostic.span_fatal(meta.span, - format!("duplicate meta item `{}`", - name).as_slice()); + format!("duplicate meta item `{}`", name)[]); } } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index c726e17a8fa..060e1d3f995 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -291,9 +291,9 @@ impl FileMap { lines.get(line_number).map(|&line| { let begin: BytePos = line - self.start_pos; let begin = begin.to_uint(); - let slice = self.src.slice_from(begin); + let slice = self.src[begin..]; match slice.find('\n') { - Some(e) => slice.slice_to(e), + Some(e) => slice[0..e], None => slice }.to_string() }) @@ -338,9 +338,9 @@ impl CodeMap { // FIXME #12884: no efficient/safe way to remove from the start of a string // and reuse the allocation. let mut src = if src.starts_with("\u{feff}") { - String::from_str(src.slice_from(3)) + String::from_str(src[3..]) } else { - String::from_str(src.as_slice()) + String::from_str(src[]) }; // Append '\n' in case it's not already there. @@ -427,8 +427,8 @@ impl CodeMap { if begin.fm.start_pos != end.fm.start_pos { None } else { - Some(begin.fm.src.slice(begin.pos.to_uint(), - end.pos.to_uint()).to_string()) + Some(begin.fm.src[begin.pos.to_uint().. + end.pos.to_uint()].to_string()) } } diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 4d765f49aca..88dfdf6e2d8 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -123,7 +123,7 @@ impl SpanHandler { panic!(ExplicitBug); } pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! { - self.span_bug(sp, format!("unimplemented {}", msg).as_slice()); + self.span_bug(sp, format!("unimplemented {}", msg)[]); } pub fn handler<'a>(&'a self) -> &'a Handler { &self.handler @@ -166,7 +166,7 @@ impl Handler { self.err_count.get()); } } - self.fatal(s.as_slice()); + self.fatal(s[]); } pub fn warn(&self, msg: &str) { self.emit.borrow_mut().emit(None, msg, None, Warning); @@ -182,7 +182,7 @@ impl Handler { panic!(ExplicitBug); } pub fn unimpl(&self, msg: &str) -> ! { - self.bug(format!("unimplemented {}", msg).as_slice()); + self.bug(format!("unimplemented {}", msg)[]); } pub fn emit(&self, cmsp: Option<(&codemap::CodeMap, Span)>, @@ -277,7 +277,7 @@ fn print_maybe_styled(w: &mut EmitterWriter, // to be miscolored. We assume this is rare enough that we don't // have to worry about it. if msg.ends_with("\n") { - try!(t.write_str(msg.slice_to(msg.len()-1))); + try!(t.write_str(msg[0..msg.len()-1])); try!(t.reset()); try!(t.write_str("\n")); } else { @@ -299,16 +299,16 @@ fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, } try!(print_maybe_styled(dst, - format!("{}: ", lvl.to_string()).as_slice(), + format!("{}: ", lvl.to_string())[], term::attr::ForegroundColor(lvl.color()))); try!(print_maybe_styled(dst, - format!("{}", msg).as_slice(), + format!("{}", msg)[], term::attr::Bold)); match code { Some(code) => { let style = term::attr::ForegroundColor(term::color::BRIGHT_MAGENTA); - try!(print_maybe_styled(dst, format!(" [{}]", code.clone()).as_slice(), style)); + try!(print_maybe_styled(dst, format!(" [{}]", code.clone())[], style)); } None => () } @@ -398,12 +398,12 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, // the span) let span_end = Span { lo: sp.hi, hi: sp.hi, expn_id: sp.expn_id}; let ses = cm.span_to_string(span_end); - try!(print_diagnostic(dst, ses.as_slice(), lvl, msg, code)); + try!(print_diagnostic(dst, ses[], lvl, msg, code)); if rsp.is_full_span() { try!(custom_highlight_lines(dst, cm, sp, lvl, lines)); } } else { - try!(print_diagnostic(dst, ss.as_slice(), lvl, msg, code)); + try!(print_diagnostic(dst, ss[], lvl, msg, code)); if rsp.is_full_span() { try!(highlight_lines(dst, cm, sp, lvl, lines)); } @@ -413,9 +413,9 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, Some(code) => match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) { Some(_) => { - try!(print_diagnostic(dst, ss.as_slice(), Help, + try!(print_diagnostic(dst, ss[], Help, format!("pass `--explain {}` to see a detailed \ - explanation", code).as_slice(), None)); + explanation", code)[], None)); } None => () }, @@ -432,7 +432,7 @@ fn highlight_lines(err: &mut EmitterWriter, let fm = &*lines.file; let mut elided = false; - let mut display_lines = lines.lines.as_slice(); + let mut display_lines = lines.lines[]; if display_lines.len() > MAX_LINES { display_lines = display_lines[0u..MAX_LINES]; elided = true; @@ -494,7 +494,7 @@ fn highlight_lines(err: &mut EmitterWriter, } } try!(print_maybe_styled(err, - format!("{}\n", s).as_slice(), + format!("{}\n", s)[], term::attr::ForegroundColor(lvl.color()))); } Ok(()) @@ -514,7 +514,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter, -> io::IoResult<()> { let fm = &*lines.file; - let lines = lines.lines.as_slice(); + let lines = lines.lines[]; if lines.len() > MAX_LINES { if let Some(line) = fm.get_line(lines[0]) { try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, @@ -545,7 +545,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter, s.push('^'); s.push('\n'); print_maybe_styled(w, - s.as_slice(), + s[], term::attr::ForegroundColor(lvl.color())) } @@ -560,12 +560,12 @@ fn print_macro_backtrace(w: &mut EmitterWriter, codemap::MacroAttribute => ("#[", "]"), codemap::MacroBang => ("", "!") }; - try!(print_diagnostic(w, ss.as_slice(), Note, + try!(print_diagnostic(w, ss[], Note, format!("in expansion of {}{}{}", pre, ei.callee.name, - post).as_slice(), None)); + post)[], None)); let ss = cm.span_to_string(ei.call_site); - try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site", None)); + try!(print_diagnostic(w, ss[], Note, "expansion site", None)); Ok(Some(ei.call_site)) } None => Ok(None) @@ -578,6 +578,6 @@ pub fn expect(diag: &SpanHandler, opt: Option, msg: M) -> T where { match opt { Some(t) => t, - None => diag.handler().bug(msg().as_slice()), + None => diag.handler().bug(msg()[]), } } diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index bcce5538314..90fc28014e6 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -58,7 +58,7 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, Some(previous_span) => { ecx.span_warn(span, format!( "diagnostic code {} already used", token::get_ident(code).get() - ).as_slice()); + )[]); ecx.span_note(previous_span, "previous invocation"); }, None => () @@ -87,12 +87,12 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, if diagnostics.insert(code.name, description).is_some() { ecx.span_err(span, format!( "diagnostic code {} already registered", token::get_ident(*code).get() - ).as_slice()); + )[]); } }); let sym = Ident::new(token::gensym(( "__register_diagnostic_".to_string() + token::get_ident(*code).get() - ).as_slice())); + )[])); MacItems::new(vec![quote_item!(ecx, mod $sym {}).unwrap()].into_iter()) } diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index b138811187b..b77b822a6b2 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -100,8 +100,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Some(('=', _)) => None, Some(('+', operand)) => { Some(token::intern_and_get_ident(format!( - "={}", - operand).as_slice())) + "={}", operand)[])) } _ => { cx.span_err(span, "output operand constraint lacks '=' or '+'"); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index aefbb2a1fea..62fe718b522 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -549,7 +549,7 @@ impl<'a> ExtCtxt<'a> { pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); } pub fn mod_path(&self) -> Vec { let mut v = Vec::new(); - v.push(token::str_to_ident(self.ecfg.crate_name.as_slice())); + v.push(token::str_to_ident(self.ecfg.crate_name[])); v.extend(self.mod_path.iter().map(|a| *a)); return v; } @@ -558,7 +558,7 @@ impl<'a> ExtCtxt<'a> { if self.recursion_count > self.ecfg.recursion_limit { self.span_fatal(ei.call_site, format!("recursion limit reached while expanding the macro `{}`", - ei.callee.name).as_slice()); + ei.callee.name)[]); } let mut call_site = ei.call_site; @@ -669,7 +669,7 @@ pub fn check_zero_tts(cx: &ExtCtxt, tts: &[ast::TokenTree], name: &str) { if tts.len() != 0 { - cx.span_err(sp, format!("{} takes no arguments", name).as_slice()); + cx.span_err(sp, format!("{} takes no arguments", name)[]); } } @@ -682,12 +682,12 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt, -> Option { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { - cx.span_err(sp, format!("{} takes 1 argument", name).as_slice()); + cx.span_err(sp, format!("{} takes 1 argument", name)[]); return None } let ret = cx.expander().fold_expr(p.parse_expr()); if p.token != token::Eof { - cx.span_err(sp, format!("{} takes 1 argument", name).as_slice()); + cx.span_err(sp, format!("{} takes 1 argument", name)[]); } expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| { s.get().to_string() diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 9d4992f7453..77165168746 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -712,8 +712,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let loc = self.codemap().lookup_char_pos(span.lo); let expr_file = self.expr_str(span, token::intern_and_get_ident(loc.file - .name - .as_slice())); + .name[])); let expr_line = self.expr_uint(span, loc.line); let expr_file_line_tuple = self.expr_tuple(span, vec!(expr_file, expr_line)); let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs index e2867c2fbab..03dd08fdf7f 100644 --- a/src/libsyntax/ext/concat.rs +++ b/src/libsyntax/ext/concat.rs @@ -40,14 +40,14 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, ast::LitInt(i, ast::UnsignedIntLit(_)) | ast::LitInt(i, ast::SignedIntLit(_, ast::Plus)) | ast::LitInt(i, ast::UnsuffixedIntLit(ast::Plus)) => { - accumulator.push_str(format!("{}", i).as_slice()); + accumulator.push_str(format!("{}", i)[]); } ast::LitInt(i, ast::SignedIntLit(_, ast::Minus)) | ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => { - accumulator.push_str(format!("-{}", i).as_slice()); + accumulator.push_str(format!("-{}", i)[]); } ast::LitBool(b) => { - accumulator.push_str(format!("{}", b).as_slice()); + accumulator.push_str(format!("{}", b)[]); } ast::LitByte(..) | ast::LitBinary(..) => { @@ -62,5 +62,5 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, } base::MacExpr::new(cx.expr_str( sp, - token::intern_and_get_ident(accumulator.as_slice()))) + token::intern_and_get_ident(accumulator[]))) } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index aa18b1be31a..2cf60d30a1b 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -40,7 +40,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] } } } - let res = str_to_ident(res_str.as_slice()); + let res = str_to_ident(res_str[]); let e = P(ast::Expr { id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index 3145b3bb1a4..c27a27fce6a 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -31,8 +31,7 @@ pub fn expand_deriving_bound(cx: &mut ExtCtxt, ref tname => { cx.span_bug(span, format!("expected built-in trait name but \ - found {}", - *tname).as_slice()) + found {}", *tname)[]) } } }, diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index a34764221b3..eedec6f37c8 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -80,13 +80,11 @@ fn cs_clone( EnumNonMatchingCollapsed (..) => { cx.span_bug(trait_span, format!("non-matching enum variants in \ - `deriving({})`", - name).as_slice()) + `deriving({})`", name)[]) } StaticEnum(..) | StaticStruct(..) => { cx.span_bug(trait_span, - format!("static method in `deriving({})`", - name).as_slice()) + format!("static method in `deriving({})`", name)[]) } } @@ -103,8 +101,7 @@ fn cs_clone( None => { cx.span_bug(trait_span, format!("unnamed field in normal struct in \ - `deriving({})`", - name).as_slice()) + `deriving({})`", name)[]) } }; cx.field_imm(field.span, ident, subcall(field)) diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 0a8d59da896..a4c70ebbc8e 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -174,7 +174,7 @@ fn decode_static_fields(cx: &mut ExtCtxt, let fields = fields.iter().enumerate().map(|(i, &span)| { getarg(cx, span, token::intern_and_get_ident(format!("_field{}", - i).as_slice()), + i)[]), i) }).collect(); diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 30851ebeaae..aac515ed81a 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -162,8 +162,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, let name = match name { Some(id) => token::get_ident(id), None => { - token::intern_and_get_ident(format!("_field{}", - i).as_slice()) + token::intern_and_get_ident(format!("_field{}", i)[]) } }; let enc = cx.expr_method_call(span, self_.clone(), diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index d8de3d2db97..a2b5c0b9e96 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -514,15 +514,15 @@ impl<'a> TraitDef<'a> { self, struct_def, type_ident, - self_args.as_slice(), - nonself_args.as_slice()) + self_args[], + nonself_args[]) } else { method_def.expand_struct_method_body(cx, self, struct_def, type_ident, - self_args.as_slice(), - nonself_args.as_slice()) + self_args[], + nonself_args[]) }; method_def.create_method(cx, @@ -554,15 +554,15 @@ impl<'a> TraitDef<'a> { self, enum_def, type_ident, - self_args.as_slice(), - nonself_args.as_slice()) + self_args[], + nonself_args[]) } else { method_def.expand_enum_method_body(cx, self, enum_def, type_ident, self_args, - nonself_args.as_slice()) + nonself_args[]) }; method_def.create_method(cx, @@ -649,7 +649,7 @@ impl<'a> MethodDef<'a> { for (i, ty) in self.args.iter().enumerate() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(format!("__arg_{}", i).as_slice()); + let ident = cx.ident_of(format!("__arg_{}", i)[]); arg_tys.push((ident, ast_ty)); let arg_expr = cx.expr_ident(trait_.span, ident); @@ -756,7 +756,7 @@ impl<'a> MethodDef<'a> { struct_path, struct_def, format!("__self_{}", - i).as_slice(), + i)[], ast::MutImmutable); patterns.push(pat); raw_fields.push(ident_expr); @@ -912,22 +912,22 @@ impl<'a> MethodDef<'a> { .collect::>(); let self_arg_idents = self_arg_names.iter() - .map(|name|cx.ident_of(name.as_slice())) + .map(|name|cx.ident_of(name[])) .collect::>(); // The `vi_idents` will be bound, solely in the catch-all, to // a series of let statements mapping each self_arg to a uint // corresponding to its variant index. let vi_idents: Vec = self_arg_names.iter() - .map(|name| { let vi_suffix = format!("{}_vi", name.as_slice()); - cx.ident_of(vi_suffix.as_slice()) }) + .map(|name| { let vi_suffix = format!("{}_vi", name[]); + cx.ident_of(vi_suffix[]) }) .collect::>(); // Builds, via callback to call_substructure_method, the // delegated expression that handles the catch-all case, // using `__variants_tuple` to drive logic if necessary. let catch_all_substructure = EnumNonMatchingCollapsed( - self_arg_idents, variants.as_slice(), vi_idents.as_slice()); + self_arg_idents, variants[], vi_idents[]); // These arms are of the form: // (Variant1, Variant1, ...) => Body1 @@ -949,12 +949,12 @@ impl<'a> MethodDef<'a> { let mut subpats = Vec::with_capacity(self_arg_names.len()); let mut self_pats_idents = Vec::with_capacity(self_arg_names.len() - 1); let first_self_pat_idents = { - let (p, idents) = mk_self_pat(cx, self_arg_names[0].as_slice()); + let (p, idents) = mk_self_pat(cx, self_arg_names[0][]); subpats.push(p); idents }; for self_arg_name in self_arg_names.tail().iter() { - let (p, idents) = mk_self_pat(cx, self_arg_name.as_slice()); + let (p, idents) = mk_self_pat(cx, self_arg_name[]); subpats.push(p); self_pats_idents.push(idents); } @@ -1010,7 +1010,7 @@ impl<'a> MethodDef<'a> { &**variant, field_tuples); let arm_expr = self.call_substructure_method( - cx, trait_, type_ident, self_args.as_slice(), nonself_args, + cx, trait_, type_ident, self_args[], nonself_args, &substructure); cx.arm(sp, vec![single_pat], arm_expr) @@ -1063,7 +1063,7 @@ impl<'a> MethodDef<'a> { } let arm_expr = self.call_substructure_method( - cx, trait_, type_ident, self_args.as_slice(), nonself_args, + cx, trait_, type_ident, self_args[], nonself_args, &catch_all_substructure); // Builds the expression: @@ -1267,7 +1267,7 @@ impl<'a> TraitDef<'a> { cx.span_bug(sp, "a struct with named and unnamed fields in `deriving`"); } }; - let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice()); + let ident = cx.ident_of(format!("{}_{}", prefix, i)[]); paths.push(codemap::Spanned{span: sp, node: ident}); let val = cx.expr( sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident))))); @@ -1313,7 +1313,7 @@ impl<'a> TraitDef<'a> { let mut ident_expr = Vec::new(); for (i, va) in variant_args.iter().enumerate() { let sp = self.set_expn_info(cx, va.ty.span); - let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice()); + let ident = cx.ident_of(format!("{}_{}", prefix, i)[]); let path1 = codemap::Spanned{span: sp, node: ident}; paths.push(path1); let expr_path = cx.expr_path(cx.path_ident(sp, ident)); @@ -1356,7 +1356,7 @@ pub fn cs_fold(use_foldl: bool, field.span, old, field.self_.clone(), - field.other.as_slice()) + field.other[]) }) } else { all_fields.iter().rev().fold(base, |old, field| { @@ -1364,12 +1364,12 @@ pub fn cs_fold(use_foldl: bool, field.span, old, field.self_.clone(), - field.other.as_slice()) + field.other[]) }) } }, EnumNonMatchingCollapsed(ref all_args, _, tuple) => - enum_nonmatch_f(cx, trait_span, (all_args.as_slice(), tuple), + enum_nonmatch_f(cx, trait_span, (all_args[], tuple), substructure.nonself_args), StaticEnum(..) | StaticStruct(..) => { cx.span_bug(trait_span, "static function in `deriving`") @@ -1409,7 +1409,7 @@ pub fn cs_same_method(f: F, f(cx, trait_span, called) }, EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => - enum_nonmatch_f(cx, trait_span, (all_self_args.as_slice(), tuple), + enum_nonmatch_f(cx, trait_span, (all_self_args[], tuple), substructure.nonself_args), StaticEnum(..) | StaticStruct(..) => { cx.span_bug(trait_span, "static function in `deriving`") diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 839e99c81d1..4a9076b07b5 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -115,7 +115,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt, cx.span_err(titem.span, format!("unknown `deriving` \ trait: `{}`", - *tname).as_slice()); + *tname)[]); } }; } diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index a68b521bbc9..19b45a1e610 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -127,7 +127,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, let formatter = substr.nonself_args[0].clone(); let meth = cx.ident_of("write_fmt"); - let s = token::intern_and_get_ident(format_string.as_slice()); + let s = token::intern_and_get_ident(format_string[]); let format_string = cx.expr_str(span, s); // phew, not our responsibility any more! diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 8c17b31f458..9fedc4a158e 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -30,7 +30,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT Some(v) => v }; - let e = match os::getenv(var.as_slice()) { + let e = match os::getenv(var[]) { None => { cx.expr_path(cx.path_all(sp, true, @@ -56,7 +56,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT cx.ident_of("Some")), vec!(cx.expr_str(sp, token::intern_and_get_ident( - s.as_slice())))) + s[])))) } }; MacExpr::new(e) @@ -83,7 +83,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) None => { token::intern_and_get_ident(format!("environment variable `{}` \ not defined", - var).as_slice()) + var)[]) } Some(second) => { match expr_to_string(cx, second, "expected string literal") { @@ -106,7 +106,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) cx.span_err(sp, msg.get()); cx.expr_uint(sp, 0) } - Some(s) => cx.expr_str(sp, token::intern_and_get_ident(s.as_slice())) + Some(s) => cx.expr_str(sp, token::intern_and_get_ident(s[])) }; MacExpr::new(e) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b10ae7a09db..f2b6f6bfe16 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -293,7 +293,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, format!("macro undefined: '{}!'", - extnamestr.get()).as_slice()); + extnamestr.get())[]); // let compilation continue None @@ -309,7 +309,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, }, }); let fm = fresh_mark(); - let marked_before = mark_tts(tts.as_slice(), fm); + let marked_before = mark_tts(tts[], fm); // The span that we pass to the expanders we want to // be the root of the call stack. That's the most @@ -320,7 +320,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, let opt_parsed = { let expanded = expandfun.expand(fld.cx, mac_span, - marked_before.as_slice()); + marked_before[]); parse_thunk(expanded) }; let parsed = match opt_parsed { @@ -329,8 +329,8 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, format!("non-expression macro in expression position: {}", - extnamestr.get().as_slice() - ).as_slice()); + extnamestr.get()[] + )[]); return None; } }; @@ -340,7 +340,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, format!("'{}' is not a tt-style macro", - extnamestr.get()).as_slice()); + extnamestr.get())[]); None } } @@ -445,7 +445,7 @@ pub fn expand_item(it: P, fld: &mut MacroExpander) if valid_ident { fld.cx.mod_push(it.ident); } - let macro_escape = contains_macro_escape(new_attrs.as_slice()); + let macro_escape = contains_macro_escape(new_attrs[]); let result = with_exts_frame!(fld.cx.syntax_env, macro_escape, noop_fold_item(it, fld)); @@ -553,7 +553,7 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) None => { fld.cx.span_err(path_span, format!("macro undefined: '{}!'", - extnamestr).as_slice()); + extnamestr)[]); // let compilation continue return SmallVector::zero(); } @@ -566,7 +566,7 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) format!("macro {}! expects no ident argument, \ given '{}'", extnamestr, - token::get_ident(it.ident)).as_slice()); + token::get_ident(it.ident))[]); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -578,14 +578,14 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) } }); // mark before expansion: - let marked_before = mark_tts(tts.as_slice(), fm); - expander.expand(fld.cx, it.span, marked_before.as_slice()) + let marked_before = mark_tts(tts[], fm); + expander.expand(fld.cx, it.span, marked_before[]) } IdentTT(ref expander, span) => { if it.ident.name == parse::token::special_idents::invalid.name { fld.cx.span_err(path_span, format!("macro {}! expects an ident argument", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -597,14 +597,14 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) } }); // mark before expansion: - let marked_tts = mark_tts(tts.as_slice(), fm); + let marked_tts = mark_tts(tts[], fm); expander.expand(fld.cx, it.span, it.ident, marked_tts) } LetSyntaxTT(ref expander, span) => { if it.ident.name == parse::token::special_idents::invalid.name { fld.cx.span_err(path_span, format!("macro {}! expects an ident argument", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -621,7 +621,7 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) _ => { fld.cx.span_err(it.span, format!("{}! is not legal in item position", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return SmallVector::zero(); } } @@ -639,8 +639,8 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) // result of expanding a LetSyntaxTT, and thus doesn't // need to be marked. Not that it could be marked anyway. // create issue to recommend refactoring here? - fld.cx.syntax_env.insert(intern(name.as_slice()), ext); - if attr::contains_name(it.attrs.as_slice(), "macro_export") { + fld.cx.syntax_env.insert(intern(name[]), ext); + if attr::contains_name(it.attrs[], "macro_export") { fld.cx.exported_macros.push(it); } SmallVector::zero() @@ -654,7 +654,7 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) Right(None) => { fld.cx.span_err(path_span, format!("non-item macro in item position: {}", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return SmallVector::zero(); } }; @@ -903,7 +903,7 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { None => { fld.cx.span_err(pth.span, format!("macro undefined: '{}!'", - extnamestr).as_slice()); + extnamestr)[]); // let compilation continue return DummyResult::raw_pat(span); } @@ -920,11 +920,11 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { }); let fm = fresh_mark(); - let marked_before = mark_tts(tts.as_slice(), fm); + let marked_before = mark_tts(tts[], fm); let mac_span = fld.cx.original_span(); let expanded = match expander.expand(fld.cx, mac_span, - marked_before.as_slice()).make_pat() { + marked_before[]).make_pat() { Some(e) => e, None => { fld.cx.span_err( @@ -932,7 +932,7 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { format!( "non-pattern macro in pattern position: {}", extnamestr.get() - ).as_slice() + )[] ); return DummyResult::raw_pat(span); } @@ -944,7 +944,7 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { _ => { fld.cx.span_err(span, format!("{}! is not legal in pattern position", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return DummyResult::raw_pat(span); } } @@ -1192,8 +1192,7 @@ pub fn expand_crate(parse_sess: &parse::ParseSess, let mut expander = MacroExpander::new(&mut cx); for ExportedMacros { crate_name, macros } in imported_macros.into_iter() { - let name = format!("<{} macros>", token::get_ident(crate_name)) - .into_string(); + let name = format!("<{} macros>", token::get_ident(crate_name)); for source in macros.into_iter() { let item = parse::parse_item_from_source_str(name.clone(), @@ -1238,7 +1237,7 @@ impl Folder for Marker { node: match node { MacInvocTT(path, tts, ctxt) => { MacInvocTT(self.fold_path(path), - self.fold_tts(tts.as_slice()), + self.fold_tts(tts[]), mtwt::apply_mark(self.mark, ctxt)) } }, @@ -1415,9 +1414,9 @@ mod test { let attr2 = make_dummy_attr ("bar"); let escape_attr = make_dummy_attr ("macro_escape"); let attrs1 = vec!(attr1.clone(), escape_attr, attr2.clone()); - assert_eq!(contains_macro_escape(attrs1.as_slice()),true); + assert_eq!(contains_macro_escape(attrs1[]),true); let attrs2 = vec!(attr1,attr2); - assert_eq!(contains_macro_escape(attrs2.as_slice()),false); + assert_eq!(contains_macro_escape(attrs2[]),false); } // make a MetaWord outer attribute with the given name @@ -1729,7 +1728,7 @@ foo_module!(); let string = ident.get(); "xx" == string }).collect(); - let cxbinds: &[&ast::Ident] = cxbinds.as_slice(); + let cxbinds: &[&ast::Ident] = cxbinds[]; let cxbind = match cxbinds { [b] => b, _ => panic!("expected just one binding for ext_cx") diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 95c7fcc564a..aad4045f00a 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -136,7 +136,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool, _ => { ecx.span_err(p.span, format!("expected ident for named argument, found `{}`", - p.this_token_to_string()).as_slice()); + p.this_token_to_string())[]); return (invocation, None); } }; @@ -149,7 +149,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool, Some(prev) => { ecx.span_err(e.span, format!("duplicate argument named `{}`", - name).as_slice()); + name)[]); ecx.parse_sess.span_diagnostic.span_note(prev.span, "previously here"); continue } @@ -240,7 +240,7 @@ impl<'a, 'b> Context<'a, 'b> { let msg = format!("invalid reference to argument `{}` ({})", arg, self.describe_num_args()); - self.ecx.span_err(self.fmtsp, msg.as_slice()); + self.ecx.span_err(self.fmtsp, msg[]); return; } { @@ -260,7 +260,7 @@ impl<'a, 'b> Context<'a, 'b> { Some(e) => e.span, None => { let msg = format!("there is no argument named `{}`", name); - self.ecx.span_err(self.fmtsp, msg.as_slice()); + self.ecx.span_err(self.fmtsp, msg[]); return; } }; @@ -303,19 +303,19 @@ impl<'a, 'b> Context<'a, 'b> { format!("argument redeclared with type `{}` when \ it was previously `{}`", *ty, - *cur).as_slice()); + *cur)[]); } (&Known(ref cur), _) => { self.ecx.span_err(sp, format!("argument used to format with `{}` was \ attempted to not be used for formatting", - *cur).as_slice()); + *cur)[]); } (_, &Known(ref ty)) => { self.ecx.span_err(sp, format!("argument previously used as a format \ argument attempted to be used as `{}`", - *ty).as_slice()); + *ty)[]); } (_, _) => { self.ecx.span_err(sp, "argument declared with multiple formats"); @@ -380,7 +380,7 @@ impl<'a, 'b> Context<'a, 'b> { /// Translate the accumulated string literals to a literal expression fn trans_literal_string(&mut self) -> P { let sp = self.fmtsp; - let s = token::intern_and_get_ident(self.literal.as_slice()); + let s = token::intern_and_get_ident(self.literal[]); self.literal.clear(); self.ecx.expr_str(sp, s) } @@ -552,7 +552,7 @@ impl<'a, 'b> Context<'a, 'b> { None => continue // error already generated }; - let name = self.ecx.ident_of(format!("__arg{}", i).as_slice()); + let name = self.ecx.ident_of(format!("__arg{}", i)[]); pats.push(self.ecx.pat_ident(e.span, name)); locals.push(Context::format_arg(self.ecx, e.span, arg_ty, self.ecx.expr_ident(e.span, name))); @@ -569,7 +569,7 @@ impl<'a, 'b> Context<'a, 'b> { }; let lname = self.ecx.ident_of(format!("__arg{}", - *name).as_slice()); + *name)[]); pats.push(self.ecx.pat_ident(e.span, lname)); names[self.name_positions[*name]] = Some(Context::format_arg(self.ecx, e.span, arg_ty, @@ -652,7 +652,7 @@ impl<'a, 'b> Context<'a, 'b> { -> P { let trait_ = match *ty { Known(ref tyname) => { - match tyname.as_slice() { + match tyname[] { "" => "Show", "?" => "Show", "e" => "LowerExp", @@ -665,7 +665,7 @@ impl<'a, 'b> Context<'a, 'b> { _ => { ecx.span_err(sp, format!("unknown format trait `{}`", - *tyname).as_slice()); + *tyname)[]); "Dummy" } } @@ -760,8 +760,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, match parser.errors.remove(0) { Some(error) => { cx.ecx.span_err(cx.fmtsp, - format!("invalid format string: {}", - error).as_slice()); + format!("invalid format string: {}", error)[]); return DummyResult::raw_expr(sp); } None => {} diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index c7cb41e2ece..368d4fa8447 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -474,7 +474,7 @@ pub fn expand_quote_stmt(cx: &mut ExtCtxt, } fn ids_ext(strs: Vec ) -> Vec { - strs.iter().map(|str| str_to_ident((*str).as_slice())).collect() + strs.iter().map(|str| str_to_ident((*str)[])).collect() } fn id_ext(str: &str) -> ast::Ident { @@ -676,7 +676,7 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec> { for i in range(0, tt.len()) { seq.push(tt.get_tt(i)); } - mk_tts(cx, seq.as_slice()) + mk_tts(cx, seq[]) } ast::TtToken(sp, ref tok) => { let e_sp = cx.expr_ident(sp, id_ext("_sp")); @@ -765,7 +765,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp)); let mut vector = vec!(stmt_let_sp, stmt_let_tt); - vector.extend(mk_tts(cx, tts.as_slice()).into_iter()); + vector.extend(mk_tts(cx, tts[]).into_iter()); let block = cx.expr_block( cx.block_all(sp, Vec::new(), diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 570231940aa..7c2c5c1530c 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -57,7 +57,7 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let topmost = cx.original_span_in_file(); let loc = cx.codemap().lookup_char_pos(topmost.lo); - let filename = token::intern_and_get_ident(loc.file.name.as_slice()); + let filename = token::intern_and_get_ident(loc.file.name[]); base::MacExpr::new(cx.expr_str(topmost, filename)) } @@ -65,7 +65,7 @@ pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { let s = pprust::tts_to_string(tts); base::MacExpr::new(cx.expr_str(sp, - token::intern_and_get_ident(s.as_slice()))) + token::intern_and_get_ident(s[]))) } pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) @@ -78,7 +78,7 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) .connect("::"); base::MacExpr::new(cx.expr_str( sp, - token::intern_and_get_ident(string.as_slice()))) + token::intern_and_get_ident(string[]))) } /// include! : parse the given file as an expr @@ -137,7 +137,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) cx.span_err(sp, format!("couldn't read {}: {}", file.display(), - e).as_slice()); + e)[]); return DummyResult::expr(sp); } Ok(bytes) => bytes, @@ -147,7 +147,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) // Add this input file to the code map to make it available as // dependency information let filename = file.display().to_string(); - let interned = token::intern_and_get_ident(src.as_slice()); + let interned = token::intern_and_get_ident(src[]); cx.codemap().new_filemap(filename, src); base::MacExpr::new(cx.expr_str(sp, interned)) @@ -155,7 +155,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Err(_) => { cx.span_err(sp, format!("{} wasn't a utf-8 file", - file.display()).as_slice()); + file.display())[]); return DummyResult::expr(sp); } } @@ -171,9 +171,7 @@ pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) match File::open(&file).read_to_end() { Err(e) => { cx.span_err(sp, - format!("couldn't read {}: {}", - file.display(), - e).as_slice()); + format!("couldn't read {}: {}", file.display(), e)[]); return DummyResult::expr(sp); } Ok(bytes) => { diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index bc639c32380..73ef18b8449 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -153,7 +153,7 @@ pub fn count_names(ms: &[TokenTree]) -> uint { seq.num_captures } &TtDelimited(_, ref delim) => { - count_names(delim.tts.as_slice()) + count_names(delim.tts[]) } &TtToken(_, MatchNt(..)) => { 1 @@ -165,7 +165,7 @@ pub fn count_names(ms: &[TokenTree]) -> uint { pub fn initial_matcher_pos(ms: Rc>, sep: Option, lo: BytePos) -> Box { - let match_idx_hi = count_names(ms.as_slice()); + let match_idx_hi = count_names(ms[]); let matches = Vec::from_fn(match_idx_hi, |_i| Vec::new()); box MatcherPos { stack: vec![], @@ -229,7 +229,7 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) p_s.span_diagnostic .span_fatal(sp, format!("duplicated bind name: {}", - string.get()).as_slice()) + string.get())[]) } } } @@ -254,13 +254,13 @@ pub fn parse_or_else(sess: &ParseSess, rdr: TtReader, ms: Vec ) -> HashMap> { - match parse(sess, cfg, rdr, ms.as_slice()) { + match parse(sess, cfg, rdr, ms[]) { Success(m) => m, Failure(sp, str) => { - sess.span_diagnostic.span_fatal(sp, str.as_slice()) + sess.span_diagnostic.span_fatal(sp, str[]) } Error(sp, str) => { - sess.span_diagnostic.span_fatal(sp, str.as_slice()) + sess.span_diagnostic.span_fatal(sp, str[]) } } } @@ -416,7 +416,7 @@ pub fn parse(sess: &ParseSess, } } TtToken(sp, SubstNt(..)) => { - return Error(sp, "Cannot transcribe in macro LHS".into_string()) + return Error(sp, "Cannot transcribe in macro LHS".to_string()) } seq @ TtDelimited(..) | seq @ TtToken(_, DocComment(..)) => { let lower_elts = mem::replace(&mut ei.top_elts, Tt(seq)); @@ -446,7 +446,7 @@ pub fn parse(sess: &ParseSess, for dv in eof_eis[0].matches.iter_mut() { v.push(dv.pop().unwrap()); } - return Success(nameize(sess, ms, v.as_slice())); + return Success(nameize(sess, ms, v[])); } else if eof_eis.len() > 1u { return Error(sp, "ambiguity: multiple successful parses".to_string()); } else { @@ -521,7 +521,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { _ => { let token_str = pprust::token_to_string(&p.token); p.fatal((format!("expected ident, found {}", - token_str.as_slice())).as_slice()) + token_str[]))[]) } }, "path" => { @@ -535,8 +535,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { res } _ => { - p.fatal(format!("unsupported builtin nonterminal parser: {}", - name).as_slice()) + p.fatal(format!("unsupported builtin nonterminal parser: {}", name)[]) } } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 92c68b7a9c7..08014dc1338 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -52,7 +52,7 @@ impl<'a> ParserAnyMacro<'a> { following", token_str); let span = parser.span; - parser.span_err(span, msg.as_slice()); + parser.span_err(span, msg[]); } } } @@ -124,8 +124,8 @@ impl TTMacroExpander for MacroRulesMacroExpander { sp, self.name, arg, - self.lhses.as_slice(), - self.rhses.as_slice()) + self.lhses[], + self.rhses[]) } } @@ -160,7 +160,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, match **lhs { MatchedNonterminal(NtTT(ref lhs_tt)) => { let lhs_tt = match **lhs_tt { - TtDelimited(_, ref delim) => delim.tts.as_slice(), + TtDelimited(_, ref delim) => delim.tts[], _ => cx.span_fatal(sp, "malformed macro lhs") }; // `None` is because we're not interpolating @@ -198,13 +198,13 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, best_fail_spot = sp; best_fail_msg = (*msg).clone(); }, - Error(sp, ref msg) => cx.span_fatal(sp, msg.as_slice()) + Error(sp, ref msg) => cx.span_fatal(sp, msg[]) } } _ => cx.bug("non-matcher found in parsed lhses") } } - cx.span_fatal(best_fail_spot, best_fail_msg.as_slice()); + cx.span_fatal(best_fail_spot, best_fail_msg[]); } // Note that macro-by-example's input is also matched against a token tree: diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 378dbba07fa..deed0b78e87 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -223,7 +223,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } LisContradiction(ref msg) => { // FIXME #2887 blame macro invoker instead - r.sp_diag.span_fatal(sp.clone(), msg.as_slice()); + r.sp_diag.span_fatal(sp.clone(), msg[]); } LisConstraint(len, _) => { if len == 0 { @@ -280,7 +280,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { r.sp_diag.span_fatal( r.cur_span, /* blame the macro writer */ format!("variable '{}' is still repeating at this depth", - token::get_ident(ident)).as_slice()); + token::get_ident(ident))[]); } } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0e0a87c74f8..d53a4b0e8d1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -133,7 +133,7 @@ impl<'a> Context<'a> { self.span_handler.span_err(span, explain); self.span_handler.span_help(span, format!("add #![feature({})] to the \ crate attributes to enable", - feature).as_slice()); + feature)[]); } } @@ -187,7 +187,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } match i.node { ast::ItemForeignMod(ref foreign_module) => { - if attr::contains_name(i.attrs.as_slice(), "link_args") { + if attr::contains_name(i.attrs[], "link_args") { self.gate_feature("link_args", i.span, "the `link_args` attribute is not portable \ across platforms, it is recommended to \ @@ -201,14 +201,14 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } ast::ItemFn(..) => { - if attr::contains_name(i.attrs.as_slice(), "plugin_registrar") { + if attr::contains_name(i.attrs[], "plugin_registrar") { self.gate_feature("plugin_registrar", i.span, "compiler plugins are experimental and possibly buggy"); } } ast::ItemStruct(..) => { - if attr::contains_name(i.attrs.as_slice(), "simd") { + if attr::contains_name(i.attrs[], "simd") { self.gate_feature("simd", i.span, "SIMD types are experimental and possibly buggy"); } @@ -285,7 +285,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { - if attr::contains_name(i.attrs.as_slice(), "linkage") { + if attr::contains_name(i.attrs[], "linkage") { self.gate_feature("linkage", i.span, "the `linkage` attribute is experimental \ and not portable across platforms") diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 41fee1556ab..41693d9d47a 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -92,8 +92,7 @@ impl<'a> ParserAttr for Parser<'a> { } _ => { let token_str = self.this_token_to_string(); - self.fatal(format!("expected `#`, found `{}`", - token_str).as_slice()); + self.fatal(format!("expected `#`, found `{}`", token_str)[]); } }; diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 95bae63f58f..b8da8365f7e 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -82,7 +82,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { while j > i && lines[j - 1].trim().is_empty() { j -= 1; } - return lines.slice(i, j).iter().map(|x| (*x).clone()).collect(); + return lines[i..j].iter().map(|x| (*x).clone()).collect(); } /// remove a "[ \t]*\*" block from each line, if possible @@ -116,7 +116,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { if can_trim { lines.iter().map(|line| { - line.slice(i + 1, line.len()).to_string() + line[i + 1..line.len()].to_string() }).collect() } else { lines @@ -127,12 +127,12 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { static ONLINERS: &'static [&'static str] = &["///!", "///", "//!", "//"]; for prefix in ONLINERS.iter() { if comment.starts_with(*prefix) { - return comment.slice_from(prefix.len()).to_string(); + return comment[prefix.len()..].to_string(); } } if comment.starts_with("/*") { - let lines = comment.slice(3u, comment.len() - 2u) + let lines = comment[3u..comment.len() - 2u] .lines_any() .map(|s| s.to_string()) .collect:: >(); @@ -187,7 +187,7 @@ fn read_line_comments(rdr: &mut StringReader, code_to_the_left: bool, let line = rdr.read_one_line_comment(); debug!("{}", line); // Doc comments are not put in comments. - if is_doc_comment(line.as_slice()) { + if is_doc_comment(line[]) { break; } lines.push(line); @@ -224,10 +224,10 @@ fn all_whitespace(s: &str, col: CharPos) -> Option { fn trim_whitespace_prefix_and_push_line(lines: &mut Vec , s: String, col: CharPos) { let len = s.len(); - let s1 = match all_whitespace(s.as_slice(), col) { + let s1 = match all_whitespace(s[], col) { Some(col) => { if col < len { - s.slice(col, len).to_string() + s[col..len].to_string() } else { "".to_string() } @@ -261,7 +261,7 @@ fn read_block_comment(rdr: &mut StringReader, rdr.bump(); rdr.bump(); } - if is_block_doc_comment(curr_line.as_slice()) { + if is_block_doc_comment(curr_line[]) { return } assert!(!curr_line.contains_char('\n')); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index da908f46ff6..13d020f6ae3 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -194,7 +194,7 @@ impl<'a> StringReader<'a> { let mut m = m.to_string(); m.push_str(": "); for c in c.escape_default() { m.push(c) } - self.fatal_span_(from_pos, to_pos, m.as_slice()); + self.fatal_span_(from_pos, to_pos, m[]); } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an @@ -203,7 +203,7 @@ impl<'a> StringReader<'a> { let mut m = m.to_string(); m.push_str(": "); for c in c.escape_default() { m.push(c) } - self.err_span_(from_pos, to_pos, m.as_slice()); + self.err_span_(from_pos, to_pos, m[]); } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending the @@ -212,8 +212,8 @@ impl<'a> StringReader<'a> { m.push_str(": "); let from = self.byte_offset(from_pos).to_uint(); let to = self.byte_offset(to_pos).to_uint(); - m.push_str(self.filemap.src.as_slice().slice(from, to)); - self.fatal_span_(from_pos, to_pos, m.as_slice()); + m.push_str(self.filemap.src[from..to]); + self.fatal_span_(from_pos, to_pos, m[]); } /// Advance peek_tok and peek_span to refer to the next token, and @@ -299,7 +299,7 @@ impl<'a> StringReader<'a> { while i < s.len() { let str::CharRange { ch, next } = s.char_range_at(i); if ch == '\r' { - if j < i { buf.push_str(s.slice(j, i)); } + if j < i { buf.push_str(s[j..i]); } j = next; if next >= s.len() || s.char_at(next) != '\n' { let pos = start + BytePos(i as u32); @@ -309,7 +309,7 @@ impl<'a> StringReader<'a> { } i = next; } - if j < s.len() { buf.push_str(s.slice_from(j)); } + if j < s.len() { buf.push_str(s[j..]); } buf } } @@ -358,7 +358,7 @@ impl<'a> StringReader<'a> { pub fn nextnextch(&self) -> Option { let offset = self.byte_offset(self.pos).to_uint(); - let s = self.filemap.deref().src.as_slice(); + let s = self.filemap.deref().src[]; if offset >= s.len() { return None } let str::CharRange { next, .. } = s.char_range_at(offset); if next < s.len() { @@ -554,7 +554,7 @@ impl<'a> StringReader<'a> { self.translate_crlf(start_bpos, string, "bare CR not allowed in block doc-comment") } else { string.into_cow() }; - token::DocComment(token::intern(string.as_slice())) + token::DocComment(token::intern(string[])) } else { token::Comment }; @@ -1108,7 +1108,7 @@ impl<'a> StringReader<'a> { // expansion purposes. See #12512 for the gory details of why // this is necessary. let ident = self.with_str_from(start, |lifetime_name| { - str_to_ident(format!("'{}", lifetime_name).as_slice()) + str_to_ident(format!("'{}", lifetime_name)[]) }); // Conjure up a "keyword checking ident" to make sure that diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 3d0877dd432..8cefb111fd1 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -251,17 +251,17 @@ pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option) Err(e) => { err(format!("couldn't read {}: {}", path.display(), - e).as_slice()); + e)[]); unreachable!() } }; - match str::from_utf8(bytes.as_slice()) { + match str::from_utf8(bytes[]).ok() { Some(s) => { return string_to_filemap(sess, s.to_string(), path.as_str().unwrap().to_string()) } None => { - err(format!("{} is not UTF-8 encoded", path.display()).as_slice()) + err(format!("{} is not UTF-8 encoded", path.display())[]) } } unreachable!() @@ -391,10 +391,10 @@ pub fn char_lit(lit: &str) -> (char, int) { } let msg = format!("lexer should have rejected a bad character escape {}", lit); - let msg2 = msg.as_slice(); + let msg2 = msg[]; fn esc(len: uint, lit: &str) -> Option<(char, int)> { - num::from_str_radix(lit.slice(2, len), 16) + num::from_str_radix(lit[2..len], 16) .and_then(char::from_u32) .map(|x| (x, len as int)) } @@ -402,10 +402,10 @@ pub fn char_lit(lit: &str) -> (char, int) { let unicode_escape: || -> Option<(char, int)> = || if lit.as_bytes()[2] == b'{' { let idx = lit.find('}').expect(msg2); - let subslice = lit.slice(3, idx); + let subslice = lit[3..idx]; num::from_str_radix(subslice, 16) .and_then(char::from_u32) - .map(|x| (x, subslice.char_len() as int + 4)) + .map(|x| (x, subslice.chars().count() as int + 4)) } else { esc(6, lit) }; @@ -429,7 +429,7 @@ pub fn str_lit(lit: &str) -> String { let error = |i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace - fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharOffsets<'a>>) { + fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharIndices<'a>>) { loop { match it.peek().map(|x| x.1) { Some(' ') | Some('\n') | Some('\r') | Some('\t') => { @@ -464,7 +464,7 @@ pub fn str_lit(lit: &str) -> String { eat(&mut chars); } else { // otherwise, a normal escape - let (c, n) = char_lit(lit.slice_from(i)); + let (c, n) = char_lit(lit[i..]); for _ in range(0, n - 1) { // we don't need to move past the first \ chars.next(); } @@ -527,7 +527,7 @@ pub fn raw_str_lit(lit: &str) -> String { fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 && first_chars.contains(&s.char_at(0)) && - s.slice_from(1).chars().all(|c| '0' <= c && c <= '9') + s[1..].chars().all(|c| '0' <= c && c <= '9') } fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, @@ -540,7 +540,7 @@ fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { // if it looks like a width, lets try to be helpful. sd.span_err(sp, &*format!("illegal width `{}` for float literal, \ - valid widths are 32 and 64", suf.slice_from(1))); + valid widths are 32 and 64", suf[1..])); } else { sd.span_err(sp, &*format!("illegal suffix `{}` for float literal, \ valid suffixes are `f32` and `f64`", suf)); @@ -576,7 +576,7 @@ pub fn byte_lit(lit: &str) -> (u8, uint) { b'\'' => b'\'', b'0' => b'\0', _ => { - match ::std::num::from_str_radix::(lit.slice(2, 4), 16) { + match ::std::num::from_str_radix::(lit[2..4], 16) { Some(c) => if c > 0xFF { panic!(err(2)) @@ -626,7 +626,7 @@ pub fn binary_lit(lit: &str) -> Rc> { } _ => { // otherwise, a normal escape - let (c, n) = byte_lit(lit.slice_from(i)); + let (c, n) = byte_lit(lit[i..]); // we don't need to move past the first \ for _ in range(0, n - 1) { chars.next(); @@ -655,7 +655,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> // s can only be ascii, byte indexing is fine let s2 = s.chars().filter(|&c| c != '_').collect::(); - let mut s = s2.as_slice(); + let mut s = s2[]; debug!("integer_lit: {}, {}", s, suffix); @@ -688,7 +688,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> } if base != 10 { - s = s.slice_from(2); + s = s[2..]; } if let Some(suf) = suffix { @@ -710,7 +710,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> if looks_like_width_suffix(&['i', 'u'], suf) { sd.span_err(sp, &*format!("illegal width `{}` for integer literal; \ valid widths are 8, 16, 32 and 64", - suf.slice_from(1))); + suf[1..])); } else { sd.span_err(sp, &*format!("illegal suffix `{}` for numeric literal", suf)); } @@ -808,7 +808,7 @@ mod test { #[test] fn string_to_tts_macro () { let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_string()); - let tts: &[ast::TokenTree] = tts.as_slice(); + let tts: &[ast::TokenTree] = tts[]; match tts { [ast::TtToken(_, token::Ident(name_macro_rules, token::Plain)), ast::TtToken(_, token::Not), @@ -816,19 +816,19 @@ mod test { ast::TtDelimited(_, ref macro_delimed)] if name_macro_rules.as_str() == "macro_rules" && name_zip.as_str() == "zip" => { - match macro_delimed.tts.as_slice() { + match macro_delimed.tts[] { [ast::TtDelimited(_, ref first_delimed), ast::TtToken(_, token::FatArrow), ast::TtDelimited(_, ref second_delimed)] if macro_delimed.delim == token::Paren => { - match first_delimed.tts.as_slice() { + match first_delimed.tts[] { [ast::TtToken(_, token::Dollar), ast::TtToken(_, token::Ident(name, token::Plain))] if first_delimed.delim == token::Paren && name.as_str() == "a" => {}, _ => panic!("value 3: {}", **first_delimed), } - match second_delimed.tts.as_slice() { + match second_delimed.tts[] { [ast::TtToken(_, token::Dollar), ast::TtToken(_, token::Ident(name, token::Plain))] if second_delimed.delim == token::Paren @@ -1106,24 +1106,24 @@ mod test { let use_s = "use foo::bar::baz;"; let vitem = string_to_view_item(use_s.to_string()); let vitem_s = view_item_to_string(&vitem); - assert_eq!(vitem_s.as_slice(), use_s); + assert_eq!(vitem_s[], use_s); let use_s = "use foo::bar as baz;"; let vitem = string_to_view_item(use_s.to_string()); let vitem_s = view_item_to_string(&vitem); - assert_eq!(vitem_s.as_slice(), use_s); + assert_eq!(vitem_s[], use_s); } #[test] fn parse_extern_crate() { let ex_s = "extern crate foo;"; let vitem = string_to_view_item(ex_s.to_string()); let vitem_s = view_item_to_string(&vitem); - assert_eq!(vitem_s.as_slice(), ex_s); + assert_eq!(vitem_s[], ex_s); let ex_s = "extern crate \"foo\" as bar;"; let vitem = string_to_view_item(ex_s.to_string()); let vitem_s = view_item_to_string(&vitem); - assert_eq!(vitem_s.as_slice(), ex_s); + assert_eq!(vitem_s[], ex_s); } fn get_spans_of_pat_idents(src: &str) -> Vec { @@ -1161,9 +1161,9 @@ mod test { for &src in srcs.iter() { let spans = get_spans_of_pat_idents(src); let Span{lo:lo,hi:hi,..} = spans[0]; - assert!("self" == src.slice(lo.to_uint(), hi.to_uint()), + assert!("self" == src[lo.to_uint()..hi.to_uint()], "\"{}\" != \"self\". src=\"{}\"", - src.slice(lo.to_uint(), hi.to_uint()), src) + src[lo.to_uint()..hi.to_uint()], src) } } @@ -1202,7 +1202,7 @@ mod test { let docs = item.attrs.iter().filter(|a| a.name().get() == "doc") .map(|a| a.value_str().unwrap().get().to_string()).collect::>(); let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; - assert_eq!(docs.as_slice(), b); + assert_eq!(docs[], b); let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name, source, Vec::new(), &sess).unwrap(); diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index a6ddcbf9ac4..e3c831c09ba 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -113,13 +113,13 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { kind_str: &str, desc: &str) { self.span_err(sp, - format!("obsolete syntax: {}", kind_str).as_slice()); + format!("obsolete syntax: {}", kind_str)[]); if !self.obsolete_set.contains(&kind) { self.sess .span_diagnostic .handler() - .note(format!("{}", desc).as_slice()); + .note(format!("{}", desc)[]); self.obsolete_set.insert(kind); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 19af118b190..7e53b28a09c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -319,7 +319,7 @@ impl TokenType { fn to_string(&self) -> String { match *self { TokenType::Token(ref t) => format!("`{}`", Parser::token_to_string(t)), - TokenType::Operator => "an operator".into_string(), + TokenType::Operator => "an operator".to_string(), } } } @@ -384,12 +384,12 @@ impl<'a> Parser<'a> { let token_str = Parser::token_to_string(t); let last_span = self.last_span; self.span_fatal(last_span, format!("unexpected token: `{}`", - token_str).as_slice()); + token_str)[]); } pub fn unexpected(&mut self) -> ! { let this_token = self.this_token_to_string(); - self.fatal(format!("unexpected token: `{}`", this_token).as_slice()); + self.fatal(format!("unexpected token: `{}`", this_token)[]); } /// Expect and consume the token t. Signal an error if @@ -403,7 +403,7 @@ impl<'a> Parser<'a> { let this_token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, found `{}`", token_str, - this_token_str).as_slice()) + this_token_str)[]) } } else { self.expect_one_of(slice::ref_slice(t), &[]); @@ -420,7 +420,7 @@ impl<'a> Parser<'a> { let mut i = tokens.iter(); // This might be a sign we need a connect method on Iterator. let b = i.next() - .map_or("".into_string(), |t| t.to_string()); + .map_or("".to_string(), |t| t.to_string()); i.enumerate().fold(b, |mut b, (i, ref a)| { if tokens.len() > 2 && i == tokens.len() - 2 { b.push_str(", or "); @@ -444,7 +444,7 @@ impl<'a> Parser<'a> { expected.push_all(&*self.expected_tokens); expected.sort_by(|a, b| a.to_string().cmp(&b.to_string())); expected.dedup(); - let expect = tokens_to_string(expected.as_slice()); + let expect = tokens_to_string(expected[]); let actual = self.this_token_to_string(); self.fatal( (if expected.len() != 1 { @@ -455,7 +455,7 @@ impl<'a> Parser<'a> { (format!("expected {}, found `{}`", expect, actual)) - }).as_slice() + })[] ) } } @@ -488,7 +488,7 @@ impl<'a> Parser<'a> { // might be unit-struct construction; check for recoverableinput error. let mut expected = edible.iter().map(|x| x.clone()).collect::>(); expected.push_all(inedible); - self.check_for_erroneous_unit_struct_expecting(expected.as_slice()); + self.check_for_erroneous_unit_struct_expecting(expected[]); } self.expect_one_of(edible, inedible) } @@ -505,9 +505,9 @@ impl<'a> Parser<'a> { .as_ref() .map_or(false, |t| t.is_ident() || t.is_path()) { let mut expected = edible.iter().map(|x| x.clone()).collect::>(); - expected.push_all(inedible.as_slice()); + expected.push_all(inedible[]); self.check_for_erroneous_unit_struct_expecting( - expected.as_slice()); + expected[]); } self.expect_one_of(edible, inedible) } @@ -530,7 +530,7 @@ impl<'a> Parser<'a> { _ => { let token_str = self.this_token_to_string(); self.fatal((format!("expected ident, found `{}`", - token_str)).as_slice()) + token_str))[]) } } } @@ -584,7 +584,7 @@ impl<'a> Parser<'a> { let id_interned_str = token::get_name(kw.to_name()); let token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, found `{}`", - id_interned_str, token_str).as_slice()) + id_interned_str, token_str)[]) } } @@ -595,7 +595,7 @@ impl<'a> Parser<'a> { let span = self.span; self.span_err(span, format!("expected identifier, found keyword `{}`", - token_str).as_slice()); + token_str)[]); } } @@ -604,7 +604,7 @@ impl<'a> Parser<'a> { if self.token.is_reserved_keyword() { let token_str = self.this_token_to_string(); self.fatal(format!("`{}` is a reserved keyword", - token_str).as_slice()) + token_str)[]) } } @@ -624,7 +624,7 @@ impl<'a> Parser<'a> { Parser::token_to_string(&token::BinOp(token::And)); self.fatal(format!("expected `{}`, found `{}`", found_token, - token_str).as_slice()) + token_str)[]) } } } @@ -645,7 +645,7 @@ impl<'a> Parser<'a> { Parser::token_to_string(&token::BinOp(token::Or)); self.fatal(format!("expected `{}`, found `{}`", token_str, - found_token).as_slice()) + found_token)[]) } } } @@ -711,7 +711,7 @@ impl<'a> Parser<'a> { let token_str = Parser::token_to_string(&token::Lt); self.fatal(format!("expected `{}`, found `{}`", token_str, - found_token).as_slice()) + found_token)[]) } } @@ -763,7 +763,7 @@ impl<'a> Parser<'a> { let this_token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, found `{}`", gt_str, - this_token_str).as_slice()) + this_token_str)[]) } } } @@ -1392,7 +1392,7 @@ impl<'a> Parser<'a> { let (inner_attrs, body) = p.parse_inner_attrs_and_block(); let mut attrs = attrs; - attrs.push_all(inner_attrs.as_slice()); + attrs.push_all(inner_attrs[]); ProvidedMethod(P(ast::Method { attrs: attrs, id: ast::DUMMY_NODE_ID, @@ -1411,7 +1411,7 @@ impl<'a> Parser<'a> { _ => { let token_str = p.this_token_to_string(); p.fatal((format!("expected `;` or `{{`, found `{}`", - token_str)).as_slice()) + token_str))[]) } } } @@ -1606,7 +1606,7 @@ impl<'a> Parser<'a> { } else { let this_token_str = self.this_token_to_string(); let msg = format!("expected type, found `{}`", this_token_str); - self.fatal(msg.as_slice()); + self.fatal(msg[]); }; let sp = mk_sp(lo, self.last_span.hi); @@ -1753,14 +1753,14 @@ impl<'a> Parser<'a> { token::Str_(s) => { (true, - LitStr(token::intern_and_get_ident(parse::str_lit(s.as_str()).as_slice()), + LitStr(token::intern_and_get_ident(parse::str_lit(s.as_str())[]), ast::CookedStr)) } token::StrRaw(s, n) => { (true, LitStr( token::intern_and_get_ident( - parse::raw_str_lit(s.as_str()).as_slice()), + parse::raw_str_lit(s.as_str())[]), ast::RawStr(n))) } token::Binary(i) => @@ -2004,7 +2004,7 @@ impl<'a> Parser<'a> { }; } _ => { - self.fatal(format!("expected a lifetime name").as_slice()); + self.fatal(format!("expected a lifetime name")[]); } } } @@ -2042,7 +2042,7 @@ impl<'a> Parser<'a> { let msg = format!("expected `,` or `>` after lifetime \ name, found `{}`", this_token_str); - self.fatal(msg.as_slice()); + self.fatal(msg[]); } } } @@ -2517,7 +2517,7 @@ impl<'a> Parser<'a> { hi = self.span.hi; self.bump(); - let index = from_str::(n.as_str()); + let index = n.as_str().parse::(); match index { Some(n) => { let id = spanned(dot, hi, n); @@ -2535,16 +2535,16 @@ impl<'a> Parser<'a> { let last_span = self.last_span; let fstr = n.as_str(); self.span_err(last_span, - format!("unexpected token: `{}`", n.as_str()).as_slice()); + format!("unexpected token: `{}`", n.as_str())[]); if fstr.chars().all(|x| "0123456789.".contains_char(x)) { - let float = match from_str::(fstr) { + let float = match fstr.parse::() { Some(f) => f, None => continue, }; self.span_help(last_span, format!("try parenthesizing the first index; e.g., `(foo.{}){}`", float.trunc() as uint, - float.fract().to_string()[1..]).as_slice()); + float.fract().to_string()[1..])[]); } self.abort_if_errors(); @@ -2716,7 +2716,7 @@ impl<'a> Parser<'a> { }; let token_str = p.this_token_to_string(); p.fatal(format!("incorrect close delimiter: `{}`", - token_str).as_slice()) + token_str)[]) }, /* we ought to allow different depths of unquotation */ token::Dollar if p.quote_depth > 0u => { @@ -2734,7 +2734,7 @@ impl<'a> Parser<'a> { let seq = match seq { Spanned { node, .. } => node, }; - let name_num = macro_parser::count_names(seq.as_slice()); + let name_num = macro_parser::count_names(seq[]); TtSequence(mk_sp(sp.lo, p.span.hi), Rc::new(SequenceRepetition { tts: seq, @@ -2885,7 +2885,7 @@ impl<'a> Parser<'a> { let this_token_to_string = self.this_token_to_string(); self.span_err(span, format!("expected expression, found `{}`", - this_token_to_string).as_slice()); + this_token_to_string)[]); let box_span = mk_sp(lo, self.last_span.hi); self.span_help(box_span, "perhaps you meant `box() (foo)` instead?"); @@ -3264,7 +3264,7 @@ impl<'a> Parser<'a> { if self.token != token::CloseDelim(token::Brace) { let token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, found `{}`", "}", - token_str).as_slice()) + token_str)[]) } etc = true; break; @@ -3285,7 +3285,7 @@ impl<'a> Parser<'a> { BindByRef(..) | BindByValue(MutMutable) => { let token_str = self.this_token_to_string(); self.fatal(format!("unexpected `{}`", - token_str).as_slice()) + token_str)[]) } _ => {} } @@ -3563,7 +3563,7 @@ impl<'a> Parser<'a> { let span = self.span; let tok_str = self.this_token_to_string(); self.span_fatal(span, - format!("expected identifier, found `{}`", tok_str).as_slice()); + format!("expected identifier, found `{}`", tok_str)[]); } let ident = self.parse_ident(); let last_span = self.last_span; @@ -3664,7 +3664,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; if self.token.is_keyword(keywords::Let) { - check_expected_item(self, item_attrs.as_slice()); + check_expected_item(self, item_attrs[]); self.expect_keyword(keywords::Let); let decl = self.parse_let(); P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) @@ -3673,7 +3673,7 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |t| *t == token::Not) { // it's a macro invocation: - check_expected_item(self, item_attrs.as_slice()); + check_expected_item(self, item_attrs[]); // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... @@ -3701,7 +3701,7 @@ impl<'a> Parser<'a> { let tok_str = self.this_token_to_string(); self.fatal(format!("expected {}`(` or `{{`, found `{}`", ident_str, - tok_str).as_slice()) + tok_str)[]) }, }; @@ -3749,7 +3749,7 @@ impl<'a> Parser<'a> { } } else { let found_attrs = !item_attrs.is_empty(); - let item_err = Parser::expected_item_err(item_attrs.as_slice()); + let item_err = Parser::expected_item_err(item_attrs[]); match self.parse_item_or_view_item(item_attrs, false) { IoviItem(i) => { let hi = i.span.hi; @@ -3793,7 +3793,7 @@ impl<'a> Parser<'a> { let sp = self.span; let tok = self.this_token_to_string(); self.span_fatal_help(sp, - format!("expected `{{`, found `{}`", tok).as_slice(), + format!("expected `{{`, found `{}`", tok)[], "place this code inside a block"); } @@ -3847,13 +3847,13 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Brace) { // parsing items even when they're not allowed lets us give // better error messages and recover more gracefully. - attributes_box.push_all(self.parse_outer_attributes().as_slice()); + attributes_box.push_all(self.parse_outer_attributes()[]); match self.token { token::Semi => { if !attributes_box.is_empty() { let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(attributes_box.as_slice())); + Parser::expected_item_err(attributes_box[])); attributes_box = Vec::new(); } self.bump(); // empty @@ -3944,7 +3944,7 @@ impl<'a> Parser<'a> { if !attributes_box.is_empty() { let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(attributes_box.as_slice())); + Parser::expected_item_err(attributes_box[])); } let hi = self.span.hi; @@ -4362,7 +4362,7 @@ impl<'a> Parser<'a> { _ => { let token_str = self.this_token_to_string(); self.fatal(format!("expected `self`, found `{}`", - token_str).as_slice()) + token_str)[]) } } } @@ -4516,7 +4516,7 @@ impl<'a> Parser<'a> { _ => { let token_str = self.this_token_to_string(); self.fatal(format!("expected `,` or `)`, found `{}`", - token_str).as_slice()) + token_str)[]) } } } @@ -4692,7 +4692,7 @@ impl<'a> Parser<'a> { let (inner_attrs, body) = self.parse_inner_attrs_and_block(); let body_span = body.span; let mut new_attrs = attrs; - new_attrs.push_all(inner_attrs.as_slice()); + new_attrs.push_all(inner_attrs[]); (ast::MethDecl(ident, generics, abi, @@ -4849,7 +4849,7 @@ impl<'a> Parser<'a> { if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be \ written as `struct {};`", - token::get_ident(class_name)).as_slice()); + token::get_ident(class_name))[]); } self.bump(); } else if self.check(&token::OpenDelim(token::Paren)) { @@ -4873,7 +4873,7 @@ impl<'a> Parser<'a> { if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be \ written as `struct {};`", - token::get_ident(class_name)).as_slice()); + token::get_ident(class_name))[]); } self.expect(&token::Semi); } else if self.eat(&token::Semi) { @@ -4884,7 +4884,7 @@ impl<'a> Parser<'a> { let token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, `(`, or `;` after struct \ name, found `{}`", "{", - token_str).as_slice()) + token_str)[]) } let _ = ast::DUMMY_NODE_ID; // FIXME: Workaround for crazy bug. @@ -4913,7 +4913,7 @@ impl<'a> Parser<'a> { let token_str = self.this_token_to_string(); self.span_fatal_help(span, format!("expected `,`, or `}}`, found `{}`", - token_str).as_slice(), + token_str)[], "struct fields should be separated by commas") } } @@ -4983,7 +4983,7 @@ impl<'a> Parser<'a> { let mut attrs = self.parse_outer_attributes(); if first { let mut tmp = attrs_remaining.clone(); - tmp.push_all(attrs.as_slice()); + tmp.push_all(attrs[]); attrs = tmp; first = false; } @@ -5000,7 +5000,7 @@ impl<'a> Parser<'a> { _ => { let token_str = self.this_token_to_string(); self.fatal(format!("expected item, found `{}`", - token_str).as_slice()) + token_str)[]) } } } @@ -5009,7 +5009,7 @@ impl<'a> Parser<'a> { // We parsed attributes for the first item but didn't find it let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(attrs_remaining.as_slice())); + Parser::expected_item_err(attrs_remaining[])); } ast::Mod { @@ -5079,7 +5079,7 @@ impl<'a> Parser<'a> { -> (ast::Item_, Vec ) { let mut prefix = Path::new(self.sess.span_diagnostic.cm.span_to_filename(self.span)); prefix.pop(); - let mod_path = Path::new(".").join_many(self.mod_path_stack.as_slice()); + let mod_path = Path::new(".").join_many(self.mod_path_stack[]); let dir_path = prefix.join(&mod_path); let mod_string = token::get_ident(id); let (file_path, owns_directory) = match ::attr::first_attr_value_str_by_name( @@ -5089,8 +5089,8 @@ impl<'a> Parser<'a> { let mod_name = mod_string.get().to_string(); let default_path_str = format!("{}.rs", mod_name); let secondary_path_str = format!("{}/mod.rs", mod_name); - let default_path = dir_path.join(default_path_str.as_slice()); - let secondary_path = dir_path.join(secondary_path_str.as_slice()); + let default_path = dir_path.join(default_path_str[]); + let secondary_path = dir_path.join(secondary_path_str[]); let default_exists = default_path.exists(); let secondary_exists = secondary_path.exists(); @@ -5105,13 +5105,13 @@ impl<'a> Parser<'a> { format!("maybe move this module `{0}` \ to its own directory via \ `{0}/mod.rs`", - this_module).as_slice()); + this_module)[]); if default_exists || secondary_exists { self.span_note(id_sp, format!("... or maybe `use` the module \ `{}` instead of possibly \ redeclaring it", - mod_name).as_slice()); + mod_name)[]); } self.abort_if_errors(); } @@ -5122,12 +5122,12 @@ impl<'a> Parser<'a> { (false, false) => { self.span_fatal_help(id_sp, format!("file not found for module `{}`", - mod_name).as_slice(), + mod_name)[], format!("name the file either {} or {} inside \ the directory {}", default_path_str, secondary_path_str, - dir_path.display()).as_slice()); + dir_path.display())[]); } (true, true) => { self.span_fatal_help( @@ -5136,7 +5136,7 @@ impl<'a> Parser<'a> { and {}", mod_name, default_path_str, - secondary_path_str).as_slice(), + secondary_path_str)[], "delete or rename one of them to remove the ambiguity"); } } @@ -5158,11 +5158,11 @@ impl<'a> Parser<'a> { let mut err = String::from_str("circular modules: "); let len = included_mod_stack.len(); for p in included_mod_stack.slice(i, len).iter() { - err.push_str(p.display().as_cow().as_slice()); + err.push_str(p.display().as_cow()[]); err.push_str(" -> "); } - err.push_str(path.display().as_cow().as_slice()); - self.span_fatal(id_sp, err.as_slice()); + err.push_str(path.display().as_cow()[]); + self.span_fatal(id_sp, err[]); } None => () } @@ -5243,7 +5243,7 @@ impl<'a> Parser<'a> { if !attrs_remaining.is_empty() { let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(attrs_remaining.as_slice())); + Parser::expected_item_err(attrs_remaining[])); } assert!(self.token == token::CloseDelim(token::Brace)); ast::ForeignMod { @@ -5284,7 +5284,7 @@ impl<'a> Parser<'a> { self.span_help(span, format!("perhaps you meant to enclose the crate name `{}` in \ a string?", - the_ident.as_str()).as_slice()); + the_ident.as_str())[]); None } else { None @@ -5310,7 +5310,7 @@ impl<'a> Parser<'a> { self.span_fatal(span, format!("expected extern crate name but \ found `{}`", - token_str).as_slice()); + token_str)[]); } }; @@ -5408,7 +5408,7 @@ impl<'a> Parser<'a> { self.span_err(start_span, format!("unit-like struct variant should be written \ without braces, as `{},`", - token::get_ident(ident)).as_slice()); + token::get_ident(ident))[]); } kind = StructVariantKind(struct_def); } else if self.check(&token::OpenDelim(token::Paren)) { @@ -5493,7 +5493,7 @@ impl<'a> Parser<'a> { format!("illegal ABI: expected one of [{}], \ found `{}`", abi::all_names().connect(", "), - the_string).as_slice()); + the_string)[]); None } } @@ -5555,7 +5555,7 @@ impl<'a> Parser<'a> { format!("`extern mod` is obsolete, use \ `extern crate` instead \ to refer to external \ - crates.").as_slice()) + crates.")[]) } return self.parse_item_extern_crate(lo, visibility, attrs); } @@ -5583,7 +5583,7 @@ impl<'a> Parser<'a> { let token_str = self.this_token_to_string(); self.span_fatal(span, format!("expected `{}` or `fn`, found `{}`", "{", - token_str).as_slice()); + token_str)[]); } if self.eat_keyword(keywords::Virtual) { @@ -5696,7 +5696,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::Mod) { // MODULE ITEM let (ident, item_, extra_attrs) = - self.parse_item_mod(attrs.as_slice()); + self.parse_item_mod(attrs[]); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -6031,7 +6031,7 @@ impl<'a> Parser<'a> { macros_allowed: bool) -> ParsedItemsAndViewItems { let mut attrs = first_item_attrs; - attrs.push_all(self.parse_outer_attributes().as_slice()); + attrs.push_all(self.parse_outer_attributes()[]); // First, parse view items. let mut view_items : Vec = Vec::new(); let mut items = Vec::new(); @@ -6113,7 +6113,7 @@ impl<'a> Parser<'a> { macros_allowed: bool) -> ParsedItemsAndViewItems { let mut attrs = first_item_attrs; - attrs.push_all(self.parse_outer_attributes().as_slice()); + attrs.push_all(self.parse_outer_attributes()[]); let mut foreign_items = Vec::new(); loop { match self.parse_foreign_item(attrs, macros_allowed) { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index dad369792d7..9e61eaae352 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -454,7 +454,7 @@ macro_rules! declare_special_idents_and_keywords {( $(init_vec.push($si_str);)* $(init_vec.push($sk_str);)* $(init_vec.push($rk_str);)* - interner::StrInterner::prefill(init_vec.as_slice()) + interner::StrInterner::prefill(init_vec[]) } }} @@ -602,10 +602,14 @@ impl InternedString { #[inline] pub fn get<'a>(&'a self) -> &'a str { - self.string.as_slice() + self.string[] } } +impl Deref for InternedString { + fn deref(&self) -> &str { &*self.string } +} + impl BytesContainer for InternedString { fn container_as_bytes<'a>(&'a self) -> &'a [u8] { // FIXME #12938: This is a workaround for the incorrect signature @@ -620,49 +624,49 @@ impl BytesContainer for InternedString { impl fmt::Show for InternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.string.as_slice()) + write!(f, "{}", self.string[]) } } #[allow(deprecated)] impl<'a> Equiv<&'a str> for InternedString { fn equiv(&self, other: & &'a str) -> bool { - (*other) == self.string.as_slice() + (*other) == self.string[] } } impl<'a> PartialEq<&'a str> for InternedString { #[inline(always)] fn eq(&self, other: & &'a str) -> bool { - PartialEq::eq(self.string.as_slice(), *other) + PartialEq::eq(self.string[], *other) } #[inline(always)] fn ne(&self, other: & &'a str) -> bool { - PartialEq::ne(self.string.as_slice(), *other) + PartialEq::ne(self.string[], *other) } } impl<'a> PartialEq for &'a str { #[inline(always)] fn eq(&self, other: &InternedString) -> bool { - PartialEq::eq(*self, other.string.as_slice()) + PartialEq::eq(*self, other.string[]) } #[inline(always)] fn ne(&self, other: &InternedString) -> bool { - PartialEq::ne(*self, other.string.as_slice()) + PartialEq::ne(*self, other.string[]) } } impl, E> Decodable for InternedString { fn decode(d: &mut D) -> Result { Ok(get_name(get_ident_interner().intern( - try!(d.read_str()).as_slice()))) + try!(d.read_str())[]))) } } impl, E> Encodable for InternedString { fn encode(&self, s: &mut S) -> Result<(), E> { - s.emit_str(self.string.as_slice()) + s.emit_str(self.string[]) } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index bfa47a46e74..ab0e0f9585c 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -139,12 +139,12 @@ pub fn buf_str(toks: Vec, } s.push_str(format!("{}={}", szs[i], - tok_str(toks[i].clone())).as_slice()); + tok_str(toks[i].clone()))[]); i += 1u; i %= n; } s.push(']'); - return s.into_string(); + s } #[deriving(Copy)] @@ -601,7 +601,7 @@ impl Printer { assert_eq!(l, len); // assert!(l <= space); self.space -= len; - self.print_str(s.as_slice()) + self.print_str(s[]) } Eof => { // Eof should never get here. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a9717a526ad..0d79b7cf925 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -30,6 +30,7 @@ use ptr::P; use std::{ascii, mem}; use std::io::{mod, IoResult}; +use std::iter; pub enum AnnNode<'a> { NodeIdent(&'a ast::Ident), @@ -113,7 +114,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, out, ann, is_expanded); - try!(s.print_mod(&krate.module, krate.attrs.as_slice())); + try!(s.print_mod(&krate.module, krate.attrs[])); try!(s.print_remaining_comments()); eof(&mut s.s) } @@ -197,56 +198,56 @@ pub fn binop_to_string(op: BinOpToken) -> &'static str { pub fn token_to_string(tok: &Token) -> String { match *tok { - token::Eq => "=".into_string(), - token::Lt => "<".into_string(), - token::Le => "<=".into_string(), - token::EqEq => "==".into_string(), - token::Ne => "!=".into_string(), - token::Ge => ">=".into_string(), - token::Gt => ">".into_string(), - token::Not => "!".into_string(), - token::Tilde => "~".into_string(), - token::OrOr => "||".into_string(), - token::AndAnd => "&&".into_string(), - token::BinOp(op) => binop_to_string(op).into_string(), + token::Eq => "=".to_string(), + token::Lt => "<".to_string(), + token::Le => "<=".to_string(), + token::EqEq => "==".to_string(), + token::Ne => "!=".to_string(), + token::Ge => ">=".to_string(), + token::Gt => ">".to_string(), + token::Not => "!".to_string(), + token::Tilde => "~".to_string(), + token::OrOr => "||".to_string(), + token::AndAnd => "&&".to_string(), + token::BinOp(op) => binop_to_string(op).to_string(), token::BinOpEq(op) => format!("{}=", binop_to_string(op)), /* Structural symbols */ - token::At => "@".into_string(), - token::Dot => ".".into_string(), - token::DotDot => "..".into_string(), - token::DotDotDot => "...".into_string(), - token::Comma => ",".into_string(), - token::Semi => ";".into_string(), - token::Colon => ":".into_string(), - token::ModSep => "::".into_string(), - token::RArrow => "->".into_string(), - token::LArrow => "<-".into_string(), - token::FatArrow => "=>".into_string(), - token::OpenDelim(token::Paren) => "(".into_string(), - token::CloseDelim(token::Paren) => ")".into_string(), - token::OpenDelim(token::Bracket) => "[".into_string(), - token::CloseDelim(token::Bracket) => "]".into_string(), - token::OpenDelim(token::Brace) => "{".into_string(), - token::CloseDelim(token::Brace) => "}".into_string(), - token::Pound => "#".into_string(), - token::Dollar => "$".into_string(), - token::Question => "?".into_string(), + token::At => "@".to_string(), + token::Dot => ".".to_string(), + token::DotDot => "..".to_string(), + token::DotDotDot => "...".to_string(), + token::Comma => ",".to_string(), + token::Semi => ";".to_string(), + token::Colon => ":".to_string(), + token::ModSep => "::".to_string(), + token::RArrow => "->".to_string(), + token::LArrow => "<-".to_string(), + token::FatArrow => "=>".to_string(), + token::OpenDelim(token::Paren) => "(".to_string(), + token::CloseDelim(token::Paren) => ")".to_string(), + token::OpenDelim(token::Bracket) => "[".to_string(), + token::CloseDelim(token::Bracket) => "]".to_string(), + token::OpenDelim(token::Brace) => "{".to_string(), + token::CloseDelim(token::Brace) => "}".to_string(), + token::Pound => "#".to_string(), + token::Dollar => "$".to_string(), + token::Question => "?".to_string(), /* Literals */ token::Literal(lit, suf) => { let mut out = match lit { token::Byte(b) => format!("b'{}'", b.as_str()), token::Char(c) => format!("'{}'", c.as_str()), - token::Float(c) => c.as_str().into_string(), - token::Integer(c) => c.as_str().into_string(), + token::Float(c) => c.as_str().to_string(), + token::Integer(c) => c.as_str().to_string(), token::Str_(s) => format!("\"{}\"", s.as_str()), token::StrRaw(s, n) => format!("r{delim}\"{string}\"{delim}", - delim="#".repeat(n), + delim=repeat("#", n), string=s.as_str()), token::Binary(v) => format!("b\"{}\"", v.as_str()), token::BinaryRaw(s, n) => format!("br{delim}\"{string}\"{delim}", - delim="#".repeat(n), + delim=repeat("#", n), string=s.as_str()), }; @@ -258,17 +259,17 @@ pub fn token_to_string(tok: &Token) -> String { } /* Name components */ - token::Ident(s, _) => token::get_ident(s).get().into_string(), + token::Ident(s, _) => token::get_ident(s).get().to_string(), token::Lifetime(s) => format!("{}", token::get_ident(s)), - token::Underscore => "_".into_string(), + token::Underscore => "_".to_string(), /* Other */ - token::DocComment(s) => s.as_str().into_string(), + token::DocComment(s) => s.as_str().to_string(), token::SubstNt(s, _) => format!("${}", s), token::MatchNt(s, t, _, _) => format!("${}:{}", s, t), - token::Eof => "".into_string(), - token::Whitespace => " ".into_string(), - token::Comment => "/* */".into_string(), + token::Eof => "".to_string(), + token::Whitespace => " ".to_string(), + token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s.as_str()), token::Interpolated(ref nt) => match *nt { @@ -276,12 +277,12 @@ pub fn token_to_string(tok: &Token) -> String { token::NtMeta(ref e) => meta_item_to_string(&**e), token::NtTy(ref e) => ty_to_string(&**e), token::NtPath(ref e) => path_to_string(&**e), - token::NtItem(..) => "an interpolated item".into_string(), - token::NtBlock(..) => "an interpolated block".into_string(), - token::NtStmt(..) => "an interpolated statement".into_string(), - token::NtPat(..) => "an interpolated pattern".into_string(), - token::NtIdent(..) => "an interpolated identifier".into_string(), - token::NtTT(..) => "an interpolated tt".into_string(), + token::NtItem(..) => "an interpolated item".to_string(), + token::NtBlock(..) => "an interpolated block".to_string(), + token::NtStmt(..) => "an interpolated statement".to_string(), + token::NtPat(..) => "an interpolated pattern".to_string(), + token::NtIdent(..) => "an interpolated identifier".to_string(), + token::NtTT(..) => "an interpolated tt".to_string(), } } } @@ -577,7 +578,7 @@ impl<'a> State<'a> { pub fn synth_comment(&mut self, text: String) -> IoResult<()> { try!(word(&mut self.s, "/*")); try!(space(&mut self.s)); - try!(word(&mut self.s, text.as_slice())); + try!(word(&mut self.s, text[])); try!(space(&mut self.s)); word(&mut self.s, "*/") } @@ -682,7 +683,7 @@ impl<'a> State<'a> { } ast::TyTup(ref elts) => { try!(self.popen()); - try!(self.commasep(Inconsistent, elts.as_slice(), + try!(self.commasep(Inconsistent, elts[], |s, ty| s.print_type(&**ty))); if elts.len() == 1 { try!(word(&mut self.s, ",")); @@ -737,10 +738,10 @@ impl<'a> State<'a> { } ast::TyObjectSum(ref ty, ref bounds) => { try!(self.print_type(&**ty)); - try!(self.print_bounds("+", bounds.as_slice())); + try!(self.print_bounds("+", bounds[])); } ast::TyPolyTraitRef(ref bounds) => { - try!(self.print_bounds("", bounds.as_slice())); + try!(self.print_bounds("", bounds[])); } ast::TyQPath(ref qpath) => { try!(word(&mut self.s, "<")); @@ -775,7 +776,7 @@ impl<'a> State<'a> { item: &ast::ForeignItem) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); - try!(self.print_outer_attributes(item.attrs.as_slice())); + try!(self.print_outer_attributes(item.attrs[])); match item.node { ast::ForeignItemFn(ref decl, ref generics) => { try!(self.print_fn(&**decl, None, abi::Rust, item.ident, generics, @@ -786,7 +787,7 @@ impl<'a> State<'a> { } ast::ForeignItemStatic(ref t, m) => { try!(self.head(visibility_qualified(item.vis, - "static").as_slice())); + "static")[])); if m { try!(self.word_space("mut")); } @@ -822,12 +823,12 @@ impl<'a> State<'a> { pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); - try!(self.print_outer_attributes(item.attrs.as_slice())); + try!(self.print_outer_attributes(item.attrs[])); try!(self.ann.pre(self, NodeItem(item))); match item.node { ast::ItemStatic(ref ty, m, ref expr) => { try!(self.head(visibility_qualified(item.vis, - "static").as_slice())); + "static")[])); if m == ast::MutMutable { try!(self.word_space("mut")); } @@ -844,7 +845,7 @@ impl<'a> State<'a> { } ast::ItemConst(ref ty, ref expr) => { try!(self.head(visibility_qualified(item.vis, - "const").as_slice())); + "const")[])); try!(self.print_ident(item.ident)); try!(self.word_space(":")); try!(self.print_type(&**ty)); @@ -867,29 +868,29 @@ impl<'a> State<'a> { item.vis )); try!(word(&mut self.s, " ")); - try!(self.print_block_with_attrs(&**body, item.attrs.as_slice())); + try!(self.print_block_with_attrs(&**body, item.attrs[])); } ast::ItemMod(ref _mod) => { try!(self.head(visibility_qualified(item.vis, - "mod").as_slice())); + "mod")[])); try!(self.print_ident(item.ident)); try!(self.nbsp()); try!(self.bopen()); - try!(self.print_mod(_mod, item.attrs.as_slice())); + try!(self.print_mod(_mod, item.attrs[])); try!(self.bclose(item.span)); } ast::ItemForeignMod(ref nmod) => { try!(self.head("extern")); - try!(self.word_nbsp(nmod.abi.to_string().as_slice())); + try!(self.word_nbsp(nmod.abi.to_string()[])); try!(self.bopen()); - try!(self.print_foreign_mod(nmod, item.attrs.as_slice())); + try!(self.print_foreign_mod(nmod, item.attrs[])); try!(self.bclose(item.span)); } ast::ItemTy(ref ty, ref params) => { try!(self.ibox(indent_unit)); try!(self.ibox(0u)); try!(self.word_nbsp(visibility_qualified(item.vis, - "type").as_slice())); + "type")[])); try!(self.print_ident(item.ident)); try!(self.print_generics(params)); try!(self.end()); // end the inner ibox @@ -911,7 +912,7 @@ impl<'a> State<'a> { )); } ast::ItemStruct(ref struct_def, ref generics) => { - try!(self.head(visibility_qualified(item.vis,"struct").as_slice())); + try!(self.head(visibility_qualified(item.vis,"struct")[])); try!(self.print_struct(&**struct_def, generics, item.ident, item.span)); } @@ -944,7 +945,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.bopen()); - try!(self.print_inner_attributes(item.attrs.as_slice())); + try!(self.print_inner_attributes(item.attrs[])); for impl_item in impl_items.iter() { match *impl_item { ast::MethodImplItem(ref meth) => { @@ -970,7 +971,7 @@ impl<'a> State<'a> { try!(self.print_trait_ref(tref)); try!(word(&mut self.s, "?")); } - try!(self.print_bounds(":", bounds.as_slice())); + try!(self.print_bounds(":", bounds[])); try!(self.print_where_clause(generics)); try!(word(&mut self.s, " ")); try!(self.bopen()); @@ -988,7 +989,7 @@ impl<'a> State<'a> { try!(self.print_ident(item.ident)); try!(self.cbox(indent_unit)); try!(self.popen()); - try!(self.print_tts(tts.as_slice())); + try!(self.print_tts(tts[])); try!(self.pclose()); try!(word(&mut self.s, ";")); try!(self.end()); @@ -1022,12 +1023,12 @@ impl<'a> State<'a> { generics: &ast::Generics, ident: ast::Ident, span: codemap::Span, visibility: ast::Visibility) -> IoResult<()> { - try!(self.head(visibility_qualified(visibility, "enum").as_slice())); + try!(self.head(visibility_qualified(visibility, "enum")[])); try!(self.print_ident(ident)); try!(self.print_generics(generics)); try!(self.print_where_clause(generics)); try!(space(&mut self.s)); - self.print_variants(enum_definition.variants.as_slice(), span) + self.print_variants(enum_definition.variants[], span) } pub fn print_variants(&mut self, @@ -1037,7 +1038,7 @@ impl<'a> State<'a> { for v in variants.iter() { try!(self.space_if_not_bol()); try!(self.maybe_print_comment(v.span.lo)); - try!(self.print_outer_attributes(v.node.attrs.as_slice())); + try!(self.print_outer_attributes(v.node.attrs[])); try!(self.ibox(indent_unit)); try!(self.print_variant(&**v)); try!(word(&mut self.s, ",")); @@ -1066,7 +1067,7 @@ impl<'a> State<'a> { if !struct_def.fields.is_empty() { try!(self.popen()); try!(self.commasep( - Inconsistent, struct_def.fields.as_slice(), + Inconsistent, struct_def.fields[], |s, field| { match field.node.kind { ast::NamedField(..) => panic!("unexpected named field"), @@ -1094,7 +1095,7 @@ impl<'a> State<'a> { ast::NamedField(ident, visibility) => { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(field.span.lo)); - try!(self.print_outer_attributes(field.node.attrs.as_slice())); + try!(self.print_outer_attributes(field.node.attrs[])); try!(self.print_visibility(visibility)); try!(self.print_ident(ident)); try!(self.word_nbsp(":")); @@ -1118,7 +1119,7 @@ impl<'a> State<'a> { pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> { match *tt { ast::TtToken(_, ref tk) => { - try!(word(&mut self.s, token_to_string(tk).as_slice())); + try!(word(&mut self.s, token_to_string(tk)[])); match *tk { parse::token::DocComment(..) => { hardbreak(&mut self.s) @@ -1127,11 +1128,11 @@ impl<'a> State<'a> { } } ast::TtDelimited(_, ref delimed) => { - try!(word(&mut self.s, token_to_string(&delimed.open_token()).as_slice())); + try!(word(&mut self.s, token_to_string(&delimed.open_token())[])); try!(space(&mut self.s)); - try!(self.print_tts(delimed.tts.as_slice())); + try!(self.print_tts(delimed.tts[])); try!(space(&mut self.s)); - word(&mut self.s, token_to_string(&delimed.close_token()).as_slice()) + word(&mut self.s, token_to_string(&delimed.close_token())[]) }, ast::TtSequence(_, ref seq) => { try!(word(&mut self.s, "$(")); @@ -1141,7 +1142,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, ")")); match seq.separator { Some(ref tk) => { - try!(word(&mut self.s, token_to_string(tk).as_slice())); + try!(word(&mut self.s, token_to_string(tk)[])); } None => {}, } @@ -1172,7 +1173,7 @@ impl<'a> State<'a> { if !args.is_empty() { try!(self.popen()); try!(self.commasep(Consistent, - args.as_slice(), + args[], |s, arg| s.print_type(&*arg.ty))); try!(self.pclose()); } @@ -1196,7 +1197,7 @@ impl<'a> State<'a> { pub fn print_ty_method(&mut self, m: &ast::TypeMethod) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(m.span.lo)); - try!(self.print_outer_attributes(m.attrs.as_slice())); + try!(self.print_outer_attributes(m.attrs[])); try!(self.print_ty_fn(None, None, m.unsafety, @@ -1228,7 +1229,7 @@ impl<'a> State<'a> { pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(meth.span.lo)); - try!(self.print_outer_attributes(meth.attrs.as_slice())); + try!(self.print_outer_attributes(meth.attrs[])); match meth.node { ast::MethDecl(ident, ref generics, @@ -1246,7 +1247,7 @@ impl<'a> State<'a> { Some(&explicit_self.node), vis)); try!(word(&mut self.s, " ")); - self.print_block_with_attrs(&**body, meth.attrs.as_slice()) + self.print_block_with_attrs(&**body, meth.attrs[]) }, ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), ..}) => { @@ -1255,7 +1256,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, "! ")); try!(self.cbox(indent_unit)); try!(self.popen()); - try!(self.print_tts(tts.as_slice())); + try!(self.print_tts(tts[])); try!(self.pclose()); try!(word(&mut self.s, ";")); self.end() @@ -1522,7 +1523,7 @@ impl<'a> State<'a> { ast::ExprVec(ref exprs) => { try!(self.ibox(indent_unit)); try!(word(&mut self.s, "[")); - try!(self.commasep_exprs(Inconsistent, exprs.as_slice())); + try!(self.commasep_exprs(Inconsistent, exprs[])); try!(word(&mut self.s, "]")); try!(self.end()); } @@ -1542,7 +1543,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, "{")); try!(self.commasep_cmnt( Consistent, - fields.as_slice(), + fields[], |s, field| { try!(s.ibox(indent_unit)); try!(s.print_ident(field.ident.node)); @@ -1568,7 +1569,7 @@ impl<'a> State<'a> { } ast::ExprTup(ref exprs) => { try!(self.popen()); - try!(self.commasep_exprs(Inconsistent, exprs.as_slice())); + try!(self.commasep_exprs(Inconsistent, exprs[])); if exprs.len() == 1 { try!(word(&mut self.s, ",")); } @@ -1576,7 +1577,7 @@ impl<'a> State<'a> { } ast::ExprCall(ref func, ref args) => { try!(self.print_expr_maybe_paren(&**func)); - try!(self.print_call_post(args.as_slice())); + try!(self.print_call_post(args[])); } ast::ExprMethodCall(ident, ref tys, ref args) => { let base_args = args.slice_from(1); @@ -1585,7 +1586,7 @@ impl<'a> State<'a> { try!(self.print_ident(ident.node)); if tys.len() > 0u { try!(word(&mut self.s, "::<")); - try!(self.commasep(Inconsistent, tys.as_slice(), + try!(self.commasep(Inconsistent, tys[], |s, ty| s.print_type(&**ty))); try!(word(&mut self.s, ">")); } @@ -1795,11 +1796,11 @@ impl<'a> State<'a> { try!(self.print_string(a.asm.get(), a.asm_str_style)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, a.outputs.as_slice(), + try!(self.commasep(Inconsistent, a.outputs[], |s, &(ref co, ref o, is_rw)| { match co.get().slice_shift_char() { Some(('=', operand)) if is_rw => { - try!(s.print_string(format!("+{}", operand).as_slice(), + try!(s.print_string(format!("+{}", operand)[], ast::CookedStr)) } _ => try!(s.print_string(co.get(), ast::CookedStr)) @@ -1812,7 +1813,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, a.inputs.as_slice(), + try!(self.commasep(Inconsistent, a.inputs[], |s, &(ref co, ref o)| { try!(s.print_string(co.get(), ast::CookedStr)); try!(s.popen()); @@ -1823,7 +1824,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, a.clobbers.as_slice(), + try!(self.commasep(Inconsistent, a.clobbers[], |s, co| { try!(s.print_string(co.get(), ast::CookedStr)); Ok(()) @@ -1877,7 +1878,7 @@ impl<'a> State<'a> { pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> { if self.encode_idents_with_hygiene { let encoded = ident.encode_with_hygiene(); - try!(word(&mut self.s, encoded.as_slice())) + try!(word(&mut self.s, encoded[])) } else { try!(word(&mut self.s, token::get_ident(ident).get())) } @@ -1885,7 +1886,7 @@ impl<'a> State<'a> { } pub fn print_uint(&mut self, i: uint) -> IoResult<()> { - word(&mut self.s, i.to_string().as_slice()) + word(&mut self.s, i.to_string()[]) } pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> { @@ -1959,7 +1960,7 @@ impl<'a> State<'a> { } try!(self.commasep( Inconsistent, - data.types.as_slice(), + data.types[], |s, ty| s.print_type(&**ty))); comma = true; } @@ -1982,7 +1983,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, "(")); try!(self.commasep( Inconsistent, - data.inputs.as_slice(), + data.inputs[], |s, ty| s.print_type(&**ty))); try!(word(&mut self.s, ")")); @@ -2035,7 +2036,7 @@ impl<'a> State<'a> { Some(ref args) => { if !args.is_empty() { try!(self.popen()); - try!(self.commasep(Inconsistent, args.as_slice(), + try!(self.commasep(Inconsistent, args[], |s, p| s.print_pat(&**p))); try!(self.pclose()); } @@ -2047,7 +2048,7 @@ impl<'a> State<'a> { try!(self.nbsp()); try!(self.word_space("{")); try!(self.commasep_cmnt( - Consistent, fields.as_slice(), + Consistent, fields[], |s, f| { try!(s.cbox(indent_unit)); if !f.node.is_shorthand { @@ -2068,7 +2069,7 @@ impl<'a> State<'a> { ast::PatTup(ref elts) => { try!(self.popen()); try!(self.commasep(Inconsistent, - elts.as_slice(), + elts[], |s, p| s.print_pat(&**p))); if elts.len() == 1 { try!(word(&mut self.s, ",")); @@ -2093,7 +2094,7 @@ impl<'a> State<'a> { ast::PatVec(ref before, ref slice, ref after) => { try!(word(&mut self.s, "[")); try!(self.commasep(Inconsistent, - before.as_slice(), + before[], |s, p| s.print_pat(&**p))); for p in slice.iter() { if !before.is_empty() { try!(self.word_space(",")); } @@ -2107,7 +2108,7 @@ impl<'a> State<'a> { if !after.is_empty() { try!(self.word_space(",")); } } try!(self.commasep(Inconsistent, - after.as_slice(), + after[], |s, p| s.print_pat(&**p))); try!(word(&mut self.s, "]")); } @@ -2124,7 +2125,7 @@ impl<'a> State<'a> { } try!(self.cbox(indent_unit)); try!(self.ibox(0u)); - try!(self.print_outer_attributes(arm.attrs.as_slice())); + try!(self.print_outer_attributes(arm.attrs[])); let mut first = true; for p in arm.pats.iter() { if first { @@ -2224,7 +2225,7 @@ impl<'a> State<'a> { // HACK(eddyb) ignore the separately printed self argument. let args = if first { - decl.inputs.as_slice() + decl.inputs[] } else { decl.inputs.slice_from(1) }; @@ -2386,7 +2387,7 @@ impl<'a> State<'a> { ints.push(i); } - try!(self.commasep(Inconsistent, ints.as_slice(), |s, &idx| { + try!(self.commasep(Inconsistent, ints[], |s, &idx| { if idx < generics.lifetimes.len() { let lifetime = &generics.lifetimes[idx]; s.print_lifetime_def(lifetime) @@ -2407,7 +2408,7 @@ impl<'a> State<'a> { try!(self.word_space("?")); } try!(self.print_ident(param.ident)); - try!(self.print_bounds(":", param.bounds.as_slice())); + try!(self.print_bounds(":", param.bounds[])); match param.default { Some(ref default) => { try!(space(&mut self.s)); @@ -2483,7 +2484,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, name.get())); try!(self.popen()); try!(self.commasep(Consistent, - items.as_slice(), + items[], |s, i| s.print_meta_item(&**i))); try!(self.pclose()); } @@ -2519,7 +2520,7 @@ impl<'a> State<'a> { try!(self.print_path(path, false)); try!(word(&mut self.s, "::{")); } - try!(self.commasep(Inconsistent, idents.as_slice(), |s, w| { + try!(self.commasep(Inconsistent, idents[], |s, w| { match w.node { ast::PathListIdent { name, .. } => { s.print_ident(name) @@ -2537,7 +2538,7 @@ impl<'a> State<'a> { pub fn print_view_item(&mut self, item: &ast::ViewItem) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); - try!(self.print_outer_attributes(item.attrs.as_slice())); + try!(self.print_outer_attributes(item.attrs[])); try!(self.print_visibility(item.vis)); match item.node { ast::ViewItemExternCrate(id, ref optional_path, _) => { @@ -2679,7 +2680,7 @@ impl<'a> State<'a> { try!(self.pclose()); } - try!(self.print_bounds(":", bounds.as_slice())); + try!(self.print_bounds(":", bounds[])); try!(self.print_fn_output(decl)); @@ -2738,7 +2739,7 @@ impl<'a> State<'a> { try!(self.maybe_print_comment(lit.span.lo)); match self.next_lit(lit.span.lo) { Some(ref ltrl) => { - return word(&mut self.s, (*ltrl).lit.as_slice()); + return word(&mut self.s, (*ltrl).lit[]); } _ => () } @@ -2748,7 +2749,7 @@ impl<'a> State<'a> { let mut res = String::from_str("b'"); ascii::escape_default(byte, |c| res.push(c as char)); res.push('\''); - word(&mut self.s, res.as_slice()) + word(&mut self.s, res[]) } ast::LitChar(ch) => { let mut res = String::from_str("'"); @@ -2756,27 +2757,27 @@ impl<'a> State<'a> { res.push(c); } res.push('\''); - word(&mut self.s, res.as_slice()) + word(&mut self.s, res[]) } ast::LitInt(i, t) => { match t { ast::SignedIntLit(st, ast::Plus) => { word(&mut self.s, - ast_util::int_ty_to_string(st, Some(i as i64)).as_slice()) + ast_util::int_ty_to_string(st, Some(i as i64))[]) } ast::SignedIntLit(st, ast::Minus) => { let istr = ast_util::int_ty_to_string(st, Some(-(i as i64))); word(&mut self.s, - format!("-{}", istr).as_slice()) + format!("-{}", istr)[]) } ast::UnsignedIntLit(ut) => { - word(&mut self.s, ast_util::uint_ty_to_string(ut, Some(i)).as_slice()) + word(&mut self.s, ast_util::uint_ty_to_string(ut, Some(i))[]) } ast::UnsuffixedIntLit(ast::Plus) => { - word(&mut self.s, format!("{}", i).as_slice()) + word(&mut self.s, format!("{}", i)[]) } ast::UnsuffixedIntLit(ast::Minus) => { - word(&mut self.s, format!("-{}", i).as_slice()) + word(&mut self.s, format!("-{}", i)[]) } } } @@ -2785,7 +2786,7 @@ impl<'a> State<'a> { format!( "{}{}", f.get(), - ast_util::float_ty_to_string(t).as_slice()).as_slice()) + ast_util::float_ty_to_string(t)[])[]) } ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, f.get()), ast::LitBool(val) => { @@ -2797,7 +2798,7 @@ impl<'a> State<'a> { ascii::escape_default(ch as u8, |ch| escaped.push(ch as char)); } - word(&mut self.s, format!("b\"{}\"", escaped).as_slice()) + word(&mut self.s, format!("b\"{}\"", escaped)[]) } } } @@ -2838,7 +2839,7 @@ impl<'a> State<'a> { comments::Mixed => { assert_eq!(cmnt.lines.len(), 1u); try!(zerobreak(&mut self.s)); - try!(word(&mut self.s, cmnt.lines[0].as_slice())); + try!(word(&mut self.s, cmnt.lines[0][])); zerobreak(&mut self.s) } comments::Isolated => { @@ -2847,7 +2848,7 @@ impl<'a> State<'a> { // Don't print empty lines because they will end up as trailing // whitespace if !line.is_empty() { - try!(word(&mut self.s, line.as_slice())); + try!(word(&mut self.s, line[])); } try!(hardbreak(&mut self.s)); } @@ -2856,13 +2857,13 @@ impl<'a> State<'a> { comments::Trailing => { try!(word(&mut self.s, " ")); if cmnt.lines.len() == 1u { - try!(word(&mut self.s, cmnt.lines[0].as_slice())); + try!(word(&mut self.s, cmnt.lines[0][])); hardbreak(&mut self.s) } else { try!(self.ibox(0u)); for line in cmnt.lines.iter() { if !line.is_empty() { - try!(word(&mut self.s, line.as_slice())); + try!(word(&mut self.s, line[])); } try!(hardbreak(&mut self.s)); } @@ -2891,11 +2892,11 @@ impl<'a> State<'a> { } ast::RawStr(n) => { (format!("r{delim}\"{string}\"{delim}", - delim="#".repeat(n), + delim=repeat("#", n), string=st)) } }; - word(&mut self.s, st.as_slice()) + word(&mut self.s, st[]) } pub fn next_comment(&mut self) -> Option { @@ -2926,7 +2927,7 @@ impl<'a> State<'a> { Some(abi::Rust) => Ok(()), Some(abi) => { try!(self.word_nbsp("extern")); - self.word_nbsp(abi.to_string().as_slice()) + self.word_nbsp(abi.to_string()[]) } None => Ok(()) } @@ -2937,7 +2938,7 @@ impl<'a> State<'a> { match opt_abi { Some(abi) => { try!(self.word_nbsp("extern")); - self.word_nbsp(abi.to_string().as_slice()) + self.word_nbsp(abi.to_string()[]) } None => Ok(()) } @@ -2953,7 +2954,7 @@ impl<'a> State<'a> { if abi != abi::Rust { try!(self.word_nbsp("extern")); - try!(self.word_nbsp(abi.to_string().as_slice())); + try!(self.word_nbsp(abi.to_string()[])); } word(&mut self.s, "fn") @@ -2967,6 +2968,8 @@ impl<'a> State<'a> { } } +fn repeat(s: &str, n: uint) -> String { iter::repeat(s).take(n).collect() } + #[cfg(test)] mod test { use super::*; diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index e98be046586..e1c8ff5011b 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -40,7 +40,7 @@ pub fn maybe_inject_prelude(krate: ast::Crate) -> ast::Crate { } fn use_std(krate: &ast::Crate) -> bool { - !attr::contains_name(krate.attrs.as_slice(), "no_std") + !attr::contains_name(krate.attrs[], "no_std") } fn no_prelude(attrs: &[ast::Attribute]) -> bool { @@ -56,7 +56,7 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { // The name to use in `extern crate "name" as std;` let actual_crate_name = match self.alt_std_name { - Some(ref s) => token::intern_and_get_ident(s.as_slice()), + Some(ref s) => token::intern_and_get_ident(s[]), None => token::intern_and_get_ident("std"), }; @@ -118,7 +118,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> { attr::mark_used(&no_std_attr); krate.attrs.push(no_std_attr); - if !no_prelude(krate.attrs.as_slice()) { + if !no_prelude(krate.attrs[]) { // only add `use std::prelude::*;` if there wasn't a // `#![no_implicit_prelude]` at the crate level. // fold_mod() will insert glob path. @@ -138,7 +138,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> { } fn fold_item(&mut self, item: P) -> SmallVector> { - if !no_prelude(item.attrs.as_slice()) { + if !no_prelude(item.attrs[]) { // only recur if there wasn't `#![no_implicit_prelude]` // on this item, i.e. this means that the prelude is not // implicitly imported though the whole subtree diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 155cabb153c..bc7dda8c44a 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -73,14 +73,14 @@ pub fn modify_for_testing(sess: &ParseSess, // We generate the test harness when building in the 'test' // configuration, either with the '--test' or '--cfg test' // command line options. - let should_test = attr::contains_name(krate.config.as_slice(), "test"); + let should_test = attr::contains_name(krate.config[], "test"); // Check for #[reexport_test_harness_main = "some_name"] which // creates a `use some_name = __test::main;`. This needs to be // unconditional, so that the attribute is still marked as used in // non-test builds. let reexport_test_harness_main = - attr::first_attr_value_str_by_name(krate.attrs.as_slice(), + attr::first_attr_value_str_by_name(krate.attrs[], "reexport_test_harness_main"); if should_test { @@ -119,7 +119,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { self.cx.path.push(ident); } debug!("current path: {}", - ast_util::path_name_i(self.cx.path.as_slice())); + ast_util::path_name_i(self.cx.path[])); if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) { match i.node { @@ -277,8 +277,8 @@ fn strip_test_functions(krate: ast::Crate) -> ast::Crate { // When not compiling with --test we should not compile the // #[test] functions config::strip_items(krate, |attrs| { - !attr::contains_name(attrs.as_slice(), "test") && - !attr::contains_name(attrs.as_slice(), "bench") + !attr::contains_name(attrs[], "test") && + !attr::contains_name(attrs[], "bench") }) } @@ -291,7 +291,7 @@ enum HasTestSignature { fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { - let has_test_attr = attr::contains_name(i.attrs.as_slice(), "test"); + let has_test_attr = attr::contains_name(i.attrs[], "test"); fn has_test_signature(i: &ast::Item) -> HasTestSignature { match &i.node { @@ -329,7 +329,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { } fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { - let has_bench_attr = attr::contains_name(i.attrs.as_slice(), "bench"); + let has_bench_attr = attr::contains_name(i.attrs[], "bench"); fn has_test_signature(i: &ast::Item) -> bool { match i.node { @@ -384,7 +384,7 @@ We're going to be building a module that looks more or less like: mod __test { extern crate test (name = "test", vers = "..."); fn main() { - test::test_main_static(::os::args().as_slice(), tests) + test::test_main_static(::os::args()[], tests) } static tests : &'static [test::TestDescAndFn] = &[ @@ -510,8 +510,8 @@ fn mk_tests(cx: &TestCtxt) -> P { } fn is_test_crate(krate: &ast::Crate) -> bool { - match attr::find_crate_name(krate.attrs.as_slice()) { - Some(ref s) if "test" == s.get().as_slice() => true, + match attr::find_crate_name(krate.attrs[]) { + Some(ref s) if "test" == s.get()[] => true, _ => false } } @@ -551,11 +551,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { // creates $name: $expr let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr); - debug!("encoding {}", ast_util::path_name_i(path.as_slice())); + debug!("encoding {}", ast_util::path_name_i(path[])); // path to the #[test] function: "foo::bar::baz" - let path_string = ast_util::path_name_i(path.as_slice()); - let name_expr = ecx.expr_str(span, token::intern_and_get_ident(path_string.as_slice())); + let path_string = ast_util::path_name_i(path[]); + let name_expr = ecx.expr_str(span, token::intern_and_get_ident(path_string[])); // self::test::StaticTestName($name_expr) let name_expr = ecx.expr_call(span, diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 590a04ce221..97eb4316583 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -95,41 +95,37 @@ pub struct RcStr { string: Rc, } +impl RcStr { + pub fn new(string: &str) -> RcStr { + RcStr { + string: Rc::new(string.to_string()), + } + } +} + impl Eq for RcStr {} impl Ord for RcStr { fn cmp(&self, other: &RcStr) -> Ordering { - self.as_slice().cmp(other.as_slice()) - } -} - -impl Str for RcStr { - #[inline] - fn as_slice<'a>(&'a self) -> &'a str { - let s: &'a str = self.string.as_slice(); - s + self[].cmp(other[]) } } impl fmt::Show for RcStr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::fmt::Show; - self.as_slice().fmt(f) + self[].fmt(f) } } impl BorrowFrom for str { fn borrow_from(owned: &RcStr) -> &str { - owned.string.as_slice() + owned.string[] } } -impl RcStr { - pub fn new(string: &str) -> RcStr { - RcStr { - string: Rc::new(string.into_string()), - } - } +impl Deref for RcStr { + fn deref(&self) -> &str { self.string[] } } /// A StrInterner differs from Interner in that it accepts diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index 65f8415835a..d944d0362fb 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -180,7 +180,7 @@ impl TerminfoTerminal { } }; - let entry = open(term.as_slice()); + let entry = open(term[]); if entry.is_err() { if os::getenv("MSYSCON").map_or(false, |s| { "mintty.exe" == s diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs index 33bfd69f71b..395fac52d8d 100644 --- a/src/libterm/terminfo/searcher.rs +++ b/src/libterm/terminfo/searcher.rs @@ -61,13 +61,13 @@ pub fn get_dbpath_for_term(term: &str) -> Option> { for p in dirs_to_search.iter() { if p.exists() { let f = first_char.to_string(); - let newp = p.join_many(&[f.as_slice(), term]); + let newp = p.join_many(&[f[], term]); if newp.exists() { return Some(box newp); } // on some installations the dir is named after the hex of the char (e.g. OS X) let f = format!("{:x}", first_char as uint); - let newp = p.join_many(&[f.as_slice(), term]); + let newp = p.join_many(&[f[], term]); if newp.exists() { return Some(box newp); } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 5b04a1fed89..1870f162ece 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -65,6 +65,7 @@ use std::io::fs::PathExtensions; use std::io::stdio::StdWriter; use std::io::{File, ChanReader, ChanWriter}; use std::io; +use std::iter::repeat; use std::num::{Float, FloatMath, Int}; use std::os; use std::str::FromStr; @@ -121,7 +122,7 @@ impl TestDesc { fn padded_name(&self, column_count: uint, align: NamePadding) -> String { let mut name = String::from_str(self.name.as_slice()); let fill = column_count.saturating_sub(name.len()); - let mut pad = " ".repeat(fill); + let mut pad = repeat(" ").take(fill).collect::(); match align { PadNone => name, PadOnLeft => { @@ -426,7 +427,7 @@ pub fn parse_opts(args: &[String]) -> Option { let ratchet_noise_percent = matches.opt_str("ratchet-noise-percent"); let ratchet_noise_percent = - ratchet_noise_percent.map(|s| from_str::(s.as_slice()).unwrap()); + ratchet_noise_percent.map(|s| s.as_slice().parse::().unwrap()); let save_metrics = matches.opt_str("save-metrics"); let save_metrics = save_metrics.map(|s| Path::new(s)); @@ -489,7 +490,8 @@ pub fn opt_shard(maybestr: Option) -> Option<(uint,uint)> { None => None, Some(s) => { let mut it = s.split('.'); - match (it.next().and_then(from_str::), it.next().and_then(from_str::), + match (it.next().and_then(|s| s.parse::()), + it.next().and_then(|s| s.parse::()), it.next()) { (Some(a), Some(b), None) => { if a <= 0 || a > b { diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 5d7d2951628..7d59e3de7b1 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -15,22 +15,16 @@ //! This module provides functionality to `str` that requires the Unicode methods provided by the //! UnicodeChar trait. +use self::GraphemeState::*; use core::prelude::*; use core::char; use core::cmp; -use core::iter::{DoubleEndedIterator, DoubleEndedIteratorExt}; -use core::iter::{Filter, AdditiveIterator, Iterator, IteratorExt}; use core::iter::{Filter, AdditiveIterator}; -use core::kinds::Sized; use core::mem; use core::num::Int; -use core::option::Option::{None, Some}; -use core::option::Option; -use core::slice::SliceExt; use core::slice; -use core::str::{CharSplits, StrPrelude}; -use core::str::{CharSplits}; +use core::str::CharSplits; use u_char::UnicodeChar; use tables::grapheme::GraphemeCat; @@ -39,106 +33,20 @@ use tables::grapheme::GraphemeCat; /// FIXME: This should be opaque #[stable] pub struct Words<'a> { - inner: Filter<'a, &'a str, CharSplits<'a, |char|:'a -> bool>, - fn(&&str) -> bool>, + inner: Filter<&'a str, CharSplits<'a, fn(char) -> bool>, fn(&&str) -> bool>, } /// Methods for Unicode string slices +#[allow(missing_docs)] // docs in libcollections pub trait UnicodeStr for Sized? { - /// Returns an iterator over the - /// [grapheme clusters](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) - /// of the string. - /// - /// If `is_extended` is true, the iterator is over the *extended grapheme clusters*; - /// otherwise, the iterator is over the *legacy grapheme clusters*. - /// [UAX#29](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) - /// recommends extended grapheme cluster boundaries for general processing. - /// - /// # Example - /// - /// ```rust - /// let gr1 = "a\u{0310}e\u{0301}o\u{0308}\u{0332}".graphemes(true).collect::>(); - /// let b: &[_] = &["a\u{0310}", "e\u{0301}", "o\u{0308}\u{0332}"]; - /// assert_eq!(gr1.as_slice(), b); - /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::>(); - /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"]; - /// assert_eq!(gr2.as_slice(), b); - /// ``` fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>; - - /// Returns an iterator over the grapheme clusters of self and their byte offsets. - /// See `graphemes()` method for more information. - /// - /// # Example - /// - /// ```rust - /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::>(); - /// let b: &[_] = &[(0u, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; - /// assert_eq!(gr_inds.as_slice(), b); - /// ``` fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>; - - /// An iterator over the words of a string (subsequences separated - /// by any sequence of whitespace). Sequences of whitespace are - /// collapsed, so empty "words" are not included. - /// - /// # Example - /// - /// ```rust - /// let some_words = " Mary had\ta little \n\t lamb"; - /// let v: Vec<&str> = some_words.words().collect(); - /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); - /// ``` - #[stable] fn words<'a>(&'a self) -> Words<'a>; - - /// Returns true if the string contains only whitespace. - /// - /// Whitespace characters are determined by `char::is_whitespace`. - /// - /// # Example - /// - /// ```rust - /// assert!(" \t\n".is_whitespace()); - /// assert!("".is_whitespace()); - /// - /// assert!( !"abc".is_whitespace()); - /// ``` fn is_whitespace(&self) -> bool; - - /// Returns true if the string contains only alphanumeric code - /// points. - /// - /// Alphanumeric characters are determined by `char::is_alphanumeric`. - /// - /// # Example - /// - /// ```rust - /// assert!("Löwe老虎Léopard123".is_alphanumeric()); - /// assert!("".is_alphanumeric()); - /// - /// assert!( !" &*~".is_alphanumeric()); - /// ``` fn is_alphanumeric(&self) -> bool; - - /// Returns a string's displayed width in columns, treating control - /// characters as zero-width. - /// - /// `is_cjk` determines behavior for characters in the Ambiguous category: - /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1. - /// In CJK locales, `is_cjk` should be `true`, else it should be `false`. - /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) - /// recommends that these characters be treated as 1 column (i.e., - /// `is_cjk` = `false`) if the locale is unknown. fn width(&self, is_cjk: bool) -> uint; - - /// Returns a string with leading and trailing whitespace removed. fn trim<'a>(&'a self) -> &'a str; - - /// Returns a string with leading whitespace removed. fn trim_left<'a>(&'a self) -> &'a str; - - /// Returns a string with trailing whitespace removed. fn trim_right<'a>(&'a self) -> &'a str; } @@ -471,10 +379,10 @@ pub fn utf8_char_width(b: u8) -> uint { /// Determines if a vector of `u16` contains valid UTF-16 pub fn is_utf16(v: &[u16]) -> bool { let mut it = v.iter(); - macro_rules! next ( ($ret:expr) => { + macro_rules! next { ($ret:expr) => { match it.next() { Some(u) => *u, None => return $ret } } - ) + } loop { let u = next!(true); @@ -513,7 +421,7 @@ impl Utf16Item { pub fn to_char_lossy(&self) -> char { match *self { Utf16Item::ScalarValue(c) => c, - Utf16Item::LoneSurrogate(_) => '\uFFFD' + Utf16Item::LoneSurrogate(_) => '\u{FFFD}' } } } @@ -568,15 +476,14 @@ impl<'a> Iterator for Utf16Items<'a> { /// # Example /// /// ```rust -/// use std::str; -/// use std::str::{ScalarValue, LoneSurrogate}; +/// use unicode::str::Utf16Item::{ScalarValue, LoneSurrogate}; /// /// // 𝄞music /// let v = [0xD834, 0xDD1E, 0x006d, 0x0075, /// 0x0073, 0xDD1E, 0x0069, 0x0063, /// 0xD834]; /// -/// assert_eq!(str::utf16_items(&v).collect::>(), +/// assert_eq!(unicode::str::utf16_items(&v).collect::>(), /// vec![ScalarValue('𝄞'), /// ScalarValue('m'), ScalarValue('u'), ScalarValue('s'), /// LoneSurrogate(0xDD1E), diff --git a/src/test/run-pass/issue-19340-1.rs b/src/test/run-pass/issue-19340-1.rs index b7a6391ee04..2f466d4ca8c 100644 --- a/src/test/run-pass/issue-19340-1.rs +++ b/src/test/run-pass/issue-19340-1.rs @@ -15,7 +15,7 @@ extern crate "issue-19340-1" as lib; use lib::Homura; fn main() { - let homura = Homura::Madoka { name: "Kaname".into_string() }; + let homura = Homura::Madoka { name: "Kaname".to_string() }; match homura { Homura::Madoka { name } => (), diff --git a/src/test/run-pass/issue-19340-2.rs b/src/test/run-pass/issue-19340-2.rs index 5179c1e2acb..8300220edea 100644 --- a/src/test/run-pass/issue-19340-2.rs +++ b/src/test/run-pass/issue-19340-2.rs @@ -17,7 +17,7 @@ enum Homura { fn main() { let homura = Homura::Madoka { - name: "Akemi".into_string(), + name: "Akemi".to_string(), age: 14, }; diff --git a/src/test/run-pass/issue-19367.rs b/src/test/run-pass/issue-19367.rs index 3efc2ee50f3..7db84d518ff 100644 --- a/src/test/run-pass/issue-19367.rs +++ b/src/test/run-pass/issue-19367.rs @@ -16,10 +16,10 @@ struct S { // on field of struct or tuple which we reassign in the match body. fn main() { - let mut a = (0i, Some("right".into_string())); + let mut a = (0i, Some("right".to_string())); let b = match a.1 { Some(v) => { - a.1 = Some("wrong".into_string()); + a.1 = Some("wrong".to_string()); v } None => String::new() @@ -28,10 +28,10 @@ fn main() { assert_eq!(b, "right"); - let mut s = S{ o: Some("right".into_string()) }; + let mut s = S{ o: Some("right".to_string()) }; let b = match s.o { Some(v) => { - s.o = Some("wrong".into_string()); + s.o = Some("wrong".to_string()); v } None => String::new(), -- cgit 1.4.1-3-g733a5 From 7f0d2e8a2b0b69aef99ebb2f915b5f62922e6739 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Sat, 29 Nov 2014 10:20:22 +1100 Subject: RFC 248? I think you meant RFC 438. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There ain’t an RFC 248, while 438 looks to be what is being referred to: https://github.com/rust-lang/rfcs/blob/master/text/0438-precedence-of-plus.md --- src/librustc_typeck/astconv.rs | 6 +++--- src/libsyntax/parse/parser.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4f4bebabead..befb4bf81e5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -798,14 +798,14 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, match ty.node { ast::TyRptr(None, ref mut_ty) => { span_note!(this.tcx().sess, ty.span, - "perhaps you meant `&{}({} +{})`? (per RFC 248)", + "perhaps you meant `&{}({} +{})`? (per RFC 438)", ppaux::mutability_to_string(mut_ty.mutbl), pprust::ty_to_string(&*mut_ty.ty), pprust::bounds_to_string(bounds)); } ast::TyRptr(Some(ref lt), ref mut_ty) => { span_note!(this.tcx().sess, ty.span, - "perhaps you meant `&{} {}({} +{})`? (per RFC 248)", + "perhaps you meant `&{} {}({} +{})`? (per RFC 438)", pprust::lifetime_to_string(lt), ppaux::mutability_to_string(mut_ty.mutbl), pprust::ty_to_string(&*mut_ty.ty), @@ -814,7 +814,7 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, _ => { span_note!(this.tcx().sess, ty.span, - "perhaps you forgot parentheses? (per RFC 248)"); + "perhaps you forgot parentheses? (per RFC 438)"); } } Err(ErrorReported) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3ad224b93ce..db195c0f206 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1456,7 +1456,7 @@ impl<'a> Parser<'a> { // clauses (i.e., not when parsing something like // `FnMut() -> T + Send`, where the `+` is legal). if self.token == token::BinOp(token::Plus) { - self.warn("deprecated syntax: `()` are required, see RFC 248 for details"); + self.warn("deprecated syntax: `()` are required, see RFC 438 for details"); } Return(t) -- cgit 1.4.1-3-g733a5 From 8a357e1d87971574817a033e5467785402d5fcfb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 13 Dec 2014 18:41:02 +1300 Subject: Add syntax for ranges --- src/librustc/middle/cfg/construct.rs | 4 ++++ src/librustc/middle/expr_use_visitor.rs | 4 ++++ src/librustc/middle/liveness.rs | 10 ++++++++ src/librustc/middle/mem_categorization.rs | 3 +++ src/librustc/middle/ty.rs | 3 +++ src/librustc_back/svh.rs | 2 ++ src/librustc_trans/trans/debuginfo.rs | 5 ++++ src/librustc_typeck/check/mod.rs | 4 ++++ src/libsyntax/ast.rs | 1 + src/libsyntax/fold.rs | 4 ++++ src/libsyntax/parse/parser.rs | 40 ++++++++++++++++++++++++------- src/libsyntax/print/pprust.rs | 7 ++++++ src/libsyntax/visit.rs | 4 ++++ 13 files changed, 83 insertions(+), 8 deletions(-) (limited to 'src/libsyntax/parse/parser.rs') diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 2d50757782d..fe8e90bc32c 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -439,6 +439,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { start.iter().chain(end.iter()).map(|x| &**x)) } + ast::ExprRange(..) => { + self.tcx.sess.span_bug(expr.span, "non-desugared range"); + } + ast::ExprUnary(_, ref e) if self.is_method_call(expr) => { self.call(expr, pred, &**e, None::.iter()) } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 7e31ae04ae0..6a2bb2fc5a3 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -465,6 +465,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { assert!(overloaded); } + ast::ExprRange(..) => { + self.tcx().sess.span_bug(expr.span, "non-desugared range"); + } + ast::ExprCall(ref callee, ref args) => { // callee(args) self.walk_callee(expr, &**callee); self.consume_exprs(args); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 798daf8d541..fe2d7d47cb9 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -486,6 +486,9 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { ast::ExprWhileLet(..) => { ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); } + ast::ExprRange(..) => { + ir.tcx.sess.span_bug(expr.span, "non-desugared range"); + } ast::ExprForLoop(ref pat, _, _, _) => { pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| { debug!("adding local variable {} from for loop with bm {}", @@ -1197,6 +1200,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_expr(&**e1, succ) } + ast::ExprRange(..) => { + self.ir.tcx.sess.span_bug(expr.span, "non-desugared range"); + } + ast::ExprBox(None, ref e) | ast::ExprAddrOf(_, ref e) | ast::ExprCast(ref e, _) | @@ -1498,6 +1505,9 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { ast::ExprWhileLet(..) => { this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); } + ast::ExprRange(..) => { + this.ir.tcx.sess.span_bug(expr.span, "non-desugared range"); + } } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 006515ea0a0..e605471fc06 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -559,6 +559,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ast::ExprWhileLet(..) => { self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet"); } + ast::ExprRange(..) => { + self.tcx().sess.span_bug(expr.span, "non-desugared range"); + } } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 22fdea8afb5..4c5d3cb5c74 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4273,6 +4273,9 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { ast::ExprWhileLet(..) => { tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); } + ast::ExprRange(..) => { + tcx.sess.span_bug(expr.span, "non-desugared range"); + } ast::ExprLit(ref lit) if lit_is_str(&**lit) => { RvalueDpsExpr diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index d40c9ee8af6..c68e9055269 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -247,6 +247,7 @@ mod svh_visitor { SawExprAssignOp(ast::BinOp), SawExprIndex, SawExprSlice, + SawExprRange, SawExprPath, SawExprAddrOf(ast::Mutability), SawExprRet, @@ -280,6 +281,7 @@ mod svh_visitor { ExprTupField(_, id) => SawExprTupField(id.node), ExprIndex(..) => SawExprIndex, ExprSlice(..) => SawExprSlice, + ExprRange(..) => SawExprRange, ExprPath(..) => SawExprPath, ExprAddrOf(m, _) => SawExprAddrOf(m), ExprBreak(id) => SawExprBreak(id.map(content)), diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 6226aace8a8..f402f1d7c31 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3494,6 +3494,11 @@ fn populate_scope_map(cx: &CrateContext, end.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map)); } + ast::ExprRange(..) => { + cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \ + Found unexpanded range."); + } + ast::ExprVec(ref init_expressions) | ast::ExprTup(ref init_expressions) => { for ie in init_expressions.iter() { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3139a17f998..02811861551 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4278,6 +4278,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } } } + ast::ExprRange(..) => { + tcx.sess.span_bug(expr.span, "non-desugared range"); + } + } debug!("type of expr({}) {} is...", expr.id, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9d4bf77d4a5..0c8c17b080b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -724,6 +724,7 @@ pub enum Expr_ { ExprTupField(P, Spanned), ExprIndex(P, P), ExprSlice(P, Option>, Option>, Mutability), + ExprRange(P, Option>), /// Variable reference, possibly containing `::` and/or /// type parameters, e.g. foo::bar:: diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 86df5883864..0803de1bb53 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1390,6 +1390,10 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> e2.map(|x| folder.fold_expr(x)), m) } + ExprRange(e1, e2) => { + ExprRange(folder.fold_expr(e1), + e2.map(|x| folder.fold_expr(x))) + } ExprPath(pth) => ExprPath(folder.fold_path(pth)), ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 197970317d2..94b61ba56d2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -26,7 +26,7 @@ use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex, ExprSlice}; -use ast::{ExprLit, ExprLoop, ExprMac}; +use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; use ast::{ExprMethodCall, ExprParen, ExprPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; @@ -95,7 +95,8 @@ bitflags! { const UNRESTRICTED = 0b0000, const RESTRICTION_STMT_EXPR = 0b0001, const RESTRICTION_NO_BAR_OP = 0b0010, - const RESTRICTION_NO_STRUCT_LITERAL = 0b0100 + const RESTRICTION_NO_STRUCT_LITERAL = 0b0100, + const RESTRICTION_NO_DOTS = 0b1000, } } @@ -1547,7 +1548,7 @@ impl<'a> Parser<'a> { // Parse the `; e` in `[ int; e ]` // where `e` is a const expression - let t = match self.maybe_parse_fixed_vstore() { + let t = match self.maybe_parse_fixed_length_of_vec() { None => TyVec(t), Some(suffix) => TyFixedLengthVec(t, suffix) }; @@ -1707,12 +1708,12 @@ impl<'a> Parser<'a> { } } - pub fn maybe_parse_fixed_vstore(&mut self) -> Option> { + pub fn maybe_parse_fixed_length_of_vec(&mut self) -> Option> { if self.check(&token::Comma) && self.look_ahead(1, |t| *t == token::DotDot) { self.bump(); self.bump(); - Some(self.parse_expr()) + Some(self.parse_expr_res(RESTRICTION_NO_DOTS)) } else if self.check(&token::Semi) { self.bump(); Some(self.parse_expr()) @@ -2130,7 +2131,8 @@ impl<'a> Parser<'a> { ExprIndex(expr, idx) } - pub fn mk_slice(&mut self, expr: P, + pub fn mk_slice(&mut self, + expr: P, start: Option>, end: Option>, mutbl: Mutability) @@ -2138,6 +2140,13 @@ impl<'a> Parser<'a> { ExprSlice(expr, start, end, mutbl) } + pub fn mk_range(&mut self, + start: P, + end: Option>) + -> ast::Expr_ { + ExprRange(start, end) + } + pub fn mk_field(&mut self, expr: P, ident: ast::SpannedIdent) -> ast::Expr_ { ExprField(expr, ident) } @@ -2615,7 +2624,7 @@ impl<'a> Parser<'a> { } // e[e] | e[e..] | e[e..e] _ => { - let ix = self.parse_expr(); + let ix = self.parse_expr_res(RESTRICTION_NO_DOTS); match self.token { // e[e..] | e[e..e] token::DotDot => { @@ -2628,7 +2637,7 @@ impl<'a> Parser<'a> { } // e[e..e] _ => { - let e2 = self.parse_expr(); + let e2 = self.parse_expr_res(RESTRICTION_NO_DOTS); self.commit_expr_expecting(&*e2, token::CloseDelim(token::Bracket)); Some(e2) @@ -2654,6 +2663,21 @@ impl<'a> Parser<'a> { } } + // A range expression, either `expr..expr` or `expr..`. + token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => { + self.bump(); + + let opt_end = if self.token.can_begin_expr() { + let end = self.parse_expr_res(RESTRICTION_NO_DOTS); + Some(end) + } else { + None + }; + + let hi = self.span.hi; + let range = self.mk_range(e, opt_end); + return self.mk_expr(lo, hi, range); + } _ => return e } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 21410395a90..3d53bd8aadf 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1759,6 +1759,13 @@ impl<'a> State<'a> { } try!(word(&mut self.s, "]")); } + ast::ExprRange(ref start, ref end) => { + try!(self.print_expr(&**start)); + try!(word(&mut self.s, "..")); + if let &Some(ref e) = end { + try!(self.print_expr(&**e)); + } + } ast::ExprPath(ref path) => try!(self.print_path(path, true)), ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 9938feb171e..4cc93467a7c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -871,6 +871,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_expr_opt(visitor, start); walk_expr_opt(visitor, end) } + ExprRange(ref start, ref end) => { + visitor.visit_expr(&**start); + walk_expr_opt(visitor, end) + } ExprPath(ref path) => { visitor.visit_path(path, expression.id) } -- cgit 1.4.1-3-g733a5