From 96b228835ad3a9b366e572ffb4d3cebee60d0f56 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 8 May 2016 21:36:44 -0700 Subject: [PATCH 01/50] trans: Always lower to `frem` Long ago LLVM unfortunately didn't handle the 32-bit MSVC case of `frem` where it can't be lowered to `fmodf` because that symbol doesn't exist. That was since fixed in http://reviews.llvm.org/D12099 (landed as r246615) and was released in what appears to be LLVM 3.8. Now that we're using that branch of LLVM let's remove our own hacks and help LLVM optimize a little better by giving it knowledge about what we're doing. --- src/librustc_trans/expr.rs | 39 +------------------------------ src/librustc_trans/mir/rvalue.rs | 40 +------------------------------- 2 files changed, 2 insertions(+), 77 deletions(-) diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs index cd11ca586890c..a583c9adae68a 100644 --- a/src/librustc_trans/expr.rs +++ b/src/librustc_trans/expr.rs @@ -63,7 +63,6 @@ use cleanup::{self, CleanupMethods, DropHintMethods}; use common::*; use datum::*; use debuginfo::{self, DebugLoc, ToDebugLoc}; -use declare; use glue; use machine; use tvec; @@ -1591,7 +1590,6 @@ fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, { let _icx = push_ctxt("trans_scalar_binop"); - let tcx = bcx.tcx(); let lhs_t = lhs.ty; assert!(!lhs_t.is_simd()); let is_float = lhs_t.is_fp(); @@ -1654,42 +1652,7 @@ fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } hir::BiRem => { if is_float { - // LLVM currently always lowers the `frem` instructions appropriate - // library calls typically found in libm. Notably f64 gets wired up - // to `fmod` and f32 gets wired up to `fmodf`. Inconveniently for - // us, 32-bit MSVC does not actually have a `fmodf` symbol, it's - // instead just an inline function in a header that goes up to a - // f64, uses `fmod`, and then comes back down to a f32. - // - // Although LLVM knows that `fmodf` doesn't exist on MSVC, it will - // still unconditionally lower frem instructions over 32-bit floats - // to a call to `fmodf`. To work around this we special case MSVC - // 32-bit float rem instructions and instead do the call out to - // `fmod` ourselves. - // - // Note that this is currently duplicated with src/libcore/ops.rs - // which does the same thing, and it would be nice to perhaps unify - // these two implementations on day! Also note that we call `fmod` - // for both 32 and 64-bit floats because if we emit any FRem - // instruction at all then LLVM is capable of optimizing it into a - // 32-bit FRem (which we're trying to avoid). - let use_fmod = tcx.sess.target.target.options.is_like_msvc && - tcx.sess.target.target.arch == "x86"; - if use_fmod { - let f64t = Type::f64(bcx.ccx()); - let fty = Type::func(&[f64t, f64t], &f64t); - let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty); - if lhs_t == tcx.types.f32 { - let lhs = FPExt(bcx, lhs, f64t); - let rhs = FPExt(bcx, rhs, f64t); - let res = Call(bcx, llfn, &[lhs, rhs], binop_debug_loc); - FPTrunc(bcx, res, Type::f32(bcx.ccx())) - } else { - Call(bcx, llfn, &[lhs, rhs], binop_debug_loc) - } - } else { - FRem(bcx, lhs, rhs, binop_debug_loc) - } + FRem(bcx, lhs, rhs, binop_debug_loc) } else { // Only zero-check integers; fp %0 is NaN bcx = base::fail_if_zero_or_overflows(bcx, diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 1236100a4d51c..0d1c2c32ec534 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -19,10 +19,8 @@ use callee::Callee; use common::{self, C_uint, BlockAndBuilder, Result}; use datum::{Datum, Lvalue}; use debuginfo::DebugLoc; -use declare; use adt; use machine; -use type_::Type; use type_of; use tvec; use value::Value; @@ -529,43 +527,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { bcx.udiv(lhs, rhs) }, mir::BinOp::Rem => if is_float { - // LLVM currently always lowers the `frem` instructions appropriate - // library calls typically found in libm. Notably f64 gets wired up - // to `fmod` and f32 gets wired up to `fmodf`. Inconveniently for - // us, 32-bit MSVC does not actually have a `fmodf` symbol, it's - // instead just an inline function in a header that goes up to a - // f64, uses `fmod`, and then comes back down to a f32. - // - // Although LLVM knows that `fmodf` doesn't exist on MSVC, it will - // still unconditionally lower frem instructions over 32-bit floats - // to a call to `fmodf`. To work around this we special case MSVC - // 32-bit float rem instructions and instead do the call out to - // `fmod` ourselves. - // - // Note that this is currently duplicated with src/libcore/ops.rs - // which does the same thing, and it would be nice to perhaps unify - // these two implementations one day! Also note that we call `fmod` - // for both 32 and 64-bit floats because if we emit any FRem - // instruction at all then LLVM is capable of optimizing it into a - // 32-bit FRem (which we're trying to avoid). - let tcx = bcx.tcx(); - let use_fmod = tcx.sess.target.target.options.is_like_msvc && - tcx.sess.target.target.arch == "x86"; - if use_fmod { - let f64t = Type::f64(bcx.ccx()); - let fty = Type::func(&[f64t, f64t], &f64t); - let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty); - if input_ty == tcx.types.f32 { - let lllhs = bcx.fpext(lhs, f64t); - let llrhs = bcx.fpext(rhs, f64t); - let llres = bcx.call(llfn, &[lllhs, llrhs], None); - bcx.fptrunc(llres, Type::f32(bcx.ccx())) - } else { - bcx.call(llfn, &[lhs, rhs], None) - } - } else { - bcx.frem(lhs, rhs) - } + bcx.frem(lhs, rhs) } else if is_signed { bcx.srem(lhs, rhs) } else { From df572fcf4eea79baddc0136573cbbeed88db001e Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 9 May 2016 23:52:50 +0000 Subject: [PATCH 02/50] Remove unused function `lower_opt_bounds` --- src/librustc/hir/lowering.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 0026412013c8e..e4b87ab8bf344 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -593,12 +593,6 @@ pub fn lower_mt(lctx: &LoweringContext, mt: &MutTy) -> hir::MutTy { } } -pub fn lower_opt_bounds(lctx: &LoweringContext, - b: &Option) - -> Option { - b.as_ref().map(|ref bounds| lower_bounds(lctx, bounds)) -} - fn lower_bounds(lctx: &LoweringContext, bounds: &TyParamBounds) -> hir::TyParamBounds { bounds.iter().map(|bound| lower_ty_param_bound(lctx, bound)).collect() } From 417fe6d16e981c01bf258cd8b47a812bfb33723d Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 9 May 2016 22:20:53 +0000 Subject: [PATCH 03/50] Refactor away method `LoweringContext::diagnostic` --- src/librustc/hir/lowering.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e4b87ab8bf344..4bfe514c39d10 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,7 +50,6 @@ use std::collections::BTreeMap; use std::iter; use syntax::ast::*; use syntax::attr::{ThinAttributes, ThinAttributesExt}; -use syntax::errors::Handler; use syntax::ext::mtwt; use syntax::ptr::P; use syntax::codemap::{respan, Spanned, Span}; @@ -94,7 +93,7 @@ impl Resolver for DummyResolver { } } -impl<'a, 'hir> LoweringContext<'a> { +impl<'a> LoweringContext<'a> { pub fn new(id_assigner: &'a NodeIdAssigner, c: Option<&Crate>, resolver: &'a mut Resolver) @@ -125,11 +124,6 @@ impl<'a, 'hir> LoweringContext<'a> { hir::Ident::from_name(token::gensym(s)) } - // Panics if this LoweringContext's NodeIdAssigner is not able to emit diagnostics. - fn diagnostic(&self) -> &Handler { - self.id_assigner.diagnostic() - } - fn with_parent_def T>(&self, parent_id: NodeId, f: F) -> T { let old_def = self.parent_def.get(); self.parent_def.set(match self.resolver.borrow_mut().definitions() { @@ -1245,8 +1239,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { make_struct(lctx, e, &["RangeInclusive", "NonEmpty"], &[("start", e1), ("end", e2)]), - _ => panic!(lctx.diagnostic().span_fatal(e.span, - "inclusive range with no end")) + _ => panic!(lctx.id_assigner.diagnostic() + .span_fatal(e.span, "inclusive range with no end")), }; } ExprKind::Path(ref qself, ref path) => { From eed8d70ac5177e6f378d08318f77499231e24e32 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 9 May 2016 07:59:19 +0000 Subject: [PATCH 04/50] Give lowering functions mutable access to the lowering context --- src/librustc/hir/lowering.rs | 281 ++++++++++++++--------------- src/librustc_driver/driver.rs | 4 +- src/librustc_metadata/astencode.rs | 16 +- src/librustdoc/test.rs | 4 +- 4 files changed, 152 insertions(+), 153 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 4bfe514c39d10..dc4ed655c9b88 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -57,8 +57,6 @@ use syntax::parse::token; use syntax::std_inject; use syntax::visit::{self, Visitor}; -use std::cell::{Cell, RefCell}; - pub struct LoweringContext<'a> { crate_root: Option<&'static str>, // Use to assign ids to hir nodes that do not directly correspond to an ast node @@ -66,8 +64,8 @@ pub struct LoweringContext<'a> { // As we walk the AST we must keep track of the current 'parent' def id (in // the form of a DefIndex) so that if we create a new node which introduces // a definition, then we can properly create the def id. - parent_def: Cell>, - resolver: RefCell<&'a mut Resolver>, + parent_def: Option, + resolver: &'a mut Resolver, } pub trait Resolver { @@ -111,8 +109,8 @@ impl<'a> LoweringContext<'a> { LoweringContext { crate_root: crate_root, id_assigner: id_assigner, - parent_def: Cell::new(None), - resolver: RefCell::new(resolver), + parent_def: None, + resolver: resolver, } } @@ -124,32 +122,34 @@ impl<'a> LoweringContext<'a> { hir::Ident::from_name(token::gensym(s)) } - fn with_parent_def T>(&self, parent_id: NodeId, f: F) -> T { - let old_def = self.parent_def.get(); - self.parent_def.set(match self.resolver.borrow_mut().definitions() { + fn with_parent_def(&mut self, parent_id: NodeId, f: F) -> T + where F: FnOnce(&mut LoweringContext) -> T + { + let old_def = self.parent_def; + self.parent_def = match self.resolver.definitions() { Some(defs) => Some(defs.opt_def_index(parent_id).unwrap()), None => old_def, - }); + }; - let result = f(); + let result = f(self); - self.parent_def.set(old_def); + self.parent_def = old_def; result } } -pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident { +pub fn lower_ident(_lctx: &mut LoweringContext, ident: Ident) -> hir::Ident { hir::Ident { name: mtwt::resolve(ident), unhygienic_name: ident.name, } } -pub fn lower_attrs(_lctx: &LoweringContext, attrs: &Vec) -> hir::HirVec { +pub fn lower_attrs(_lctx: &mut LoweringContext, attrs: &Vec) -> hir::HirVec { attrs.clone().into() } -pub fn lower_view_path(lctx: &LoweringContext, view_path: &ViewPath) -> P { +pub fn lower_view_path(lctx: &mut LoweringContext, view_path: &ViewPath) -> P { P(Spanned { node: match view_path.node { ViewPathSimple(ident, ref path) => { @@ -186,7 +186,7 @@ fn lower_path_list_item(path_list_ident: &PathListItem) -> hir::PathListItem { } } -pub fn lower_arm(lctx: &LoweringContext, arm: &Arm) -> hir::Arm { +pub fn lower_arm(lctx: &mut LoweringContext, arm: &Arm) -> hir::Arm { hir::Arm { attrs: lower_attrs(lctx, &arm.attrs), pats: arm.pats.iter().map(|x| lower_pat(lctx, x)).collect(), @@ -195,7 +195,7 @@ pub fn lower_arm(lctx: &LoweringContext, arm: &Arm) -> hir::Arm { } } -pub fn lower_decl(lctx: &LoweringContext, d: &Decl) -> P { +pub fn lower_decl(lctx: &mut LoweringContext, d: &Decl) -> P { match d.node { DeclKind::Local(ref l) => P(Spanned { node: hir::DeclLocal(lower_local(lctx, l)), @@ -208,7 +208,7 @@ pub fn lower_decl(lctx: &LoweringContext, d: &Decl) -> P { } } -pub fn lower_ty_binding(lctx: &LoweringContext, b: &TypeBinding) -> hir::TypeBinding { +pub fn lower_ty_binding(lctx: &mut LoweringContext, b: &TypeBinding) -> hir::TypeBinding { hir::TypeBinding { id: b.id, name: b.ident.name, @@ -217,7 +217,7 @@ pub fn lower_ty_binding(lctx: &LoweringContext, b: &TypeBinding) -> hir::TypeBin } } -pub fn lower_ty(lctx: &LoweringContext, t: &Ty) -> P { +pub fn lower_ty(lctx: &mut LoweringContext, t: &Ty) -> P { use syntax::ast::TyKind::*; P(hir::Ty { id: t.id, @@ -267,14 +267,14 @@ pub fn lower_ty(lctx: &LoweringContext, t: &Ty) -> P { }) } -pub fn lower_foreign_mod(lctx: &LoweringContext, fm: &ForeignMod) -> hir::ForeignMod { +pub fn lower_foreign_mod(lctx: &mut LoweringContext, fm: &ForeignMod) -> hir::ForeignMod { hir::ForeignMod { abi: fm.abi, items: fm.items.iter().map(|x| lower_foreign_item(lctx, x)).collect(), } } -pub fn lower_variant(lctx: &LoweringContext, v: &Variant) -> hir::Variant { +pub fn lower_variant(lctx: &mut LoweringContext, v: &Variant) -> hir::Variant { Spanned { node: hir::Variant_ { name: v.node.name.name, @@ -289,7 +289,7 @@ pub fn lower_variant(lctx: &LoweringContext, v: &Variant) -> hir::Variant { // Path segments are usually unhygienic, hygienic path segments can occur only in // identifier-like paths originating from `ExprPath`. // Make life simpler for rustc_resolve by renaming only such segments. -pub fn lower_path_full(lctx: &LoweringContext, p: &Path, maybe_hygienic: bool) -> hir::Path { +pub fn lower_path_full(lctx: &mut LoweringContext, p: &Path, maybe_hygienic: bool) -> hir::Path { let maybe_hygienic = maybe_hygienic && !p.global && p.segments.len() == 1; hir::Path { global: p.global, @@ -310,11 +310,11 @@ pub fn lower_path_full(lctx: &LoweringContext, p: &Path, maybe_hygienic: bool) - } } -pub fn lower_path(lctx: &LoweringContext, p: &Path) -> hir::Path { +pub fn lower_path(lctx: &mut LoweringContext, p: &Path) -> hir::Path { lower_path_full(lctx, p, false) } -pub fn lower_path_parameters(lctx: &LoweringContext, +pub fn lower_path_parameters(lctx: &mut LoweringContext, path_parameters: &PathParameters) -> hir::PathParameters { match *path_parameters { @@ -325,7 +325,7 @@ pub fn lower_path_parameters(lctx: &LoweringContext, } } -pub fn lower_angle_bracketed_parameter_data(lctx: &LoweringContext, +pub fn lower_angle_bracketed_parameter_data(lctx: &mut LoweringContext, data: &AngleBracketedParameterData) -> hir::AngleBracketedParameterData { let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data; @@ -336,7 +336,7 @@ pub fn lower_angle_bracketed_parameter_data(lctx: &LoweringContext, } } -pub fn lower_parenthesized_parameter_data(lctx: &LoweringContext, +pub fn lower_parenthesized_parameter_data(lctx: &mut LoweringContext, data: &ParenthesizedParameterData) -> hir::ParenthesizedParameterData { let &ParenthesizedParameterData { ref inputs, ref output, span } = data; @@ -347,7 +347,7 @@ pub fn lower_parenthesized_parameter_data(lctx: &LoweringContext, } } -pub fn lower_local(lctx: &LoweringContext, l: &Local) -> P { +pub fn lower_local(lctx: &mut LoweringContext, l: &Local) -> P { P(hir::Local { id: l.id, ty: l.ty.as_ref().map(|t| lower_ty(lctx, t)), @@ -358,7 +358,7 @@ pub fn lower_local(lctx: &LoweringContext, l: &Local) -> P { }) } -pub fn lower_explicit_self_underscore(lctx: &LoweringContext, +pub fn lower_explicit_self_underscore(lctx: &mut LoweringContext, es: &SelfKind) -> hir::ExplicitSelf_ { match *es { @@ -375,21 +375,21 @@ pub fn lower_explicit_self_underscore(lctx: &LoweringContext, } } -pub fn lower_mutability(_lctx: &LoweringContext, m: Mutability) -> hir::Mutability { +pub fn lower_mutability(_lctx: &mut LoweringContext, m: Mutability) -> hir::Mutability { match m { Mutability::Mutable => hir::MutMutable, Mutability::Immutable => hir::MutImmutable, } } -pub fn lower_explicit_self(lctx: &LoweringContext, s: &ExplicitSelf) -> hir::ExplicitSelf { +pub fn lower_explicit_self(lctx: &mut LoweringContext, s: &ExplicitSelf) -> hir::ExplicitSelf { Spanned { node: lower_explicit_self_underscore(lctx, &s.node), span: s.span, } } -pub fn lower_arg(lctx: &LoweringContext, arg: &Arg) -> hir::Arg { +pub fn lower_arg(lctx: &mut LoweringContext, arg: &Arg) -> hir::Arg { hir::Arg { id: arg.id, pat: lower_pat(lctx, &arg.pat), @@ -397,7 +397,7 @@ pub fn lower_arg(lctx: &LoweringContext, arg: &Arg) -> hir::Arg { } } -pub fn lower_fn_decl(lctx: &LoweringContext, decl: &FnDecl) -> P { +pub fn lower_fn_decl(lctx: &mut LoweringContext, decl: &FnDecl) -> P { P(hir::FnDecl { inputs: decl.inputs.iter().map(|x| lower_arg(lctx, x)).collect(), output: match decl.output { @@ -409,7 +409,7 @@ pub fn lower_fn_decl(lctx: &LoweringContext, decl: &FnDecl) -> P { }) } -pub fn lower_ty_param_bound(lctx: &LoweringContext, tpb: &TyParamBound) -> hir::TyParamBound { +pub fn lower_ty_param_bound(lctx: &mut LoweringContext, tpb: &TyParamBound) -> hir::TyParamBound { match *tpb { TraitTyParamBound(ref ty, modifier) => { hir::TraitTyParamBound(lower_poly_trait_ref(lctx, ty), @@ -421,7 +421,7 @@ pub fn lower_ty_param_bound(lctx: &LoweringContext, tpb: &TyParamBound) -> hir:: } } -pub fn lower_ty_param(lctx: &LoweringContext, tp: &TyParam) -> hir::TyParam { +pub fn lower_ty_param(lctx: &mut LoweringContext, tp: &TyParam) -> hir::TyParam { hir::TyParam { id: tp.id, name: tp.ident.name, @@ -431,13 +431,13 @@ pub fn lower_ty_param(lctx: &LoweringContext, tp: &TyParam) -> hir::TyParam { } } -pub fn lower_ty_params(lctx: &LoweringContext, +pub fn lower_ty_params(lctx: &mut LoweringContext, tps: &P<[TyParam]>) -> hir::HirVec { tps.iter().map(|tp| lower_ty_param(lctx, tp)).collect() } -pub fn lower_lifetime(_lctx: &LoweringContext, l: &Lifetime) -> hir::Lifetime { +pub fn lower_lifetime(_lctx: &mut LoweringContext, l: &Lifetime) -> hir::Lifetime { hir::Lifetime { id: l.id, name: l.name, @@ -445,30 +445,31 @@ pub fn lower_lifetime(_lctx: &LoweringContext, l: &Lifetime) -> hir::Lifetime { } } -pub fn lower_lifetime_def(lctx: &LoweringContext, l: &LifetimeDef) -> hir::LifetimeDef { +pub fn lower_lifetime_def(lctx: &mut LoweringContext, l: &LifetimeDef) -> hir::LifetimeDef { hir::LifetimeDef { lifetime: lower_lifetime(lctx, &l.lifetime), bounds: lower_lifetimes(lctx, &l.bounds), } } -pub fn lower_lifetimes(lctx: &LoweringContext, lts: &Vec) -> hir::HirVec { +pub fn lower_lifetimes(lctx: &mut LoweringContext, lts: &Vec) + -> hir::HirVec { lts.iter().map(|l| lower_lifetime(lctx, l)).collect() } -pub fn lower_lifetime_defs(lctx: &LoweringContext, +pub fn lower_lifetime_defs(lctx: &mut LoweringContext, lts: &Vec) -> hir::HirVec { lts.iter().map(|l| lower_lifetime_def(lctx, l)).collect() } -pub fn lower_opt_lifetime(lctx: &LoweringContext, +pub fn lower_opt_lifetime(lctx: &mut LoweringContext, o_lt: &Option) -> Option { o_lt.as_ref().map(|lt| lower_lifetime(lctx, lt)) } -pub fn lower_generics(lctx: &LoweringContext, g: &Generics) -> hir::Generics { +pub fn lower_generics(lctx: &mut LoweringContext, g: &Generics) -> hir::Generics { hir::Generics { ty_params: lower_ty_params(lctx, &g.ty_params), lifetimes: lower_lifetime_defs(lctx, &g.lifetimes), @@ -476,7 +477,7 @@ pub fn lower_generics(lctx: &LoweringContext, g: &Generics) -> hir::Generics { } } -pub fn lower_where_clause(lctx: &LoweringContext, wc: &WhereClause) -> hir::WhereClause { +pub fn lower_where_clause(lctx: &mut LoweringContext, wc: &WhereClause) -> hir::WhereClause { hir::WhereClause { id: wc.id, predicates: wc.predicates @@ -486,7 +487,7 @@ pub fn lower_where_clause(lctx: &LoweringContext, wc: &WhereClause) -> hir::Wher } } -pub fn lower_where_predicate(lctx: &LoweringContext, +pub fn lower_where_predicate(lctx: &mut LoweringContext, pred: &WherePredicate) -> hir::WherePredicate { match *pred { @@ -524,7 +525,7 @@ pub fn lower_where_predicate(lctx: &LoweringContext, } } -pub fn lower_variant_data(lctx: &LoweringContext, vdata: &VariantData) -> hir::VariantData { +pub fn lower_variant_data(lctx: &mut LoweringContext, vdata: &VariantData) -> hir::VariantData { match *vdata { VariantData::Struct(ref fields, id) => { hir::VariantData::Struct(fields.iter() @@ -544,14 +545,14 @@ pub fn lower_variant_data(lctx: &LoweringContext, vdata: &VariantData) -> hir::V } } -pub fn lower_trait_ref(lctx: &LoweringContext, p: &TraitRef) -> hir::TraitRef { +pub fn lower_trait_ref(lctx: &mut LoweringContext, p: &TraitRef) -> hir::TraitRef { hir::TraitRef { path: lower_path(lctx, &p.path), ref_id: p.ref_id, } } -pub fn lower_poly_trait_ref(lctx: &LoweringContext, p: &PolyTraitRef) -> hir::PolyTraitRef { +pub fn lower_poly_trait_ref(lctx: &mut LoweringContext, p: &PolyTraitRef) -> hir::PolyTraitRef { hir::PolyTraitRef { bound_lifetimes: lower_lifetime_defs(lctx, &p.bound_lifetimes), trait_ref: lower_trait_ref(lctx, &p.trait_ref), @@ -559,7 +560,7 @@ pub fn lower_poly_trait_ref(lctx: &LoweringContext, p: &PolyTraitRef) -> hir::Po } } -pub fn lower_struct_field(lctx: &LoweringContext, +pub fn lower_struct_field(lctx: &mut LoweringContext, (index, f): (usize, &StructField)) -> hir::StructField { hir::StructField { @@ -572,7 +573,7 @@ pub fn lower_struct_field(lctx: &LoweringContext, } } -pub fn lower_field(lctx: &LoweringContext, f: &Field) -> hir::Field { +pub fn lower_field(lctx: &mut LoweringContext, f: &Field) -> hir::Field { hir::Field { name: respan(f.ident.span, f.ident.node.name), expr: lower_expr(lctx, &f.expr), @@ -580,18 +581,18 @@ pub fn lower_field(lctx: &LoweringContext, f: &Field) -> hir::Field { } } -pub fn lower_mt(lctx: &LoweringContext, mt: &MutTy) -> hir::MutTy { +pub fn lower_mt(lctx: &mut LoweringContext, mt: &MutTy) -> hir::MutTy { hir::MutTy { ty: lower_ty(lctx, &mt.ty), mutbl: lower_mutability(lctx, mt.mutbl), } } -fn lower_bounds(lctx: &LoweringContext, bounds: &TyParamBounds) -> hir::TyParamBounds { +fn lower_bounds(lctx: &mut LoweringContext, bounds: &TyParamBounds) -> hir::TyParamBounds { bounds.iter().map(|bound| lower_ty_param_bound(lctx, bound)).collect() } -pub fn lower_block(lctx: &LoweringContext, b: &Block) -> P { +pub fn lower_block(lctx: &mut LoweringContext, b: &Block) -> P { P(hir::Block { id: b.id, stmts: b.stmts.iter().map(|s| lower_stmt(lctx, s)).collect(), @@ -601,7 +602,7 @@ pub fn lower_block(lctx: &LoweringContext, b: &Block) -> P { }) } -pub fn lower_item_kind(lctx: &LoweringContext, i: &ItemKind) -> hir::Item_ { +pub fn lower_item_kind(lctx: &mut LoweringContext, i: &ItemKind) -> hir::Item_ { match *i { ItemKind::ExternCrate(string) => hir::ItemExternCrate(string), ItemKind::Use(ref view_path) => { @@ -669,8 +670,8 @@ pub fn lower_item_kind(lctx: &LoweringContext, i: &ItemKind) -> hir::Item_ { } } -pub fn lower_trait_item(lctx: &LoweringContext, i: &TraitItem) -> hir::TraitItem { - lctx.with_parent_def(i.id, || { +pub fn lower_trait_item(lctx: &mut LoweringContext, i: &TraitItem) -> hir::TraitItem { + lctx.with_parent_def(i.id, |lctx| { hir::TraitItem { id: i.id, name: i.ident.name, @@ -694,8 +695,8 @@ pub fn lower_trait_item(lctx: &LoweringContext, i: &TraitItem) -> hir::TraitItem }) } -pub fn lower_impl_item(lctx: &LoweringContext, i: &ImplItem) -> hir::ImplItem { - lctx.with_parent_def(i.id, || { +pub fn lower_impl_item(lctx: &mut LoweringContext, i: &ImplItem) -> hir::ImplItem { + lctx.with_parent_def(i.id, |lctx| { hir::ImplItem { id: i.id, name: i.ident.name, @@ -717,7 +718,7 @@ pub fn lower_impl_item(lctx: &LoweringContext, i: &ImplItem) -> hir::ImplItem { }) } -pub fn lower_mod(lctx: &LoweringContext, m: &Mod) -> hir::Mod { +pub fn lower_mod(lctx: &mut LoweringContext, m: &Mod) -> hir::Mod { hir::Mod { inner: m.inner, item_ids: m.items.iter().map(|x| lower_item_id(lctx, x)).collect(), @@ -726,7 +727,7 @@ pub fn lower_mod(lctx: &LoweringContext, m: &Mod) -> hir::Mod { struct ItemLowerer<'lcx, 'interner: 'lcx> { items: BTreeMap, - lctx: &'lcx LoweringContext<'interner>, + lctx: &'lcx mut LoweringContext<'interner>, } impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> { @@ -736,7 +737,7 @@ impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> { } } -pub fn lower_crate(lctx: &LoweringContext, c: &Crate) -> hir::Crate { +pub fn lower_crate(lctx: &mut LoweringContext, c: &Crate) -> hir::Crate { let items = { let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), lctx: lctx }; visit::walk_crate(&mut item_lowerer, c); @@ -753,7 +754,7 @@ pub fn lower_crate(lctx: &LoweringContext, c: &Crate) -> hir::Crate { } } -pub fn lower_macro_def(lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef { +pub fn lower_macro_def(lctx: &mut LoweringContext, m: &MacroDef) -> hir::MacroDef { hir::MacroDef { name: m.ident.name, attrs: lower_attrs(lctx, &m.attrs), @@ -767,12 +768,12 @@ pub fn lower_macro_def(lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef { } } -pub fn lower_item_id(_lctx: &LoweringContext, i: &Item) -> hir::ItemId { +pub fn lower_item_id(_lctx: &mut LoweringContext, i: &Item) -> hir::ItemId { hir::ItemId { id: i.id } } -pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item { - let node = lctx.with_parent_def(i.id, || { +pub fn lower_item(lctx: &mut LoweringContext, i: &Item) -> hir::Item { + let node = lctx.with_parent_def(i.id, |lctx| { lower_item_kind(lctx, &i.node) }); @@ -786,8 +787,8 @@ pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item { } } -pub fn lower_foreign_item(lctx: &LoweringContext, i: &ForeignItem) -> hir::ForeignItem { - lctx.with_parent_def(i.id, || { +pub fn lower_foreign_item(lctx: &mut LoweringContext, i: &ForeignItem) -> hir::ForeignItem { + lctx.with_parent_def(i.id, |lctx| { hir::ForeignItem { id: i.id, name: i.ident.name, @@ -806,7 +807,7 @@ pub fn lower_foreign_item(lctx: &LoweringContext, i: &ForeignItem) -> hir::Forei }) } -pub fn lower_method_sig(lctx: &LoweringContext, sig: &MethodSig) -> hir::MethodSig { +pub fn lower_method_sig(lctx: &mut LoweringContext, sig: &MethodSig) -> hir::MethodSig { hir::MethodSig { generics: lower_generics(lctx, &sig.generics), abi: sig.abi, @@ -817,21 +818,21 @@ pub fn lower_method_sig(lctx: &LoweringContext, sig: &MethodSig) -> hir::MethodS } } -pub fn lower_unsafety(_lctx: &LoweringContext, u: Unsafety) -> hir::Unsafety { +pub fn lower_unsafety(_lctx: &mut LoweringContext, u: Unsafety) -> hir::Unsafety { match u { Unsafety::Unsafe => hir::Unsafety::Unsafe, Unsafety::Normal => hir::Unsafety::Normal, } } -pub fn lower_constness(_lctx: &LoweringContext, c: Constness) -> hir::Constness { +pub fn lower_constness(_lctx: &mut LoweringContext, c: Constness) -> hir::Constness { match c { Constness::Const => hir::Constness::Const, Constness::NotConst => hir::Constness::NotConst, } } -pub fn lower_unop(_lctx: &LoweringContext, u: UnOp) -> hir::UnOp { +pub fn lower_unop(_lctx: &mut LoweringContext, u: UnOp) -> hir::UnOp { match u { UnOp::Deref => hir::UnDeref, UnOp::Not => hir::UnNot, @@ -839,7 +840,7 @@ pub fn lower_unop(_lctx: &LoweringContext, u: UnOp) -> hir::UnOp { } } -pub fn lower_binop(_lctx: &LoweringContext, b: BinOp) -> hir::BinOp { +pub fn lower_binop(_lctx: &mut LoweringContext, b: BinOp) -> hir::BinOp { Spanned { node: match b.node { BinOpKind::Add => hir::BiAdd, @@ -865,13 +866,13 @@ pub fn lower_binop(_lctx: &LoweringContext, b: BinOp) -> hir::BinOp { } } -pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P { +pub fn lower_pat(lctx: &mut LoweringContext, p: &Pat) -> P { P(hir::Pat { id: p.id, node: match p.node { PatKind::Wild => hir::PatKind::Wild, PatKind::Ident(ref binding_mode, pth1, ref sub) => { - lctx.with_parent_def(p.id, || { + lctx.with_parent_def(p.id, |lctx| { hir::PatKind::Ident(lower_binding_mode(lctx, binding_mode), respan(pth1.span, lower_ident(lctx, pth1.node)), sub.as_ref().map(|x| lower_pat(lctx, x))) @@ -930,7 +931,7 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P { }) } -pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { +pub fn lower_expr(lctx: &mut LoweringContext, e: &Expr) -> P { P(hir::Expr { id: e.id, node: match e.node { @@ -977,17 +978,17 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { let move_val_init = ["intrinsics", "move_val_init"]; let inplace_finalize = ["ops", "InPlace", "finalize"]; - let make_call = |lctx: &LoweringContext, p, args| { + let make_call = |lctx: &mut LoweringContext, p, args| { let path = core_path(lctx, e.span, p); let path = expr_path(lctx, path, None); expr_call(lctx, e.span, path, args, None) }; - let mk_stmt_let = |lctx: &LoweringContext, bind, expr| { + let mk_stmt_let = |lctx: &mut LoweringContext, bind, expr| { stmt_let(lctx, e.span, false, bind, expr, None) }; - let mk_stmt_let_mut = |lctx: &LoweringContext, bind, expr| { + let mk_stmt_let_mut = |lctx: &mut LoweringContext, bind, expr| { stmt_let(lctx, e.span, true, bind, expr, None) }; @@ -1145,7 +1146,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { hir::MatchSource::Normal) } ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => { - lctx.with_parent_def(e.id, || { + lctx.with_parent_def(e.id, |lctx| { hir::ExprClosure(lower_capture_clause(lctx, capture_clause), lower_fn_decl(lctx, decl), lower_block(lctx, body), @@ -1171,7 +1172,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { hir::ExprIndex(lower_expr(lctx, el), lower_expr(lctx, er)) } ExprKind::Range(ref e1, ref e2, lims) => { - fn make_struct(lctx: &LoweringContext, + fn make_struct(lctx: &mut LoweringContext, ast_expr: &Expr, path: &[&str], fields: &[(&str, &P)]) -> P { @@ -1187,21 +1188,19 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { structpath, ast_expr.attrs.clone()) } else { - expr_struct(lctx, - ast_expr.span, - structpath, - fields.into_iter().map(|&(s, e)| { - field(token::intern(s), - signal_block_expr(lctx, - hir_vec![], - lower_expr(lctx, &**e), - e.span, - hir::PopUnstableBlock, - None), - ast_expr.span) - }).collect(), - None, - ast_expr.attrs.clone()) + let fields = fields.into_iter().map(|&(s, e)| { + let expr = lower_expr(lctx, &e); + let signal_block = signal_block_expr(lctx, + hir_vec![], + expr, + e.span, + hir::PopUnstableBlock, + None); + field(token::intern(s), signal_block, ast_expr.span) + }).collect(); + let attrs = ast_expr.attrs.clone(); + + expr_struct(lctx, ast_expr.span, structpath, fields, None, attrs) }; signal_block_expr(lctx, @@ -1613,7 +1612,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { }) } -pub fn lower_stmt(lctx: &LoweringContext, s: &Stmt) -> hir::Stmt { +pub fn lower_stmt(lctx: &mut LoweringContext, s: &Stmt) -> hir::Stmt { match s.node { StmtKind::Decl(ref d, id) => { Spanned { @@ -1637,14 +1636,14 @@ pub fn lower_stmt(lctx: &LoweringContext, s: &Stmt) -> hir::Stmt { } } -pub fn lower_capture_clause(_lctx: &LoweringContext, c: CaptureBy) -> hir::CaptureClause { +pub fn lower_capture_clause(_lctx: &mut LoweringContext, c: CaptureBy) -> hir::CaptureClause { match c { CaptureBy::Value => hir::CaptureByValue, CaptureBy::Ref => hir::CaptureByRef, } } -pub fn lower_visibility(lctx: &LoweringContext, v: &Visibility) -> hir::Visibility { +pub fn lower_visibility(lctx: &mut LoweringContext, v: &Visibility) -> hir::Visibility { match *v { Visibility::Public => hir::Public, Visibility::Crate(_) => hir::Visibility::Crate, @@ -1654,42 +1653,42 @@ pub fn lower_visibility(lctx: &LoweringContext, v: &Visibility) -> hir::Visibili } } -pub fn lower_defaultness(_lctx: &LoweringContext, d: Defaultness) -> hir::Defaultness { +pub fn lower_defaultness(_lctx: &mut LoweringContext, d: Defaultness) -> hir::Defaultness { match d { Defaultness::Default => hir::Defaultness::Default, Defaultness::Final => hir::Defaultness::Final, } } -pub fn lower_block_check_mode(lctx: &LoweringContext, b: &BlockCheckMode) -> hir::BlockCheckMode { +pub fn lower_block_check_mode(lctx: &mut LoweringContext, b: &BlockCheckMode) -> hir::BlockCheckMode { match *b { BlockCheckMode::Default => hir::DefaultBlock, BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(lower_unsafe_source(lctx, u)), } } -pub fn lower_binding_mode(lctx: &LoweringContext, b: &BindingMode) -> hir::BindingMode { +pub fn lower_binding_mode(lctx: &mut LoweringContext, b: &BindingMode) -> hir::BindingMode { match *b { BindingMode::ByRef(m) => hir::BindByRef(lower_mutability(lctx, m)), BindingMode::ByValue(m) => hir::BindByValue(lower_mutability(lctx, m)), } } -pub fn lower_unsafe_source(_lctx: &LoweringContext, u: UnsafeSource) -> hir::UnsafeSource { +pub fn lower_unsafe_source(_lctx: &mut LoweringContext, u: UnsafeSource) -> hir::UnsafeSource { match u { CompilerGenerated => hir::CompilerGenerated, UserProvided => hir::UserProvided, } } -pub fn lower_impl_polarity(_lctx: &LoweringContext, i: ImplPolarity) -> hir::ImplPolarity { +pub fn lower_impl_polarity(_lctx: &mut LoweringContext, i: ImplPolarity) -> hir::ImplPolarity { match i { ImplPolarity::Positive => hir::ImplPolarity::Positive, ImplPolarity::Negative => hir::ImplPolarity::Negative, } } -pub fn lower_trait_bound_modifier(_lctx: &LoweringContext, +pub fn lower_trait_bound_modifier(_lctx: &mut LoweringContext, f: TraitBoundModifier) -> hir::TraitBoundModifier { match f { @@ -1720,12 +1719,12 @@ fn field(name: Name, expr: P, span: Span) -> hir::Field { } } -fn expr_break(lctx: &LoweringContext, span: Span, +fn expr_break(lctx: &mut LoweringContext, span: Span, attrs: ThinAttributes) -> P { expr(lctx, span, hir::ExprBreak(None), attrs) } -fn expr_call(lctx: &LoweringContext, +fn expr_call(lctx: &mut LoweringContext, span: Span, e: P, args: hir::HirVec>, @@ -1734,32 +1733,32 @@ fn expr_call(lctx: &LoweringContext, expr(lctx, span, hir::ExprCall(e, args), attrs) } -fn expr_ident(lctx: &LoweringContext, span: Span, id: hir::Ident, +fn expr_ident(lctx: &mut LoweringContext, span: Span, id: hir::Ident, attrs: ThinAttributes, binding: NodeId) -> P { let expr = expr(lctx, span, hir::ExprPath(None, path_ident(span, id)), attrs); - let mut resolver = lctx.resolver.borrow_mut(); - let def = resolver.definitions().map(|defs| Def::Local(defs.local_def_id(binding), binding)) - .unwrap_or(Def::Err); - resolver.record_resolution(expr.id, def); + let def = lctx.resolver.definitions().map(|defs| { + Def::Local(defs.local_def_id(binding), binding) + }).unwrap_or(Def::Err); + lctx.resolver.record_resolution(expr.id, def); expr } -fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P, +fn expr_mut_addr_of(lctx: &mut LoweringContext, span: Span, e: P, attrs: ThinAttributes) -> P { expr(lctx, span, hir::ExprAddrOf(hir::MutMutable, e), attrs) } -fn expr_path(lctx: &LoweringContext, path: hir::Path, +fn expr_path(lctx: &mut LoweringContext, path: hir::Path, attrs: ThinAttributes) -> P { - let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, true); + let def = lctx.resolver.resolve_generated_global_path(&path, true); let expr = expr(lctx, path.span, hir::ExprPath(None, path), attrs); - lctx.resolver.borrow_mut().record_resolution(expr.id, def); + lctx.resolver.record_resolution(expr.id, def); expr } -fn expr_match(lctx: &LoweringContext, +fn expr_match(lctx: &mut LoweringContext, span: Span, arg: P, arms: hir::HirVec, @@ -1769,30 +1768,30 @@ fn expr_match(lctx: &LoweringContext, expr(lctx, span, hir::ExprMatch(arg, arms, source), attrs) } -fn expr_block(lctx: &LoweringContext, b: P, +fn expr_block(lctx: &mut LoweringContext, b: P, attrs: ThinAttributes) -> P { expr(lctx, b.span, hir::ExprBlock(b), attrs) } -fn expr_tuple(lctx: &LoweringContext, sp: Span, exprs: hir::HirVec>, +fn expr_tuple(lctx: &mut LoweringContext, sp: Span, exprs: hir::HirVec>, attrs: ThinAttributes) -> P { expr(lctx, sp, hir::ExprTup(exprs), attrs) } -fn expr_struct(lctx: &LoweringContext, +fn expr_struct(lctx: &mut LoweringContext, sp: Span, path: hir::Path, fields: hir::HirVec, e: Option>, attrs: ThinAttributes) -> P { - let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, false); + let def = lctx.resolver.resolve_generated_global_path(&path, false); let expr = expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs); - lctx.resolver.borrow_mut().record_resolution(expr.id, def); + lctx.resolver.record_resolution(expr.id, def); expr } -fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_, +fn expr(lctx: &mut LoweringContext, span: Span, node: hir::Expr_, attrs: ThinAttributes) -> P { P(hir::Expr { id: lctx.next_id(), @@ -1802,7 +1801,7 @@ fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_, }) } -fn stmt_let(lctx: &LoweringContext, +fn stmt_let(lctx: &mut LoweringContext, sp: Span, mutbl: bool, ident: hir::Ident, @@ -1827,11 +1826,11 @@ fn stmt_let(lctx: &LoweringContext, (respan(sp, hir::StmtDecl(P(decl), lctx.next_id())), pat_id) } -fn block_expr(lctx: &LoweringContext, expr: P) -> P { +fn block_expr(lctx: &mut LoweringContext, expr: P) -> P { block_all(lctx, expr.span, hir::HirVec::new(), Some(expr)) } -fn block_all(lctx: &LoweringContext, +fn block_all(lctx: &mut LoweringContext, span: Span, stmts: hir::HirVec, expr: Option>) @@ -1845,51 +1844,51 @@ fn block_all(lctx: &LoweringContext, }) } -fn pat_ok(lctx: &LoweringContext, span: Span, pat: P) -> P { +fn pat_ok(lctx: &mut LoweringContext, span: Span, pat: P) -> P { let ok = std_path(lctx, &["result", "Result", "Ok"]); let path = path_global(span, ok); pat_enum(lctx, span, path, hir_vec![pat]) } -fn pat_err(lctx: &LoweringContext, span: Span, pat: P) -> P { +fn pat_err(lctx: &mut LoweringContext, span: Span, pat: P) -> P { let err = std_path(lctx, &["result", "Result", "Err"]); let path = path_global(span, err); pat_enum(lctx, span, path, hir_vec![pat]) } -fn pat_some(lctx: &LoweringContext, span: Span, pat: P) -> P { +fn pat_some(lctx: &mut LoweringContext, span: Span, pat: P) -> P { let some = std_path(lctx, &["option", "Option", "Some"]); let path = path_global(span, some); pat_enum(lctx, span, path, hir_vec![pat]) } -fn pat_none(lctx: &LoweringContext, span: Span) -> P { +fn pat_none(lctx: &mut LoweringContext, span: Span) -> P { let none = std_path(lctx, &["option", "Option", "None"]); let path = path_global(span, none); pat_enum(lctx, span, path, hir_vec![]) } -fn pat_enum(lctx: &LoweringContext, +fn pat_enum(lctx: &mut LoweringContext, span: Span, path: hir::Path, subpats: hir::HirVec>) -> P { - let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, true); + let def = lctx.resolver.resolve_generated_global_path(&path, true); let pt = if subpats.is_empty() { hir::PatKind::Path(path) } else { hir::PatKind::TupleStruct(path, Some(subpats)) }; let pat = pat(lctx, span, pt); - lctx.resolver.borrow_mut().record_resolution(pat.id, def); + lctx.resolver.record_resolution(pat.id, def); pat } -fn pat_ident(lctx: &LoweringContext, span: Span, ident: hir::Ident) -> P { +fn pat_ident(lctx: &mut LoweringContext, span: Span, ident: hir::Ident) -> P { pat_ident_binding_mode(lctx, span, ident, hir::BindByValue(hir::MutImmutable)) } -fn pat_ident_binding_mode(lctx: &LoweringContext, +fn pat_ident_binding_mode(lctx: &mut LoweringContext, span: Span, ident: hir::Ident, bm: hir::BindingMode) @@ -1903,22 +1902,22 @@ fn pat_ident_binding_mode(lctx: &LoweringContext, let pat = pat(lctx, span, pat_ident); - let mut resolver = lctx.resolver.borrow_mut(); - let def = resolver.definitions().map(|defs| { + let parent_def = lctx.parent_def; + let def = lctx.resolver.definitions().map(|defs| { let def_path_data = DefPathData::Binding(ident.name); - let def_index = defs.create_def_with_parent(lctx.parent_def.get(), pat.id, def_path_data); + let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data); Def::Local(DefId::local(def_index), pat.id) }).unwrap_or(Def::Err); - resolver.record_resolution(pat.id, def); + lctx.resolver.record_resolution(pat.id, def); pat } -fn pat_wild(lctx: &LoweringContext, span: Span) -> P { +fn pat_wild(lctx: &mut LoweringContext, span: Span) -> P { pat(lctx, span, hir::PatKind::Wild) } -fn pat(lctx: &LoweringContext, span: Span, pat: hir::PatKind) -> P { +fn pat(lctx: &mut LoweringContext, span: Span, pat: hir::PatKind) -> P { P(hir::Pat { id: lctx.next_id(), node: pat, @@ -1969,7 +1968,7 @@ fn path_all(sp: Span, } } -fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec { +fn std_path(lctx: &mut LoweringContext, components: &[&str]) -> Vec { let mut v = Vec::new(); if let Some(s) = lctx.crate_root { v.push(hir::Ident::from_name(token::intern(s))); @@ -1980,12 +1979,12 @@ fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec { // Given suffix ["b","c","d"], returns path `::std::b::c::d` when // `fld.cx.use_std`, and `::core::b::c::d` otherwise. -fn core_path(lctx: &LoweringContext, span: Span, components: &[&str]) -> hir::Path { +fn core_path(lctx: &mut LoweringContext, span: Span, components: &[&str]) -> hir::Path { let idents = std_path(lctx, components); path_global(span, idents) } -fn signal_block_expr(lctx: &LoweringContext, +fn signal_block_expr(lctx: &mut LoweringContext, stmts: hir::HirVec, expr: P, span: Span, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e72204e5e22de..66b1b28a0e505 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -787,8 +787,8 @@ pub fn lower_and_resolve<'a>(sess: &Session, // Lower ast -> hir. let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { - let lcx = LoweringContext::new(sess, Some(krate), &mut resolver); - hir_map::Forest::new(lower_crate(&lcx, krate), dep_graph) + let mut lcx = LoweringContext::new(sess, Some(krate), &mut resolver); + hir_map::Forest::new(lower_crate(&mut lcx, krate), dep_graph) }); (ty::CrateAnalysis { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 56f6a3f7b14cb..ce525b716ff2c 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -1326,11 +1326,11 @@ fn mk_ctxt() -> parse::ParseSess { } #[cfg(test)] -fn with_testing_context T>(f: F) -> T { +fn with_testing_context T>(f: F) -> T { let assigner = FakeNodeIdAssigner; let mut resolver = DummyResolver; - let lcx = LoweringContext::new(&assigner, None, &mut resolver); - f(lcx) + let mut lcx = LoweringContext::new(&assigner, None, &mut resolver); + f(&mut lcx) } #[cfg(test)] @@ -1347,7 +1347,7 @@ fn roundtrip(in_item: hir::Item) { fn test_basic() { let cx = mk_ctxt(); with_testing_context(|lcx| { - roundtrip(lower_item(&lcx, "e_item!(&cx, + roundtrip(lower_item(lcx, "e_item!(&cx, fn foo() {} ).unwrap())); }); @@ -1357,7 +1357,7 @@ fn test_basic() { fn test_smalltalk() { let cx = mk_ctxt(); with_testing_context(|lcx| { - roundtrip(lower_item(&lcx, "e_item!(&cx, + roundtrip(lower_item(lcx, "e_item!(&cx, fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed. ).unwrap())); }); @@ -1367,7 +1367,7 @@ fn test_smalltalk() { fn test_more() { let cx = mk_ctxt(); with_testing_context(|lcx| { - roundtrip(lower_item(&lcx, "e_item!(&cx, + roundtrip(lower_item(lcx, "e_item!(&cx, fn foo(x: usize, y: usize) -> usize { let z = x + y; return z; @@ -1387,10 +1387,10 @@ fn test_simplification() { ).unwrap(); let cx = mk_ctxt(); with_testing_context(|lcx| { - let hir_item = lower_item(&lcx, &item); + let hir_item = lower_item(lcx, &item); let item_in = InlinedItemRef::Item(&hir_item); let item_out = simplify_ast(item_in); - let item_exp = InlinedItem::Item(P(lower_item(&lcx, "e_item!(&cx, + let item_exp = InlinedItem::Item(P(lower_item(lcx, "e_item!(&cx, fn new_int_alist() -> alist { return alist {eq_fn: eq_int, data: Vec::new()}; } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index fc548924e2964..0f518900ea787 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -98,8 +98,8 @@ pub fn run(input: &str, let defs = &RefCell::new(hir_map::collect_definitions(&krate)); let mut dummy_resolver = DummyResolver; - let lcx = LoweringContext::new(&sess, Some(&krate), &mut dummy_resolver); - let krate = lower_crate(&lcx, &krate); + let mut lcx = LoweringContext::new(&sess, Some(&krate), &mut dummy_resolver); + let krate = lower_crate(&mut lcx, &krate); let opts = scrape_test_config(&krate); From 8d5c5785d58f435d2d6e6e408e20c5c0b02a8e41 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 10 May 2016 00:05:50 +0000 Subject: [PATCH 05/50] Remove needless `pub`s --- src/librustc/hir/lowering.rs | 162 +++++++++++++++++------------------ 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index dc4ed655c9b88..40f6fddf10970 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -138,18 +138,18 @@ impl<'a> LoweringContext<'a> { } } -pub fn lower_ident(_lctx: &mut LoweringContext, ident: Ident) -> hir::Ident { +fn lower_ident(_lctx: &mut LoweringContext, ident: Ident) -> hir::Ident { hir::Ident { name: mtwt::resolve(ident), unhygienic_name: ident.name, } } -pub fn lower_attrs(_lctx: &mut LoweringContext, attrs: &Vec) -> hir::HirVec { +fn lower_attrs(_lctx: &mut LoweringContext, attrs: &Vec) -> hir::HirVec { attrs.clone().into() } -pub fn lower_view_path(lctx: &mut LoweringContext, view_path: &ViewPath) -> P { +fn lower_view_path(lctx: &mut LoweringContext, view_path: &ViewPath) -> P { P(Spanned { node: match view_path.node { ViewPathSimple(ident, ref path) => { @@ -186,7 +186,7 @@ fn lower_path_list_item(path_list_ident: &PathListItem) -> hir::PathListItem { } } -pub fn lower_arm(lctx: &mut LoweringContext, arm: &Arm) -> hir::Arm { +fn lower_arm(lctx: &mut LoweringContext, arm: &Arm) -> hir::Arm { hir::Arm { attrs: lower_attrs(lctx, &arm.attrs), pats: arm.pats.iter().map(|x| lower_pat(lctx, x)).collect(), @@ -195,7 +195,7 @@ pub fn lower_arm(lctx: &mut LoweringContext, arm: &Arm) -> hir::Arm { } } -pub fn lower_decl(lctx: &mut LoweringContext, d: &Decl) -> P { +fn lower_decl(lctx: &mut LoweringContext, d: &Decl) -> P { match d.node { DeclKind::Local(ref l) => P(Spanned { node: hir::DeclLocal(lower_local(lctx, l)), @@ -208,7 +208,7 @@ pub fn lower_decl(lctx: &mut LoweringContext, d: &Decl) -> P { } } -pub fn lower_ty_binding(lctx: &mut LoweringContext, b: &TypeBinding) -> hir::TypeBinding { +fn lower_ty_binding(lctx: &mut LoweringContext, b: &TypeBinding) -> hir::TypeBinding { hir::TypeBinding { id: b.id, name: b.ident.name, @@ -217,7 +217,7 @@ pub fn lower_ty_binding(lctx: &mut LoweringContext, b: &TypeBinding) -> hir::Typ } } -pub fn lower_ty(lctx: &mut LoweringContext, t: &Ty) -> P { +fn lower_ty(lctx: &mut LoweringContext, t: &Ty) -> P { use syntax::ast::TyKind::*; P(hir::Ty { id: t.id, @@ -267,14 +267,14 @@ pub fn lower_ty(lctx: &mut LoweringContext, t: &Ty) -> P { }) } -pub fn lower_foreign_mod(lctx: &mut LoweringContext, fm: &ForeignMod) -> hir::ForeignMod { +fn lower_foreign_mod(lctx: &mut LoweringContext, fm: &ForeignMod) -> hir::ForeignMod { hir::ForeignMod { abi: fm.abi, items: fm.items.iter().map(|x| lower_foreign_item(lctx, x)).collect(), } } -pub fn lower_variant(lctx: &mut LoweringContext, v: &Variant) -> hir::Variant { +fn lower_variant(lctx: &mut LoweringContext, v: &Variant) -> hir::Variant { Spanned { node: hir::Variant_ { name: v.node.name.name, @@ -289,7 +289,7 @@ pub fn lower_variant(lctx: &mut LoweringContext, v: &Variant) -> hir::Variant { // Path segments are usually unhygienic, hygienic path segments can occur only in // identifier-like paths originating from `ExprPath`. // Make life simpler for rustc_resolve by renaming only such segments. -pub fn lower_path_full(lctx: &mut LoweringContext, p: &Path, maybe_hygienic: bool) -> hir::Path { +fn lower_path_full(lctx: &mut LoweringContext, p: &Path, maybe_hygienic: bool) -> hir::Path { let maybe_hygienic = maybe_hygienic && !p.global && p.segments.len() == 1; hir::Path { global: p.global, @@ -310,13 +310,13 @@ pub fn lower_path_full(lctx: &mut LoweringContext, p: &Path, maybe_hygienic: boo } } -pub fn lower_path(lctx: &mut LoweringContext, p: &Path) -> hir::Path { +fn lower_path(lctx: &mut LoweringContext, p: &Path) -> hir::Path { lower_path_full(lctx, p, false) } -pub fn lower_path_parameters(lctx: &mut LoweringContext, - path_parameters: &PathParameters) - -> hir::PathParameters { +fn lower_path_parameters(lctx: &mut LoweringContext, + path_parameters: &PathParameters) + -> hir::PathParameters { match *path_parameters { PathParameters::AngleBracketed(ref data) => hir::AngleBracketedParameters(lower_angle_bracketed_parameter_data(lctx, data)), @@ -325,9 +325,9 @@ pub fn lower_path_parameters(lctx: &mut LoweringContext, } } -pub fn lower_angle_bracketed_parameter_data(lctx: &mut LoweringContext, - data: &AngleBracketedParameterData) - -> hir::AngleBracketedParameterData { +fn lower_angle_bracketed_parameter_data(lctx: &mut LoweringContext, + data: &AngleBracketedParameterData) + -> hir::AngleBracketedParameterData { let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data; hir::AngleBracketedParameterData { lifetimes: lower_lifetimes(lctx, lifetimes), @@ -336,9 +336,9 @@ pub fn lower_angle_bracketed_parameter_data(lctx: &mut LoweringContext, } } -pub fn lower_parenthesized_parameter_data(lctx: &mut LoweringContext, - data: &ParenthesizedParameterData) - -> hir::ParenthesizedParameterData { +fn lower_parenthesized_parameter_data(lctx: &mut LoweringContext, + data: &ParenthesizedParameterData) + -> hir::ParenthesizedParameterData { let &ParenthesizedParameterData { ref inputs, ref output, span } = data; hir::ParenthesizedParameterData { inputs: inputs.iter().map(|ty| lower_ty(lctx, ty)).collect(), @@ -347,7 +347,7 @@ pub fn lower_parenthesized_parameter_data(lctx: &mut LoweringContext, } } -pub fn lower_local(lctx: &mut LoweringContext, l: &Local) -> P { +fn lower_local(lctx: &mut LoweringContext, l: &Local) -> P { P(hir::Local { id: l.id, ty: l.ty.as_ref().map(|t| lower_ty(lctx, t)), @@ -358,9 +358,9 @@ pub fn lower_local(lctx: &mut LoweringContext, l: &Local) -> P { }) } -pub fn lower_explicit_self_underscore(lctx: &mut LoweringContext, - es: &SelfKind) - -> hir::ExplicitSelf_ { +fn lower_explicit_self_underscore(lctx: &mut LoweringContext, + es: &SelfKind) + -> hir::ExplicitSelf_ { match *es { SelfKind::Static => hir::SelfStatic, SelfKind::Value(v) => hir::SelfValue(v.name), @@ -375,21 +375,21 @@ pub fn lower_explicit_self_underscore(lctx: &mut LoweringContext, } } -pub fn lower_mutability(_lctx: &mut LoweringContext, m: Mutability) -> hir::Mutability { +fn lower_mutability(_lctx: &mut LoweringContext, m: Mutability) -> hir::Mutability { match m { Mutability::Mutable => hir::MutMutable, Mutability::Immutable => hir::MutImmutable, } } -pub fn lower_explicit_self(lctx: &mut LoweringContext, s: &ExplicitSelf) -> hir::ExplicitSelf { +fn lower_explicit_self(lctx: &mut LoweringContext, s: &ExplicitSelf) -> hir::ExplicitSelf { Spanned { node: lower_explicit_self_underscore(lctx, &s.node), span: s.span, } } -pub fn lower_arg(lctx: &mut LoweringContext, arg: &Arg) -> hir::Arg { +fn lower_arg(lctx: &mut LoweringContext, arg: &Arg) -> hir::Arg { hir::Arg { id: arg.id, pat: lower_pat(lctx, &arg.pat), @@ -397,7 +397,7 @@ pub fn lower_arg(lctx: &mut LoweringContext, arg: &Arg) -> hir::Arg { } } -pub fn lower_fn_decl(lctx: &mut LoweringContext, decl: &FnDecl) -> P { +fn lower_fn_decl(lctx: &mut LoweringContext, decl: &FnDecl) -> P { P(hir::FnDecl { inputs: decl.inputs.iter().map(|x| lower_arg(lctx, x)).collect(), output: match decl.output { @@ -409,7 +409,7 @@ pub fn lower_fn_decl(lctx: &mut LoweringContext, decl: &FnDecl) -> P hir::TyParamBound { +fn lower_ty_param_bound(lctx: &mut LoweringContext, tpb: &TyParamBound) -> hir::TyParamBound { match *tpb { TraitTyParamBound(ref ty, modifier) => { hir::TraitTyParamBound(lower_poly_trait_ref(lctx, ty), @@ -421,7 +421,7 @@ pub fn lower_ty_param_bound(lctx: &mut LoweringContext, tpb: &TyParamBound) -> h } } -pub fn lower_ty_param(lctx: &mut LoweringContext, tp: &TyParam) -> hir::TyParam { +fn lower_ty_param(lctx: &mut LoweringContext, tp: &TyParam) -> hir::TyParam { hir::TyParam { id: tp.id, name: tp.ident.name, @@ -431,13 +431,13 @@ pub fn lower_ty_param(lctx: &mut LoweringContext, tp: &TyParam) -> hir::TyParam } } -pub fn lower_ty_params(lctx: &mut LoweringContext, - tps: &P<[TyParam]>) - -> hir::HirVec { +fn lower_ty_params(lctx: &mut LoweringContext, + tps: &P<[TyParam]>) + -> hir::HirVec { tps.iter().map(|tp| lower_ty_param(lctx, tp)).collect() } -pub fn lower_lifetime(_lctx: &mut LoweringContext, l: &Lifetime) -> hir::Lifetime { +fn lower_lifetime(_lctx: &mut LoweringContext, l: &Lifetime) -> hir::Lifetime { hir::Lifetime { id: l.id, name: l.name, @@ -445,31 +445,31 @@ pub fn lower_lifetime(_lctx: &mut LoweringContext, l: &Lifetime) -> hir::Lifetim } } -pub fn lower_lifetime_def(lctx: &mut LoweringContext, l: &LifetimeDef) -> hir::LifetimeDef { +fn lower_lifetime_def(lctx: &mut LoweringContext, l: &LifetimeDef) -> hir::LifetimeDef { hir::LifetimeDef { lifetime: lower_lifetime(lctx, &l.lifetime), bounds: lower_lifetimes(lctx, &l.bounds), } } -pub fn lower_lifetimes(lctx: &mut LoweringContext, lts: &Vec) +fn lower_lifetimes(lctx: &mut LoweringContext, lts: &Vec) -> hir::HirVec { lts.iter().map(|l| lower_lifetime(lctx, l)).collect() } -pub fn lower_lifetime_defs(lctx: &mut LoweringContext, - lts: &Vec) - -> hir::HirVec { +fn lower_lifetime_defs(lctx: &mut LoweringContext, + lts: &Vec) + -> hir::HirVec { lts.iter().map(|l| lower_lifetime_def(lctx, l)).collect() } -pub fn lower_opt_lifetime(lctx: &mut LoweringContext, - o_lt: &Option) - -> Option { +fn lower_opt_lifetime(lctx: &mut LoweringContext, + o_lt: &Option) + -> Option { o_lt.as_ref().map(|lt| lower_lifetime(lctx, lt)) } -pub fn lower_generics(lctx: &mut LoweringContext, g: &Generics) -> hir::Generics { +fn lower_generics(lctx: &mut LoweringContext, g: &Generics) -> hir::Generics { hir::Generics { ty_params: lower_ty_params(lctx, &g.ty_params), lifetimes: lower_lifetime_defs(lctx, &g.lifetimes), @@ -477,7 +477,7 @@ pub fn lower_generics(lctx: &mut LoweringContext, g: &Generics) -> hir::Generics } } -pub fn lower_where_clause(lctx: &mut LoweringContext, wc: &WhereClause) -> hir::WhereClause { +fn lower_where_clause(lctx: &mut LoweringContext, wc: &WhereClause) -> hir::WhereClause { hir::WhereClause { id: wc.id, predicates: wc.predicates @@ -487,9 +487,9 @@ pub fn lower_where_clause(lctx: &mut LoweringContext, wc: &WhereClause) -> hir:: } } -pub fn lower_where_predicate(lctx: &mut LoweringContext, - pred: &WherePredicate) - -> hir::WherePredicate { +fn lower_where_predicate(lctx: &mut LoweringContext, + pred: &WherePredicate) + -> hir::WherePredicate { match *pred { WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes, ref bounded_ty, @@ -525,7 +525,7 @@ pub fn lower_where_predicate(lctx: &mut LoweringContext, } } -pub fn lower_variant_data(lctx: &mut LoweringContext, vdata: &VariantData) -> hir::VariantData { +fn lower_variant_data(lctx: &mut LoweringContext, vdata: &VariantData) -> hir::VariantData { match *vdata { VariantData::Struct(ref fields, id) => { hir::VariantData::Struct(fields.iter() @@ -545,14 +545,14 @@ pub fn lower_variant_data(lctx: &mut LoweringContext, vdata: &VariantData) -> hi } } -pub fn lower_trait_ref(lctx: &mut LoweringContext, p: &TraitRef) -> hir::TraitRef { +fn lower_trait_ref(lctx: &mut LoweringContext, p: &TraitRef) -> hir::TraitRef { hir::TraitRef { path: lower_path(lctx, &p.path), ref_id: p.ref_id, } } -pub fn lower_poly_trait_ref(lctx: &mut LoweringContext, p: &PolyTraitRef) -> hir::PolyTraitRef { +fn lower_poly_trait_ref(lctx: &mut LoweringContext, p: &PolyTraitRef) -> hir::PolyTraitRef { hir::PolyTraitRef { bound_lifetimes: lower_lifetime_defs(lctx, &p.bound_lifetimes), trait_ref: lower_trait_ref(lctx, &p.trait_ref), @@ -560,9 +560,9 @@ pub fn lower_poly_trait_ref(lctx: &mut LoweringContext, p: &PolyTraitRef) -> hir } } -pub fn lower_struct_field(lctx: &mut LoweringContext, - (index, f): (usize, &StructField)) - -> hir::StructField { +fn lower_struct_field(lctx: &mut LoweringContext, + (index, f): (usize, &StructField)) + -> hir::StructField { hir::StructField { span: f.span, id: f.id, @@ -573,7 +573,7 @@ pub fn lower_struct_field(lctx: &mut LoweringContext, } } -pub fn lower_field(lctx: &mut LoweringContext, f: &Field) -> hir::Field { +fn lower_field(lctx: &mut LoweringContext, f: &Field) -> hir::Field { hir::Field { name: respan(f.ident.span, f.ident.node.name), expr: lower_expr(lctx, &f.expr), @@ -581,7 +581,7 @@ pub fn lower_field(lctx: &mut LoweringContext, f: &Field) -> hir::Field { } } -pub fn lower_mt(lctx: &mut LoweringContext, mt: &MutTy) -> hir::MutTy { +fn lower_mt(lctx: &mut LoweringContext, mt: &MutTy) -> hir::MutTy { hir::MutTy { ty: lower_ty(lctx, &mt.ty), mutbl: lower_mutability(lctx, mt.mutbl), @@ -592,7 +592,7 @@ fn lower_bounds(lctx: &mut LoweringContext, bounds: &TyParamBounds) -> hir::TyPa bounds.iter().map(|bound| lower_ty_param_bound(lctx, bound)).collect() } -pub fn lower_block(lctx: &mut LoweringContext, b: &Block) -> P { +fn lower_block(lctx: &mut LoweringContext, b: &Block) -> P { P(hir::Block { id: b.id, stmts: b.stmts.iter().map(|s| lower_stmt(lctx, s)).collect(), @@ -602,7 +602,7 @@ pub fn lower_block(lctx: &mut LoweringContext, b: &Block) -> P { }) } -pub fn lower_item_kind(lctx: &mut LoweringContext, i: &ItemKind) -> hir::Item_ { +fn lower_item_kind(lctx: &mut LoweringContext, i: &ItemKind) -> hir::Item_ { match *i { ItemKind::ExternCrate(string) => hir::ItemExternCrate(string), ItemKind::Use(ref view_path) => { @@ -670,7 +670,7 @@ pub fn lower_item_kind(lctx: &mut LoweringContext, i: &ItemKind) -> hir::Item_ { } } -pub fn lower_trait_item(lctx: &mut LoweringContext, i: &TraitItem) -> hir::TraitItem { +fn lower_trait_item(lctx: &mut LoweringContext, i: &TraitItem) -> hir::TraitItem { lctx.with_parent_def(i.id, |lctx| { hir::TraitItem { id: i.id, @@ -695,7 +695,7 @@ pub fn lower_trait_item(lctx: &mut LoweringContext, i: &TraitItem) -> hir::Trait }) } -pub fn lower_impl_item(lctx: &mut LoweringContext, i: &ImplItem) -> hir::ImplItem { +fn lower_impl_item(lctx: &mut LoweringContext, i: &ImplItem) -> hir::ImplItem { lctx.with_parent_def(i.id, |lctx| { hir::ImplItem { id: i.id, @@ -718,7 +718,7 @@ pub fn lower_impl_item(lctx: &mut LoweringContext, i: &ImplItem) -> hir::ImplIte }) } -pub fn lower_mod(lctx: &mut LoweringContext, m: &Mod) -> hir::Mod { +fn lower_mod(lctx: &mut LoweringContext, m: &Mod) -> hir::Mod { hir::Mod { inner: m.inner, item_ids: m.items.iter().map(|x| lower_item_id(lctx, x)).collect(), @@ -754,7 +754,7 @@ pub fn lower_crate(lctx: &mut LoweringContext, c: &Crate) -> hir::Crate { } } -pub fn lower_macro_def(lctx: &mut LoweringContext, m: &MacroDef) -> hir::MacroDef { +fn lower_macro_def(lctx: &mut LoweringContext, m: &MacroDef) -> hir::MacroDef { hir::MacroDef { name: m.ident.name, attrs: lower_attrs(lctx, &m.attrs), @@ -768,7 +768,7 @@ pub fn lower_macro_def(lctx: &mut LoweringContext, m: &MacroDef) -> hir::MacroDe } } -pub fn lower_item_id(_lctx: &mut LoweringContext, i: &Item) -> hir::ItemId { +fn lower_item_id(_lctx: &mut LoweringContext, i: &Item) -> hir::ItemId { hir::ItemId { id: i.id } } @@ -787,7 +787,7 @@ pub fn lower_item(lctx: &mut LoweringContext, i: &Item) -> hir::Item { } } -pub fn lower_foreign_item(lctx: &mut LoweringContext, i: &ForeignItem) -> hir::ForeignItem { +fn lower_foreign_item(lctx: &mut LoweringContext, i: &ForeignItem) -> hir::ForeignItem { lctx.with_parent_def(i.id, |lctx| { hir::ForeignItem { id: i.id, @@ -807,7 +807,7 @@ pub fn lower_foreign_item(lctx: &mut LoweringContext, i: &ForeignItem) -> hir::F }) } -pub fn lower_method_sig(lctx: &mut LoweringContext, sig: &MethodSig) -> hir::MethodSig { +fn lower_method_sig(lctx: &mut LoweringContext, sig: &MethodSig) -> hir::MethodSig { hir::MethodSig { generics: lower_generics(lctx, &sig.generics), abi: sig.abi, @@ -818,21 +818,21 @@ pub fn lower_method_sig(lctx: &mut LoweringContext, sig: &MethodSig) -> hir::Met } } -pub fn lower_unsafety(_lctx: &mut LoweringContext, u: Unsafety) -> hir::Unsafety { +fn lower_unsafety(_lctx: &mut LoweringContext, u: Unsafety) -> hir::Unsafety { match u { Unsafety::Unsafe => hir::Unsafety::Unsafe, Unsafety::Normal => hir::Unsafety::Normal, } } -pub fn lower_constness(_lctx: &mut LoweringContext, c: Constness) -> hir::Constness { +fn lower_constness(_lctx: &mut LoweringContext, c: Constness) -> hir::Constness { match c { Constness::Const => hir::Constness::Const, Constness::NotConst => hir::Constness::NotConst, } } -pub fn lower_unop(_lctx: &mut LoweringContext, u: UnOp) -> hir::UnOp { +fn lower_unop(_lctx: &mut LoweringContext, u: UnOp) -> hir::UnOp { match u { UnOp::Deref => hir::UnDeref, UnOp::Not => hir::UnNot, @@ -840,7 +840,7 @@ pub fn lower_unop(_lctx: &mut LoweringContext, u: UnOp) -> hir::UnOp { } } -pub fn lower_binop(_lctx: &mut LoweringContext, b: BinOp) -> hir::BinOp { +fn lower_binop(_lctx: &mut LoweringContext, b: BinOp) -> hir::BinOp { Spanned { node: match b.node { BinOpKind::Add => hir::BiAdd, @@ -866,7 +866,7 @@ pub fn lower_binop(_lctx: &mut LoweringContext, b: BinOp) -> hir::BinOp { } } -pub fn lower_pat(lctx: &mut LoweringContext, p: &Pat) -> P { +fn lower_pat(lctx: &mut LoweringContext, p: &Pat) -> P { P(hir::Pat { id: p.id, node: match p.node { @@ -931,7 +931,7 @@ pub fn lower_pat(lctx: &mut LoweringContext, p: &Pat) -> P { }) } -pub fn lower_expr(lctx: &mut LoweringContext, e: &Expr) -> P { +fn lower_expr(lctx: &mut LoweringContext, e: &Expr) -> P { P(hir::Expr { id: e.id, node: match e.node { @@ -1612,7 +1612,7 @@ pub fn lower_expr(lctx: &mut LoweringContext, e: &Expr) -> P { }) } -pub fn lower_stmt(lctx: &mut LoweringContext, s: &Stmt) -> hir::Stmt { +fn lower_stmt(lctx: &mut LoweringContext, s: &Stmt) -> hir::Stmt { match s.node { StmtKind::Decl(ref d, id) => { Spanned { @@ -1636,14 +1636,14 @@ pub fn lower_stmt(lctx: &mut LoweringContext, s: &Stmt) -> hir::Stmt { } } -pub fn lower_capture_clause(_lctx: &mut LoweringContext, c: CaptureBy) -> hir::CaptureClause { +fn lower_capture_clause(_lctx: &mut LoweringContext, c: CaptureBy) -> hir::CaptureClause { match c { CaptureBy::Value => hir::CaptureByValue, CaptureBy::Ref => hir::CaptureByRef, } } -pub fn lower_visibility(lctx: &mut LoweringContext, v: &Visibility) -> hir::Visibility { +fn lower_visibility(lctx: &mut LoweringContext, v: &Visibility) -> hir::Visibility { match *v { Visibility::Public => hir::Public, Visibility::Crate(_) => hir::Visibility::Crate, @@ -1653,44 +1653,44 @@ pub fn lower_visibility(lctx: &mut LoweringContext, v: &Visibility) -> hir::Visi } } -pub fn lower_defaultness(_lctx: &mut LoweringContext, d: Defaultness) -> hir::Defaultness { +fn lower_defaultness(_lctx: &mut LoweringContext, d: Defaultness) -> hir::Defaultness { match d { Defaultness::Default => hir::Defaultness::Default, Defaultness::Final => hir::Defaultness::Final, } } -pub fn lower_block_check_mode(lctx: &mut LoweringContext, b: &BlockCheckMode) -> hir::BlockCheckMode { +fn lower_block_check_mode(lctx: &mut LoweringContext, b: &BlockCheckMode) -> hir::BlockCheckMode { match *b { BlockCheckMode::Default => hir::DefaultBlock, BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(lower_unsafe_source(lctx, u)), } } -pub fn lower_binding_mode(lctx: &mut LoweringContext, b: &BindingMode) -> hir::BindingMode { +fn lower_binding_mode(lctx: &mut LoweringContext, b: &BindingMode) -> hir::BindingMode { match *b { BindingMode::ByRef(m) => hir::BindByRef(lower_mutability(lctx, m)), BindingMode::ByValue(m) => hir::BindByValue(lower_mutability(lctx, m)), } } -pub fn lower_unsafe_source(_lctx: &mut LoweringContext, u: UnsafeSource) -> hir::UnsafeSource { +fn lower_unsafe_source(_lctx: &mut LoweringContext, u: UnsafeSource) -> hir::UnsafeSource { match u { CompilerGenerated => hir::CompilerGenerated, UserProvided => hir::UserProvided, } } -pub fn lower_impl_polarity(_lctx: &mut LoweringContext, i: ImplPolarity) -> hir::ImplPolarity { +fn lower_impl_polarity(_lctx: &mut LoweringContext, i: ImplPolarity) -> hir::ImplPolarity { match i { ImplPolarity::Positive => hir::ImplPolarity::Positive, ImplPolarity::Negative => hir::ImplPolarity::Negative, } } -pub fn lower_trait_bound_modifier(_lctx: &mut LoweringContext, - f: TraitBoundModifier) - -> hir::TraitBoundModifier { +fn lower_trait_bound_modifier(_lctx: &mut LoweringContext, + f: TraitBoundModifier) + -> hir::TraitBoundModifier { match f { TraitBoundModifier::None => hir::TraitBoundModifier::None, TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe, From 0a380897a8273d6310604297cf97d8cf28eec798 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 May 2016 14:53:48 +1000 Subject: [PATCH 06/50] Copy more libraries from local Rust to stage0 When bootstrapping Rust using a previously built toolchain, I noticed a number of libraries were not copied in. As a result the copied in rustc fails to execute because it can't find all its dependences. Add them into the local_stage0.sh script. --- src/etc/local_stage0.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/etc/local_stage0.sh b/src/etc/local_stage0.sh index aee69a5c8bc58..fb455441910b8 100755 --- a/src/etc/local_stage0.sh +++ b/src/etc/local_stage0.sh @@ -55,6 +55,14 @@ cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}extra*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_D cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rust*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}std*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}syntax*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ +cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}flate*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ +cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}fmt_macros*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ +cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}getopts*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ +cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}graphviz*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ +cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}log*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ +cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rbml*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ +cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}serialize*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ +cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}term*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/ # do not fail if one of the above fails, as all we need is a working rustc! exit 0 From 946efcd4cae78640222d855c6c8aafafc0f844ef Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 10 May 2016 01:11:59 +0000 Subject: [PATCH 07/50] Refactor the `hir::lowering::lower_*` functions into methods of `LoweringContext` --- src/librustc/hir/lowering.rs | 2759 ++++++++++++++-------------- src/librustc_driver/driver.rs | 6 +- src/librustc_metadata/astencode.rs | 12 +- src/librustdoc/test.rs | 5 +- 4 files changed, 1383 insertions(+), 1399 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 40f6fddf10970..0f65c5c64e491 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -114,6 +114,35 @@ impl<'a> LoweringContext<'a> { } } + pub fn lower_crate(&mut self, c: &Crate) -> hir::Crate { + struct ItemLowerer<'lcx, 'interner: 'lcx> { + items: BTreeMap, + lctx: &'lcx mut LoweringContext<'interner>, + } + + impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> { + fn visit_item(&mut self, item: &'lcx Item) { + self.items.insert(item.id, self.lctx.lower_item(item)); + visit::walk_item(self, item); + } + } + + let items = { + let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), lctx: self }; + visit::walk_crate(&mut item_lowerer, c); + item_lowerer.items + }; + + hir::Crate { + module: self.lower_mod(&c.module), + attrs: self.lower_attrs(&c.attrs), + config: c.config.clone().into(), + span: c.span, + exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(), + items: items, + } + } + fn next_id(&self) -> NodeId { self.id_assigner.next_node_id() } @@ -136,1564 +165,1520 @@ impl<'a> LoweringContext<'a> { self.parent_def = old_def; result } -} -fn lower_ident(_lctx: &mut LoweringContext, ident: Ident) -> hir::Ident { - hir::Ident { - name: mtwt::resolve(ident), - unhygienic_name: ident.name, + fn lower_ident(&mut self, ident: Ident) -> hir::Ident { + hir::Ident { + name: mtwt::resolve(ident), + unhygienic_name: ident.name, + } } -} -fn lower_attrs(_lctx: &mut LoweringContext, attrs: &Vec) -> hir::HirVec { - attrs.clone().into() -} - -fn lower_view_path(lctx: &mut LoweringContext, view_path: &ViewPath) -> P { - P(Spanned { - node: match view_path.node { - ViewPathSimple(ident, ref path) => { - hir::ViewPathSimple(ident.name, lower_path(lctx, path)) - } - ViewPathGlob(ref path) => { - hir::ViewPathGlob(lower_path(lctx, path)) - } - ViewPathList(ref path, ref path_list_idents) => { - hir::ViewPathList(lower_path(lctx, path), - path_list_idents.iter() - .map(lower_path_list_item) - .collect()) - } - }, - span: view_path.span, - }) -} + fn lower_attrs(&mut self, attrs: &Vec) -> hir::HirVec { + attrs.clone().into() + } -fn lower_path_list_item(path_list_ident: &PathListItem) -> hir::PathListItem { - Spanned { - node: match path_list_ident.node { - PathListItemKind::Ident { id, name, rename } => hir::PathListIdent { - id: id, - name: name.name, - rename: rename.map(|x| x.name), - }, - PathListItemKind::Mod { id, rename } => hir::PathListMod { - id: id, - rename: rename.map(|x| x.name), + fn lower_view_path(&mut self, view_path: &ViewPath) -> P { + P(Spanned { + node: match view_path.node { + ViewPathSimple(ident, ref path) => { + hir::ViewPathSimple(ident.name, self.lower_path(path)) + } + ViewPathGlob(ref path) => { + hir::ViewPathGlob(self.lower_path(path)) + } + ViewPathList(ref path, ref path_list_idents) => { + hir::ViewPathList(self.lower_path(path), + path_list_idents.iter() + .map(|item| self.lower_path_list_item(item)) + .collect()) + } }, - }, - span: path_list_ident.span, + span: view_path.span, + }) } -} -fn lower_arm(lctx: &mut LoweringContext, arm: &Arm) -> hir::Arm { - hir::Arm { - attrs: lower_attrs(lctx, &arm.attrs), - pats: arm.pats.iter().map(|x| lower_pat(lctx, x)).collect(), - guard: arm.guard.as_ref().map(|ref x| lower_expr(lctx, x)), - body: lower_expr(lctx, &arm.body), + fn lower_path_list_item(&mut self, path_list_ident: &PathListItem) -> hir::PathListItem { + Spanned { + node: match path_list_ident.node { + PathListItemKind::Ident { id, name, rename } => hir::PathListIdent { + id: id, + name: name.name, + rename: rename.map(|x| x.name), + }, + PathListItemKind::Mod { id, rename } => hir::PathListMod { + id: id, + rename: rename.map(|x| x.name), + }, + }, + span: path_list_ident.span, + } } -} -fn lower_decl(lctx: &mut LoweringContext, d: &Decl) -> P { - match d.node { - DeclKind::Local(ref l) => P(Spanned { - node: hir::DeclLocal(lower_local(lctx, l)), - span: d.span, - }), - DeclKind::Item(ref it) => P(Spanned { - node: hir::DeclItem(lower_item_id(lctx, it)), - span: d.span, - }), + fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { + hir::Arm { + attrs: self.lower_attrs(&arm.attrs), + pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(), + guard: arm.guard.as_ref().map(|ref x| self.lower_expr(x)), + body: self.lower_expr(&arm.body), + } } -} -fn lower_ty_binding(lctx: &mut LoweringContext, b: &TypeBinding) -> hir::TypeBinding { - hir::TypeBinding { - id: b.id, - name: b.ident.name, - ty: lower_ty(lctx, &b.ty), - span: b.span, + fn lower_decl(&mut self, d: &Decl) -> P { + match d.node { + DeclKind::Local(ref l) => P(Spanned { + node: hir::DeclLocal(self.lower_local(l)), + span: d.span, + }), + DeclKind::Item(ref it) => P(Spanned { + node: hir::DeclItem(self.lower_item_id(it)), + span: d.span, + }), + } } -} - -fn lower_ty(lctx: &mut LoweringContext, t: &Ty) -> P { - use syntax::ast::TyKind::*; - P(hir::Ty { - id: t.id, - node: match t.node { - Infer => hir::TyInfer, - Vec(ref ty) => hir::TyVec(lower_ty(lctx, ty)), - Ptr(ref mt) => hir::TyPtr(lower_mt(lctx, mt)), - Rptr(ref region, ref mt) => { - hir::TyRptr(lower_opt_lifetime(lctx, region), lower_mt(lctx, mt)) - } - BareFn(ref f) => { - hir::TyBareFn(P(hir::BareFnTy { - lifetimes: lower_lifetime_defs(lctx, &f.lifetimes), - unsafety: lower_unsafety(lctx, f.unsafety), - abi: f.abi, - decl: lower_fn_decl(lctx, &f.decl), - })) - } - Tup(ref tys) => hir::TyTup(tys.iter().map(|ty| lower_ty(lctx, ty)).collect()), - Paren(ref ty) => { - return lower_ty(lctx, ty); - } - Path(ref qself, ref path) => { - let qself = qself.as_ref().map(|&QSelf { ref ty, position }| { - hir::QSelf { - ty: lower_ty(lctx, ty), - position: position, - } - }); - hir::TyPath(qself, lower_path(lctx, path)) - } - ObjectSum(ref ty, ref bounds) => { - hir::TyObjectSum(lower_ty(lctx, ty), lower_bounds(lctx, bounds)) - } - FixedLengthVec(ref ty, ref e) => { - hir::TyFixedLengthVec(lower_ty(lctx, ty), lower_expr(lctx, e)) - } - Typeof(ref expr) => { - hir::TyTypeof(lower_expr(lctx, expr)) - } - PolyTraitRef(ref bounds) => { - hir::TyPolyTraitRef(bounds.iter().map(|b| lower_ty_param_bound(lctx, b)).collect()) - } - Mac(_) => panic!("TyMac should have been expanded by now."), - }, - span: t.span, - }) -} -fn lower_foreign_mod(lctx: &mut LoweringContext, fm: &ForeignMod) -> hir::ForeignMod { - hir::ForeignMod { - abi: fm.abi, - items: fm.items.iter().map(|x| lower_foreign_item(lctx, x)).collect(), + fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding { + hir::TypeBinding { + id: b.id, + name: b.ident.name, + ty: self.lower_ty(&b.ty), + span: b.span, + } } -} -fn lower_variant(lctx: &mut LoweringContext, v: &Variant) -> hir::Variant { - Spanned { - node: hir::Variant_ { - name: v.node.name.name, - attrs: lower_attrs(lctx, &v.node.attrs), - data: lower_variant_data(lctx, &v.node.data), - disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(lctx, e)), - }, - span: v.span, + fn lower_ty(&mut self, t: &Ty) -> P { + use syntax::ast::TyKind::*; + P(hir::Ty { + id: t.id, + node: match t.node { + Infer => hir::TyInfer, + Vec(ref ty) => hir::TyVec(self.lower_ty(ty)), + Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)), + Rptr(ref region, ref mt) => { + hir::TyRptr(self.lower_opt_lifetime(region), self.lower_mt(mt)) + } + BareFn(ref f) => { + hir::TyBareFn(P(hir::BareFnTy { + lifetimes: self.lower_lifetime_defs(&f.lifetimes), + unsafety: self.lower_unsafety(f.unsafety), + abi: f.abi, + decl: self.lower_fn_decl(&f.decl), + })) + } + Tup(ref tys) => hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect()), + Paren(ref ty) => { + return self.lower_ty(ty); + } + Path(ref qself, ref path) => { + let qself = qself.as_ref().map(|&QSelf { ref ty, position }| { + hir::QSelf { + ty: self.lower_ty(ty), + position: position, + } + }); + hir::TyPath(qself, self.lower_path(path)) + } + ObjectSum(ref ty, ref bounds) => { + hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds)) + } + FixedLengthVec(ref ty, ref e) => { + hir::TyFixedLengthVec(self.lower_ty(ty), self.lower_expr(e)) + } + Typeof(ref expr) => { + hir::TyTypeof(self.lower_expr(expr)) + } + PolyTraitRef(ref bounds) => { + let bounds = bounds.iter().map(|b| self.lower_ty_param_bound(b)).collect(); + hir::TyPolyTraitRef(bounds) + } + Mac(_) => panic!("TyMac should have been expanded by now."), + }, + span: t.span, + }) } -} -// Path segments are usually unhygienic, hygienic path segments can occur only in -// identifier-like paths originating from `ExprPath`. -// Make life simpler for rustc_resolve by renaming only such segments. -fn lower_path_full(lctx: &mut LoweringContext, p: &Path, maybe_hygienic: bool) -> hir::Path { - let maybe_hygienic = maybe_hygienic && !p.global && p.segments.len() == 1; - hir::Path { - global: p.global, - segments: p.segments - .iter() - .map(|&PathSegment { identifier, ref parameters }| { - hir::PathSegment { - identifier: if maybe_hygienic { - lower_ident(lctx, identifier) - } else { - hir::Ident::from_name(identifier.name) - }, - parameters: lower_path_parameters(lctx, parameters), - } - }) - .collect(), - span: p.span, + fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod { + hir::ForeignMod { + abi: fm.abi, + items: fm.items.iter().map(|x| self.lower_foreign_item(x)).collect(), + } } -} -fn lower_path(lctx: &mut LoweringContext, p: &Path) -> hir::Path { - lower_path_full(lctx, p, false) -} - -fn lower_path_parameters(lctx: &mut LoweringContext, - path_parameters: &PathParameters) - -> hir::PathParameters { - match *path_parameters { - PathParameters::AngleBracketed(ref data) => - hir::AngleBracketedParameters(lower_angle_bracketed_parameter_data(lctx, data)), - PathParameters::Parenthesized(ref data) => - hir::ParenthesizedParameters(lower_parenthesized_parameter_data(lctx, data)), + fn lower_variant(&mut self, v: &Variant) -> hir::Variant { + Spanned { + node: hir::Variant_ { + name: v.node.name.name, + attrs: self.lower_attrs(&v.node.attrs), + data: self.lower_variant_data(&v.node.data), + disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_expr(e)), + }, + span: v.span, + } } -} -fn lower_angle_bracketed_parameter_data(lctx: &mut LoweringContext, - data: &AngleBracketedParameterData) - -> hir::AngleBracketedParameterData { - let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data; - hir::AngleBracketedParameterData { - lifetimes: lower_lifetimes(lctx, lifetimes), - types: types.iter().map(|ty| lower_ty(lctx, ty)).collect(), - bindings: bindings.iter().map(|b| lower_ty_binding(lctx, b)).collect(), + // Path segments are usually unhygienic, hygienic path segments can occur only in + // identifier-like paths originating from `ExprPath`. + // Make life simpler for rustc_resolve by renaming only such segments. + fn lower_path_full(&mut self, p: &Path, maybe_hygienic: bool) -> hir::Path { + let maybe_hygienic = maybe_hygienic && !p.global && p.segments.len() == 1; + hir::Path { + global: p.global, + segments: p.segments + .iter() + .map(|&PathSegment { identifier, ref parameters }| { + hir::PathSegment { + identifier: if maybe_hygienic { + self.lower_ident(identifier) + } else { + hir::Ident::from_name(identifier.name) + }, + parameters: self.lower_path_parameters(parameters), + } + }) + .collect(), + span: p.span, + } } -} -fn lower_parenthesized_parameter_data(lctx: &mut LoweringContext, - data: &ParenthesizedParameterData) - -> hir::ParenthesizedParameterData { - let &ParenthesizedParameterData { ref inputs, ref output, span } = data; - hir::ParenthesizedParameterData { - inputs: inputs.iter().map(|ty| lower_ty(lctx, ty)).collect(), - output: output.as_ref().map(|ty| lower_ty(lctx, ty)), - span: span, + fn lower_path(&mut self, p: &Path) -> hir::Path { + self.lower_path_full(p, false) } -} -fn lower_local(lctx: &mut LoweringContext, l: &Local) -> P { - P(hir::Local { - id: l.id, - ty: l.ty.as_ref().map(|t| lower_ty(lctx, t)), - pat: lower_pat(lctx, &l.pat), - init: l.init.as_ref().map(|e| lower_expr(lctx, e)), - span: l.span, - attrs: l.attrs.clone(), - }) -} - -fn lower_explicit_self_underscore(lctx: &mut LoweringContext, - es: &SelfKind) - -> hir::ExplicitSelf_ { - match *es { - SelfKind::Static => hir::SelfStatic, - SelfKind::Value(v) => hir::SelfValue(v.name), - SelfKind::Region(ref lifetime, m, ident) => { - hir::SelfRegion(lower_opt_lifetime(lctx, lifetime), - lower_mutability(lctx, m), - ident.name) - } - SelfKind::Explicit(ref typ, ident) => { - hir::SelfExplicit(lower_ty(lctx, typ), ident.name) + fn lower_path_parameters(&mut self, path_parameters: &PathParameters) -> hir::PathParameters { + match *path_parameters { + PathParameters::AngleBracketed(ref data) => + hir::AngleBracketedParameters(self.lower_angle_bracketed_parameter_data(data)), + PathParameters::Parenthesized(ref data) => + hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)), } } -} -fn lower_mutability(_lctx: &mut LoweringContext, m: Mutability) -> hir::Mutability { - match m { - Mutability::Mutable => hir::MutMutable, - Mutability::Immutable => hir::MutImmutable, + fn lower_angle_bracketed_parameter_data(&mut self, + data: &AngleBracketedParameterData) + -> hir::AngleBracketedParameterData { + let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data; + hir::AngleBracketedParameterData { + lifetimes: self.lower_lifetimes(lifetimes), + types: types.iter().map(|ty| self.lower_ty(ty)).collect(), + bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(), + } } -} -fn lower_explicit_self(lctx: &mut LoweringContext, s: &ExplicitSelf) -> hir::ExplicitSelf { - Spanned { - node: lower_explicit_self_underscore(lctx, &s.node), - span: s.span, + fn lower_parenthesized_parameter_data(&mut self, + data: &ParenthesizedParameterData) + -> hir::ParenthesizedParameterData { + let &ParenthesizedParameterData { ref inputs, ref output, span } = data; + hir::ParenthesizedParameterData { + inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(), + output: output.as_ref().map(|ty| self.lower_ty(ty)), + span: span, + } } -} -fn lower_arg(lctx: &mut LoweringContext, arg: &Arg) -> hir::Arg { - hir::Arg { - id: arg.id, - pat: lower_pat(lctx, &arg.pat), - ty: lower_ty(lctx, &arg.ty), + fn lower_local(&mut self, l: &Local) -> P { + P(hir::Local { + id: l.id, + ty: l.ty.as_ref().map(|t| self.lower_ty(t)), + pat: self.lower_pat(&l.pat), + init: l.init.as_ref().map(|e| self.lower_expr(e)), + span: l.span, + attrs: l.attrs.clone(), + }) } -} - -fn lower_fn_decl(lctx: &mut LoweringContext, decl: &FnDecl) -> P { - P(hir::FnDecl { - inputs: decl.inputs.iter().map(|x| lower_arg(lctx, x)).collect(), - output: match decl.output { - FunctionRetTy::Ty(ref ty) => hir::Return(lower_ty(lctx, ty)), - FunctionRetTy::Default(span) => hir::DefaultReturn(span), - FunctionRetTy::None(span) => hir::NoReturn(span), - }, - variadic: decl.variadic, - }) -} -fn lower_ty_param_bound(lctx: &mut LoweringContext, tpb: &TyParamBound) -> hir::TyParamBound { - match *tpb { - TraitTyParamBound(ref ty, modifier) => { - hir::TraitTyParamBound(lower_poly_trait_ref(lctx, ty), - lower_trait_bound_modifier(lctx, modifier)) - } - RegionTyParamBound(ref lifetime) => { - hir::RegionTyParamBound(lower_lifetime(lctx, lifetime)) + fn lower_explicit_self_underscore(&mut self, es: &SelfKind) -> hir::ExplicitSelf_ { + match *es { + SelfKind::Static => hir::SelfStatic, + SelfKind::Value(v) => hir::SelfValue(v.name), + SelfKind::Region(ref lifetime, m, ident) => { + hir::SelfRegion(self.lower_opt_lifetime(lifetime), + self.lower_mutability(m), + ident.name) + } + SelfKind::Explicit(ref typ, ident) => { + hir::SelfExplicit(self.lower_ty(typ), ident.name) + } } } -} -fn lower_ty_param(lctx: &mut LoweringContext, tp: &TyParam) -> hir::TyParam { - hir::TyParam { - id: tp.id, - name: tp.ident.name, - bounds: lower_bounds(lctx, &tp.bounds), - default: tp.default.as_ref().map(|x| lower_ty(lctx, x)), - span: tp.span, + fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability { + match m { + Mutability::Mutable => hir::MutMutable, + Mutability::Immutable => hir::MutImmutable, + } } -} - -fn lower_ty_params(lctx: &mut LoweringContext, - tps: &P<[TyParam]>) - -> hir::HirVec { - tps.iter().map(|tp| lower_ty_param(lctx, tp)).collect() -} -fn lower_lifetime(_lctx: &mut LoweringContext, l: &Lifetime) -> hir::Lifetime { - hir::Lifetime { - id: l.id, - name: l.name, - span: l.span, + fn lower_explicit_self(&mut self, s: &ExplicitSelf) -> hir::ExplicitSelf { + Spanned { + node: self.lower_explicit_self_underscore(&s.node), + span: s.span, + } } -} -fn lower_lifetime_def(lctx: &mut LoweringContext, l: &LifetimeDef) -> hir::LifetimeDef { - hir::LifetimeDef { - lifetime: lower_lifetime(lctx, &l.lifetime), - bounds: lower_lifetimes(lctx, &l.bounds), + fn lower_arg(&mut self, arg: &Arg) -> hir::Arg { + hir::Arg { + id: arg.id, + pat: self.lower_pat(&arg.pat), + ty: self.lower_ty(&arg.ty), + } } -} - -fn lower_lifetimes(lctx: &mut LoweringContext, lts: &Vec) - -> hir::HirVec { - lts.iter().map(|l| lower_lifetime(lctx, l)).collect() -} -fn lower_lifetime_defs(lctx: &mut LoweringContext, - lts: &Vec) - -> hir::HirVec { - lts.iter().map(|l| lower_lifetime_def(lctx, l)).collect() -} + fn lower_fn_decl(&mut self, decl: &FnDecl) -> P { + P(hir::FnDecl { + inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(), + output: match decl.output { + FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)), + FunctionRetTy::Default(span) => hir::DefaultReturn(span), + FunctionRetTy::None(span) => hir::NoReturn(span), + }, + variadic: decl.variadic, + }) + } -fn lower_opt_lifetime(lctx: &mut LoweringContext, - o_lt: &Option) - -> Option { - o_lt.as_ref().map(|lt| lower_lifetime(lctx, lt)) -} + fn lower_ty_param_bound(&mut self, tpb: &TyParamBound) -> hir::TyParamBound { + match *tpb { + TraitTyParamBound(ref ty, modifier) => { + hir::TraitTyParamBound(self.lower_poly_trait_ref(ty), + self.lower_trait_bound_modifier(modifier)) + } + RegionTyParamBound(ref lifetime) => { + hir::RegionTyParamBound(self.lower_lifetime(lifetime)) + } + } + } -fn lower_generics(lctx: &mut LoweringContext, g: &Generics) -> hir::Generics { - hir::Generics { - ty_params: lower_ty_params(lctx, &g.ty_params), - lifetimes: lower_lifetime_defs(lctx, &g.lifetimes), - where_clause: lower_where_clause(lctx, &g.where_clause), + fn lower_ty_param(&mut self, tp: &TyParam) -> hir::TyParam { + hir::TyParam { + id: tp.id, + name: tp.ident.name, + bounds: self.lower_bounds(&tp.bounds), + default: tp.default.as_ref().map(|x| self.lower_ty(x)), + span: tp.span, + } } -} -fn lower_where_clause(lctx: &mut LoweringContext, wc: &WhereClause) -> hir::WhereClause { - hir::WhereClause { - id: wc.id, - predicates: wc.predicates - .iter() - .map(|predicate| lower_where_predicate(lctx, predicate)) - .collect(), + fn lower_ty_params(&mut self, tps: &P<[TyParam]>) -> hir::HirVec { + tps.iter().map(|tp| self.lower_ty_param(tp)).collect() } -} -fn lower_where_predicate(lctx: &mut LoweringContext, - pred: &WherePredicate) - -> hir::WherePredicate { - match *pred { - WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes, - ref bounded_ty, - ref bounds, - span}) => { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_lifetimes: lower_lifetime_defs(lctx, bound_lifetimes), - bounded_ty: lower_ty(lctx, bounded_ty), - bounds: bounds.iter().map(|x| lower_ty_param_bound(lctx, x)).collect(), - span: span, - }) - } - WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime, - ref bounds, - span}) => { - hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - span: span, - lifetime: lower_lifetime(lctx, lifetime), - bounds: bounds.iter().map(|bound| lower_lifetime(lctx, bound)).collect(), - }) - } - WherePredicate::EqPredicate(WhereEqPredicate{ id, - ref path, - ref ty, - span}) => { - hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - id: id, - path: lower_path(lctx, path), - ty: lower_ty(lctx, ty), - span: span, - }) + fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { + hir::Lifetime { + id: l.id, + name: l.name, + span: l.span, } } -} -fn lower_variant_data(lctx: &mut LoweringContext, vdata: &VariantData) -> hir::VariantData { - match *vdata { - VariantData::Struct(ref fields, id) => { - hir::VariantData::Struct(fields.iter() - .enumerate() - .map(|f| lower_struct_field(lctx, f)) - .collect(), - id) + fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef { + hir::LifetimeDef { + lifetime: self.lower_lifetime(&l.lifetime), + bounds: self.lower_lifetimes(&l.bounds), } - VariantData::Tuple(ref fields, id) => { - hir::VariantData::Tuple(fields.iter() - .enumerate() - .map(|f| lower_struct_field(lctx, f)) - .collect(), - id) - } - VariantData::Unit(id) => hir::VariantData::Unit(id), } -} -fn lower_trait_ref(lctx: &mut LoweringContext, p: &TraitRef) -> hir::TraitRef { - hir::TraitRef { - path: lower_path(lctx, &p.path), - ref_id: p.ref_id, + fn lower_lifetimes(&mut self, lts: &Vec) -> hir::HirVec { + lts.iter().map(|l| self.lower_lifetime(l)).collect() } -} -fn lower_poly_trait_ref(lctx: &mut LoweringContext, p: &PolyTraitRef) -> hir::PolyTraitRef { - hir::PolyTraitRef { - bound_lifetimes: lower_lifetime_defs(lctx, &p.bound_lifetimes), - trait_ref: lower_trait_ref(lctx, &p.trait_ref), - span: p.span, + fn lower_lifetime_defs(&mut self, lts: &Vec) -> hir::HirVec { + lts.iter().map(|l| self.lower_lifetime_def(l)).collect() } -} -fn lower_struct_field(lctx: &mut LoweringContext, - (index, f): (usize, &StructField)) - -> hir::StructField { - hir::StructField { - span: f.span, - id: f.id, - name: f.ident.map(|ident| ident.name).unwrap_or(token::intern(&index.to_string())), - vis: lower_visibility(lctx, &f.vis), - ty: lower_ty(lctx, &f.ty), - attrs: lower_attrs(lctx, &f.attrs), + fn lower_opt_lifetime(&mut self, o_lt: &Option) -> Option { + o_lt.as_ref().map(|lt| self.lower_lifetime(lt)) } -} -fn lower_field(lctx: &mut LoweringContext, f: &Field) -> hir::Field { - hir::Field { - name: respan(f.ident.span, f.ident.node.name), - expr: lower_expr(lctx, &f.expr), - span: f.span, + fn lower_generics(&mut self, g: &Generics) -> hir::Generics { + hir::Generics { + ty_params: self.lower_ty_params(&g.ty_params), + lifetimes: self.lower_lifetime_defs(&g.lifetimes), + where_clause: self.lower_where_clause(&g.where_clause), + } } -} -fn lower_mt(lctx: &mut LoweringContext, mt: &MutTy) -> hir::MutTy { - hir::MutTy { - ty: lower_ty(lctx, &mt.ty), - mutbl: lower_mutability(lctx, mt.mutbl), + fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause { + hir::WhereClause { + id: wc.id, + predicates: wc.predicates + .iter() + .map(|predicate| self.lower_where_predicate(predicate)) + .collect(), + } } -} - -fn lower_bounds(lctx: &mut LoweringContext, bounds: &TyParamBounds) -> hir::TyParamBounds { - bounds.iter().map(|bound| lower_ty_param_bound(lctx, bound)).collect() -} - -fn lower_block(lctx: &mut LoweringContext, b: &Block) -> P { - P(hir::Block { - id: b.id, - stmts: b.stmts.iter().map(|s| lower_stmt(lctx, s)).collect(), - expr: b.expr.as_ref().map(|ref x| lower_expr(lctx, x)), - rules: lower_block_check_mode(lctx, &b.rules), - span: b.span, - }) -} -fn lower_item_kind(lctx: &mut LoweringContext, i: &ItemKind) -> hir::Item_ { - match *i { - ItemKind::ExternCrate(string) => hir::ItemExternCrate(string), - ItemKind::Use(ref view_path) => { - hir::ItemUse(lower_view_path(lctx, view_path)) - } - ItemKind::Static(ref t, m, ref e) => { - hir::ItemStatic(lower_ty(lctx, t), - lower_mutability(lctx, m), - lower_expr(lctx, e)) - } - ItemKind::Const(ref t, ref e) => { - hir::ItemConst(lower_ty(lctx, t), lower_expr(lctx, e)) - } - ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { - hir::ItemFn(lower_fn_decl(lctx, decl), - lower_unsafety(lctx, unsafety), - lower_constness(lctx, constness), - abi, - lower_generics(lctx, generics), - lower_block(lctx, body)) - } - ItemKind::Mod(ref m) => hir::ItemMod(lower_mod(lctx, m)), - ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(lower_foreign_mod(lctx, nm)), - ItemKind::Ty(ref t, ref generics) => { - hir::ItemTy(lower_ty(lctx, t), lower_generics(lctx, generics)) - } - ItemKind::Enum(ref enum_definition, ref generics) => { - hir::ItemEnum(hir::EnumDef { - variants: enum_definition.variants - .iter() - .map(|x| lower_variant(lctx, x)) - .collect(), - }, - lower_generics(lctx, generics)) - } - ItemKind::Struct(ref struct_def, ref generics) => { - let struct_def = lower_variant_data(lctx, struct_def); - hir::ItemStruct(struct_def, lower_generics(lctx, generics)) + fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate { + match *pred { + WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes, + ref bounded_ty, + ref bounds, + span}) => { + hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + bound_lifetimes: self.lower_lifetime_defs(bound_lifetimes), + bounded_ty: self.lower_ty(bounded_ty), + bounds: bounds.iter().map(|x| self.lower_ty_param_bound(x)).collect(), + span: span, + }) + } + WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime, + ref bounds, + span}) => { + hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { + span: span, + lifetime: self.lower_lifetime(lifetime), + bounds: bounds.iter().map(|bound| self.lower_lifetime(bound)).collect(), + }) + } + WherePredicate::EqPredicate(WhereEqPredicate{ id, + ref path, + ref ty, + span}) => { + hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { + id: id, + path: self.lower_path(path), + ty: self.lower_ty(ty), + span: span, + }) + } } - ItemKind::DefaultImpl(unsafety, ref trait_ref) => { - hir::ItemDefaultImpl(lower_unsafety(lctx, unsafety), - lower_trait_ref(lctx, trait_ref)) + } + + fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData { + match *vdata { + VariantData::Struct(ref fields, id) => { + hir::VariantData::Struct(fields.iter() + .enumerate() + .map(|f| self.lower_struct_field(f)) + .collect(), + id) + } + VariantData::Tuple(ref fields, id) => { + hir::VariantData::Tuple(fields.iter() + .enumerate() + .map(|f| self.lower_struct_field(f)) + .collect(), + id) + } + VariantData::Unit(id) => hir::VariantData::Unit(id), } - ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => { - let new_impl_items = impl_items.iter() - .map(|item| lower_impl_item(lctx, item)) - .collect(); - let ifce = ifce.as_ref().map(|trait_ref| lower_trait_ref(lctx, trait_ref)); - hir::ItemImpl(lower_unsafety(lctx, unsafety), - lower_impl_polarity(lctx, polarity), - lower_generics(lctx, generics), - ifce, - lower_ty(lctx, ty), - new_impl_items) + } + + fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef { + hir::TraitRef { + path: self.lower_path(&p.path), + ref_id: p.ref_id, } - ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => { - let bounds = lower_bounds(lctx, bounds); - let items = items.iter().map(|item| lower_trait_item(lctx, item)).collect(); - hir::ItemTrait(lower_unsafety(lctx, unsafety), - lower_generics(lctx, generics), - bounds, - items) + } + + fn lower_poly_trait_ref(&mut self, p: &PolyTraitRef) -> hir::PolyTraitRef { + hir::PolyTraitRef { + bound_lifetimes: self.lower_lifetime_defs(&p.bound_lifetimes), + trait_ref: self.lower_trait_ref(&p.trait_ref), + span: p.span, } - ItemKind::Mac(_) => panic!("Shouldn't still be around"), } -} -fn lower_trait_item(lctx: &mut LoweringContext, i: &TraitItem) -> hir::TraitItem { - lctx.with_parent_def(i.id, |lctx| { - hir::TraitItem { - id: i.id, - name: i.ident.name, - attrs: lower_attrs(lctx, &i.attrs), - node: match i.node { - TraitItemKind::Const(ref ty, ref default) => { - hir::ConstTraitItem(lower_ty(lctx, ty), - default.as_ref().map(|x| lower_expr(lctx, x))) - } - TraitItemKind::Method(ref sig, ref body) => { - hir::MethodTraitItem(lower_method_sig(lctx, sig), - body.as_ref().map(|x| lower_block(lctx, x))) - } - TraitItemKind::Type(ref bounds, ref default) => { - hir::TypeTraitItem(lower_bounds(lctx, bounds), - default.as_ref().map(|x| lower_ty(lctx, x))) - } - }, - span: i.span, + fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField { + hir::StructField { + span: f.span, + id: f.id, + name: f.ident.map(|ident| ident.name).unwrap_or(token::intern(&index.to_string())), + vis: self.lower_visibility(&f.vis), + ty: self.lower_ty(&f.ty), + attrs: self.lower_attrs(&f.attrs), } - }) -} + } -fn lower_impl_item(lctx: &mut LoweringContext, i: &ImplItem) -> hir::ImplItem { - lctx.with_parent_def(i.id, |lctx| { - hir::ImplItem { - id: i.id, - name: i.ident.name, - attrs: lower_attrs(lctx, &i.attrs), - vis: lower_visibility(lctx, &i.vis), - defaultness: lower_defaultness(lctx, i.defaultness), - node: match i.node { - ImplItemKind::Const(ref ty, ref expr) => { - hir::ImplItemKind::Const(lower_ty(lctx, ty), lower_expr(lctx, expr)) - } - ImplItemKind::Method(ref sig, ref body) => { - hir::ImplItemKind::Method(lower_method_sig(lctx, sig), lower_block(lctx, body)) - } - ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(lower_ty(lctx, ty)), - ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), - }, - span: i.span, + fn lower_field(&mut self, f: &Field) -> hir::Field { + hir::Field { + name: respan(f.ident.span, f.ident.node.name), + expr: self.lower_expr(&f.expr), + span: f.span, } - }) -} + } -fn lower_mod(lctx: &mut LoweringContext, m: &Mod) -> hir::Mod { - hir::Mod { - inner: m.inner, - item_ids: m.items.iter().map(|x| lower_item_id(lctx, x)).collect(), + fn lower_mt(&mut self, mt: &MutTy) -> hir::MutTy { + hir::MutTy { + ty: self.lower_ty(&mt.ty), + mutbl: self.lower_mutability(mt.mutbl), + } } -} -struct ItemLowerer<'lcx, 'interner: 'lcx> { - items: BTreeMap, - lctx: &'lcx mut LoweringContext<'interner>, -} + fn lower_bounds(&mut self, bounds: &TyParamBounds) -> hir::TyParamBounds { + bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect() + } -impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> { - fn visit_item(&mut self, item: &'lcx Item) { - self.items.insert(item.id, lower_item(self.lctx, item)); - visit::walk_item(self, item); + fn lower_block(&mut self, b: &Block) -> P { + P(hir::Block { + id: b.id, + stmts: b.stmts.iter().map(|s| self.lower_stmt(s)).collect(), + expr: b.expr.as_ref().map(|ref x| self.lower_expr(x)), + rules: self.lower_block_check_mode(&b.rules), + span: b.span, + }) } -} -pub fn lower_crate(lctx: &mut LoweringContext, c: &Crate) -> hir::Crate { - let items = { - let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), lctx: lctx }; - visit::walk_crate(&mut item_lowerer, c); - item_lowerer.items - }; + fn lower_item_kind(&mut self, i: &ItemKind) -> hir::Item_ { + match *i { + ItemKind::ExternCrate(string) => hir::ItemExternCrate(string), + ItemKind::Use(ref view_path) => { + hir::ItemUse(self.lower_view_path(view_path)) + } + ItemKind::Static(ref t, m, ref e) => { + hir::ItemStatic(self.lower_ty(t), + self.lower_mutability(m), + self.lower_expr(e)) + } + ItemKind::Const(ref t, ref e) => { + hir::ItemConst(self.lower_ty(t), self.lower_expr(e)) + } + ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { + hir::ItemFn(self.lower_fn_decl(decl), + self.lower_unsafety(unsafety), + self.lower_constness(constness), + abi, + self.lower_generics(generics), + self.lower_block(body)) + } + ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)), + ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)), + ItemKind::Ty(ref t, ref generics) => { + hir::ItemTy(self.lower_ty(t), self.lower_generics(generics)) + } + ItemKind::Enum(ref enum_definition, ref generics) => { + hir::ItemEnum(hir::EnumDef { + variants: enum_definition.variants + .iter() + .map(|x| self.lower_variant(x)) + .collect(), + }, + self.lower_generics(generics)) + } + ItemKind::Struct(ref struct_def, ref generics) => { + let struct_def = self.lower_variant_data(struct_def); + hir::ItemStruct(struct_def, self.lower_generics(generics)) + } + ItemKind::DefaultImpl(unsafety, ref trait_ref) => { + hir::ItemDefaultImpl(self.lower_unsafety(unsafety), + self.lower_trait_ref(trait_ref)) + } + ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => { + let new_impl_items = impl_items.iter() + .map(|item| self.lower_impl_item(item)) + .collect(); + let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref)); + hir::ItemImpl(self.lower_unsafety(unsafety), + self.lower_impl_polarity(polarity), + self.lower_generics(generics), + ifce, + self.lower_ty(ty), + new_impl_items) + } + ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => { + let bounds = self.lower_bounds(bounds); + let items = items.iter().map(|item| self.lower_trait_item(item)).collect(); + hir::ItemTrait(self.lower_unsafety(unsafety), + self.lower_generics(generics), + bounds, + items) + } + ItemKind::Mac(_) => panic!("Shouldn't still be around"), + } + } - hir::Crate { - module: lower_mod(lctx, &c.module), - attrs: lower_attrs(lctx, &c.attrs), - config: c.config.clone().into(), - span: c.span, - exported_macros: c.exported_macros.iter().map(|m| lower_macro_def(lctx, m)).collect(), - items: items, + fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem { + self.with_parent_def(i.id, |this| { + hir::TraitItem { + id: i.id, + name: i.ident.name, + attrs: this.lower_attrs(&i.attrs), + node: match i.node { + TraitItemKind::Const(ref ty, ref default) => { + hir::ConstTraitItem(this.lower_ty(ty), + default.as_ref().map(|x| this.lower_expr(x))) + } + TraitItemKind::Method(ref sig, ref body) => { + hir::MethodTraitItem(this.lower_method_sig(sig), + body.as_ref().map(|x| this.lower_block(x))) + } + TraitItemKind::Type(ref bounds, ref default) => { + hir::TypeTraitItem(this.lower_bounds(bounds), + default.as_ref().map(|x| this.lower_ty(x))) + } + }, + span: i.span, + } + }) } -} -fn lower_macro_def(lctx: &mut LoweringContext, m: &MacroDef) -> hir::MacroDef { - hir::MacroDef { - name: m.ident.name, - attrs: lower_attrs(lctx, &m.attrs), - id: m.id, - span: m.span, - imported_from: m.imported_from.map(|x| x.name), - export: m.export, - use_locally: m.use_locally, - allow_internal_unstable: m.allow_internal_unstable, - body: m.body.clone().into(), + fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { + self.with_parent_def(i.id, |this| { + hir::ImplItem { + id: i.id, + name: i.ident.name, + attrs: this.lower_attrs(&i.attrs), + vis: this.lower_visibility(&i.vis), + defaultness: this.lower_defaultness(i.defaultness), + node: match i.node { + ImplItemKind::Const(ref ty, ref expr) => { + hir::ImplItemKind::Const(this.lower_ty(ty), this.lower_expr(expr)) + } + ImplItemKind::Method(ref sig, ref body) => { + hir::ImplItemKind::Method(this.lower_method_sig(sig), + this.lower_block(body)) + } + ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), + ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), + }, + span: i.span, + } + }) } -} -fn lower_item_id(_lctx: &mut LoweringContext, i: &Item) -> hir::ItemId { - hir::ItemId { id: i.id } -} + fn lower_mod(&mut self, m: &Mod) -> hir::Mod { + hir::Mod { + inner: m.inner, + item_ids: m.items.iter().map(|x| self.lower_item_id(x)).collect(), + } + } -pub fn lower_item(lctx: &mut LoweringContext, i: &Item) -> hir::Item { - let node = lctx.with_parent_def(i.id, |lctx| { - lower_item_kind(lctx, &i.node) - }); + fn lower_macro_def(&mut self, m: &MacroDef) -> hir::MacroDef { + hir::MacroDef { + name: m.ident.name, + attrs: self.lower_attrs(&m.attrs), + id: m.id, + span: m.span, + imported_from: m.imported_from.map(|x| x.name), + export: m.export, + use_locally: m.use_locally, + allow_internal_unstable: m.allow_internal_unstable, + body: m.body.clone().into(), + } + } - hir::Item { - id: i.id, - name: i.ident.name, - attrs: lower_attrs(lctx, &i.attrs), - node: node, - vis: lower_visibility(lctx, &i.vis), - span: i.span, + fn lower_item_id(&mut self, i: &Item) -> hir::ItemId { + hir::ItemId { id: i.id } } -} -fn lower_foreign_item(lctx: &mut LoweringContext, i: &ForeignItem) -> hir::ForeignItem { - lctx.with_parent_def(i.id, |lctx| { - hir::ForeignItem { + pub fn lower_item(&mut self, i: &Item) -> hir::Item { + let node = self.with_parent_def(i.id, |this| { + this.lower_item_kind(&i.node) + }); + + hir::Item { id: i.id, name: i.ident.name, - attrs: lower_attrs(lctx, &i.attrs), - node: match i.node { - ForeignItemKind::Fn(ref fdec, ref generics) => { - hir::ForeignItemFn(lower_fn_decl(lctx, fdec), lower_generics(lctx, generics)) - } - ForeignItemKind::Static(ref t, m) => { - hir::ForeignItemStatic(lower_ty(lctx, t), m) - } - }, - vis: lower_visibility(lctx, &i.vis), + attrs: self.lower_attrs(&i.attrs), + node: node, + vis: self.lower_visibility(&i.vis), span: i.span, } - }) -} + } -fn lower_method_sig(lctx: &mut LoweringContext, sig: &MethodSig) -> hir::MethodSig { - hir::MethodSig { - generics: lower_generics(lctx, &sig.generics), - abi: sig.abi, - explicit_self: lower_explicit_self(lctx, &sig.explicit_self), - unsafety: lower_unsafety(lctx, sig.unsafety), - constness: lower_constness(lctx, sig.constness), - decl: lower_fn_decl(lctx, &sig.decl), + fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem { + self.with_parent_def(i.id, |this| { + hir::ForeignItem { + id: i.id, + name: i.ident.name, + attrs: this.lower_attrs(&i.attrs), + node: match i.node { + ForeignItemKind::Fn(ref fdec, ref generics) => { + hir::ForeignItemFn(this.lower_fn_decl(fdec), this.lower_generics(generics)) + } + ForeignItemKind::Static(ref t, m) => { + hir::ForeignItemStatic(this.lower_ty(t), m) + } + }, + vis: this.lower_visibility(&i.vis), + span: i.span, + } + }) } -} -fn lower_unsafety(_lctx: &mut LoweringContext, u: Unsafety) -> hir::Unsafety { - match u { - Unsafety::Unsafe => hir::Unsafety::Unsafe, - Unsafety::Normal => hir::Unsafety::Normal, + fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { + hir::MethodSig { + generics: self.lower_generics(&sig.generics), + abi: sig.abi, + explicit_self: self.lower_explicit_self(&sig.explicit_self), + unsafety: self.lower_unsafety(sig.unsafety), + constness: self.lower_constness(sig.constness), + decl: self.lower_fn_decl(&sig.decl), + } } -} -fn lower_constness(_lctx: &mut LoweringContext, c: Constness) -> hir::Constness { - match c { - Constness::Const => hir::Constness::Const, - Constness::NotConst => hir::Constness::NotConst, + fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety { + match u { + Unsafety::Unsafe => hir::Unsafety::Unsafe, + Unsafety::Normal => hir::Unsafety::Normal, + } } -} -fn lower_unop(_lctx: &mut LoweringContext, u: UnOp) -> hir::UnOp { - match u { - UnOp::Deref => hir::UnDeref, - UnOp::Not => hir::UnNot, - UnOp::Neg => hir::UnNeg, + fn lower_constness(&mut self, c: Constness) -> hir::Constness { + match c { + Constness::Const => hir::Constness::Const, + Constness::NotConst => hir::Constness::NotConst, + } } -} -fn lower_binop(_lctx: &mut LoweringContext, b: BinOp) -> hir::BinOp { - Spanned { - node: match b.node { - BinOpKind::Add => hir::BiAdd, - BinOpKind::Sub => hir::BiSub, - BinOpKind::Mul => hir::BiMul, - BinOpKind::Div => hir::BiDiv, - BinOpKind::Rem => hir::BiRem, - BinOpKind::And => hir::BiAnd, - BinOpKind::Or => hir::BiOr, - BinOpKind::BitXor => hir::BiBitXor, - BinOpKind::BitAnd => hir::BiBitAnd, - BinOpKind::BitOr => hir::BiBitOr, - BinOpKind::Shl => hir::BiShl, - BinOpKind::Shr => hir::BiShr, - BinOpKind::Eq => hir::BiEq, - BinOpKind::Lt => hir::BiLt, - BinOpKind::Le => hir::BiLe, - BinOpKind::Ne => hir::BiNe, - BinOpKind::Ge => hir::BiGe, - BinOpKind::Gt => hir::BiGt, - }, - span: b.span, + fn lower_unop(&mut self, u: UnOp) -> hir::UnOp { + match u { + UnOp::Deref => hir::UnDeref, + UnOp::Not => hir::UnNot, + UnOp::Neg => hir::UnNeg, + } } -} -fn lower_pat(lctx: &mut LoweringContext, p: &Pat) -> P { - P(hir::Pat { - id: p.id, - node: match p.node { - PatKind::Wild => hir::PatKind::Wild, - PatKind::Ident(ref binding_mode, pth1, ref sub) => { - lctx.with_parent_def(p.id, |lctx| { - hir::PatKind::Ident(lower_binding_mode(lctx, binding_mode), - respan(pth1.span, lower_ident(lctx, pth1.node)), - sub.as_ref().map(|x| lower_pat(lctx, x))) - }) - } - PatKind::Lit(ref e) => hir::PatKind::Lit(lower_expr(lctx, e)), - PatKind::TupleStruct(ref pth, ref pats) => { - hir::PatKind::TupleStruct(lower_path(lctx, pth), - pats.as_ref() - .map(|pats| pats.iter().map(|x| lower_pat(lctx, x)).collect())) - } - PatKind::Path(ref pth) => { - hir::PatKind::Path(lower_path(lctx, pth)) - } - PatKind::QPath(ref qself, ref pth) => { - let qself = hir::QSelf { - ty: lower_ty(lctx, &qself.ty), - position: qself.position, - }; - hir::PatKind::QPath(qself, lower_path(lctx, pth)) - } - PatKind::Struct(ref pth, ref fields, etc) => { - let pth = lower_path(lctx, pth); - let fs = fields.iter() - .map(|f| { - Spanned { - span: f.span, - node: hir::FieldPat { - name: f.node.ident.name, - pat: lower_pat(lctx, &f.node.pat), - is_shorthand: f.node.is_shorthand, - }, - } - }) - .collect(); - hir::PatKind::Struct(pth, fs, etc) - } - PatKind::Tup(ref elts) => { - hir::PatKind::Tup(elts.iter().map(|x| lower_pat(lctx, x)).collect()) - } - PatKind::Box(ref inner) => hir::PatKind::Box(lower_pat(lctx, inner)), - PatKind::Ref(ref inner, mutbl) => { - hir::PatKind::Ref(lower_pat(lctx, inner), lower_mutability(lctx, mutbl)) - } - PatKind::Range(ref e1, ref e2) => { - hir::PatKind::Range(lower_expr(lctx, e1), lower_expr(lctx, e2)) - } - PatKind::Vec(ref before, ref slice, ref after) => { - hir::PatKind::Vec(before.iter().map(|x| lower_pat(lctx, x)).collect(), - slice.as_ref().map(|x| lower_pat(lctx, x)), - after.iter().map(|x| lower_pat(lctx, x)).collect()) - } - PatKind::Mac(_) => panic!("Shouldn't exist here"), - }, - span: p.span, - }) -} + fn lower_binop(&mut self, b: BinOp) -> hir::BinOp { + Spanned { + node: match b.node { + BinOpKind::Add => hir::BiAdd, + BinOpKind::Sub => hir::BiSub, + BinOpKind::Mul => hir::BiMul, + BinOpKind::Div => hir::BiDiv, + BinOpKind::Rem => hir::BiRem, + BinOpKind::And => hir::BiAnd, + BinOpKind::Or => hir::BiOr, + BinOpKind::BitXor => hir::BiBitXor, + BinOpKind::BitAnd => hir::BiBitAnd, + BinOpKind::BitOr => hir::BiBitOr, + BinOpKind::Shl => hir::BiShl, + BinOpKind::Shr => hir::BiShr, + BinOpKind::Eq => hir::BiEq, + BinOpKind::Lt => hir::BiLt, + BinOpKind::Le => hir::BiLe, + BinOpKind::Ne => hir::BiNe, + BinOpKind::Ge => hir::BiGe, + BinOpKind::Gt => hir::BiGt, + }, + span: b.span, + } + } -fn lower_expr(lctx: &mut LoweringContext, e: &Expr) -> P { - P(hir::Expr { - id: e.id, - node: match e.node { - // Issue #22181: - // Eventually a desugaring for `box EXPR` - // (similar to the desugaring above for `in PLACE BLOCK`) - // should go here, desugaring - // - // to: - // - // let mut place = BoxPlace::make_place(); - // let raw_place = Place::pointer(&mut place); - // let value = $value; - // unsafe { - // ::std::ptr::write(raw_place, value); - // Boxed::finalize(place) - // } - // - // But for now there are type-inference issues doing that. - ExprKind::Box(ref e) => { - hir::ExprBox(lower_expr(lctx, e)) - } + fn lower_pat(&mut self, p: &Pat) -> P { + P(hir::Pat { + id: p.id, + node: match p.node { + PatKind::Wild => hir::PatKind::Wild, + PatKind::Ident(ref binding_mode, pth1, ref sub) => { + self.with_parent_def(p.id, |this| { + hir::PatKind::Ident(this.lower_binding_mode(binding_mode), + respan(pth1.span, this.lower_ident(pth1.node)), + sub.as_ref().map(|x| this.lower_pat(x))) + }) + } + PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)), + PatKind::TupleStruct(ref pth, ref pats) => { + hir::PatKind::TupleStruct(self.lower_path(pth), + pats.as_ref() + .map(|pats| pats.iter().map(|x| self.lower_pat(x)).collect())) + } + PatKind::Path(ref pth) => { + hir::PatKind::Path(self.lower_path(pth)) + } + PatKind::QPath(ref qself, ref pth) => { + let qself = hir::QSelf { + ty: self.lower_ty(&qself.ty), + position: qself.position, + }; + hir::PatKind::QPath(qself, self.lower_path(pth)) + } + PatKind::Struct(ref pth, ref fields, etc) => { + let pth = self.lower_path(pth); + let fs = fields.iter() + .map(|f| { + Spanned { + span: f.span, + node: hir::FieldPat { + name: f.node.ident.name, + pat: self.lower_pat(&f.node.pat), + is_shorthand: f.node.is_shorthand, + }, + } + }) + .collect(); + hir::PatKind::Struct(pth, fs, etc) + } + PatKind::Tup(ref elts) => { + hir::PatKind::Tup(elts.iter().map(|x| self.lower_pat(x)).collect()) + } + PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)), + PatKind::Ref(ref inner, mutbl) => { + hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl)) + } + PatKind::Range(ref e1, ref e2) => { + hir::PatKind::Range(self.lower_expr(e1), self.lower_expr(e2)) + } + PatKind::Vec(ref before, ref slice, ref after) => { + hir::PatKind::Vec(before.iter().map(|x| self.lower_pat(x)).collect(), + slice.as_ref().map(|x| self.lower_pat(x)), + after.iter().map(|x| self.lower_pat(x)).collect()) + } + PatKind::Mac(_) => panic!("Shouldn't exist here"), + }, + span: p.span, + }) + } - // Desugar ExprBox: `in (PLACE) EXPR` - ExprKind::InPlace(ref placer, ref value_expr) => { + fn lower_expr(&mut self, e: &Expr) -> P { + P(hir::Expr { + id: e.id, + node: match e.node { + // Issue #22181: + // Eventually a desugaring for `box EXPR` + // (similar to the desugaring above for `in PLACE BLOCK`) + // should go here, desugaring + // // to: // - // let p = PLACE; - // let mut place = Placer::make_place(p); + // let mut place = BoxPlace::make_place(); // let raw_place = Place::pointer(&mut place); - // push_unsafe!({ - // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); - // InPlace::finalize(place) - // }) - let placer_expr = lower_expr(lctx, placer); - let value_expr = lower_expr(lctx, value_expr); - - let placer_ident = lctx.str_to_ident("placer"); - let place_ident = lctx.str_to_ident("place"); - let p_ptr_ident = lctx.str_to_ident("p_ptr"); - - let make_place = ["ops", "Placer", "make_place"]; - let place_pointer = ["ops", "Place", "pointer"]; - let move_val_init = ["intrinsics", "move_val_init"]; - let inplace_finalize = ["ops", "InPlace", "finalize"]; - - let make_call = |lctx: &mut LoweringContext, p, args| { - let path = core_path(lctx, e.span, p); - let path = expr_path(lctx, path, None); - expr_call(lctx, e.span, path, args, None) - }; - - let mk_stmt_let = |lctx: &mut LoweringContext, bind, expr| { - stmt_let(lctx, e.span, false, bind, expr, None) - }; - - let mk_stmt_let_mut = |lctx: &mut LoweringContext, bind, expr| { - stmt_let(lctx, e.span, true, bind, expr, None) - }; - - // let placer = ; - let (s1, placer_binding) = { - let placer_expr = signal_block_expr(lctx, - hir_vec![], - placer_expr, - e.span, - hir::PopUnstableBlock, - None); - mk_stmt_let(lctx, placer_ident, placer_expr) - }; - - // let mut place = Placer::make_place(placer); - let (s2, place_binding) = { - let placer = expr_ident(lctx, e.span, placer_ident, None, placer_binding); - let call = make_call(lctx, &make_place, hir_vec![placer]); - mk_stmt_let_mut(lctx, place_ident, call) - }; - - // let p_ptr = Place::pointer(&mut place); - let (s3, p_ptr_binding) = { - let agent = expr_ident(lctx, e.span, place_ident, None, place_binding); - let args = hir_vec![expr_mut_addr_of(lctx, e.span, agent, None)]; - let call = make_call(lctx, &place_pointer, args); - mk_stmt_let(lctx, p_ptr_ident, call) - }; - - // pop_unsafe!(EXPR)); - let pop_unsafe_expr = { - let value_expr = signal_block_expr(lctx, - hir_vec![], - value_expr, - e.span, - hir::PopUnstableBlock, - None); - signal_block_expr(lctx, - hir_vec![], - value_expr, - e.span, - hir::PopUnsafeBlock(hir::CompilerGenerated), None) - }; - - // push_unsafe!({ - // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); - // InPlace::finalize(place) - // }) - let expr = { - let ptr = expr_ident(lctx, e.span, p_ptr_ident, None, p_ptr_binding); - let call_move_val_init = - hir::StmtSemi( - make_call(lctx, &move_val_init, hir_vec![ptr, pop_unsafe_expr]), - lctx.next_id()); - let call_move_val_init = respan(e.span, call_move_val_init); - - let place = expr_ident(lctx, e.span, place_ident, None, place_binding); - let call = make_call(lctx, &inplace_finalize, hir_vec![place]); - signal_block_expr(lctx, - hir_vec![call_move_val_init], - call, - e.span, - hir::PushUnsafeBlock(hir::CompilerGenerated), None) - }; - - return signal_block_expr(lctx, - hir_vec![s1, s2, s3], - expr, - e.span, - hir::PushUnstableBlock, - e.attrs.clone()); - } + // let value = $value; + // unsafe { + // ::std::ptr::write(raw_place, value); + // Boxed::finalize(place) + // } + // + // But for now there are type-inference issues doing that. + ExprKind::Box(ref e) => { + hir::ExprBox(self.lower_expr(e)) + } - ExprKind::Vec(ref exprs) => { - hir::ExprVec(exprs.iter().map(|x| lower_expr(lctx, x)).collect()) - } - ExprKind::Repeat(ref expr, ref count) => { - let expr = lower_expr(lctx, expr); - let count = lower_expr(lctx, count); - hir::ExprRepeat(expr, count) - } - ExprKind::Tup(ref elts) => { - hir::ExprTup(elts.iter().map(|x| lower_expr(lctx, x)).collect()) - } - ExprKind::Call(ref f, ref args) => { - let f = lower_expr(lctx, f); - hir::ExprCall(f, args.iter().map(|x| lower_expr(lctx, x)).collect()) - } - ExprKind::MethodCall(i, ref tps, ref args) => { - let tps = tps.iter().map(|x| lower_ty(lctx, x)).collect(); - let args = args.iter().map(|x| lower_expr(lctx, x)).collect(); - hir::ExprMethodCall(respan(i.span, i.node.name), tps, args) - } - ExprKind::Binary(binop, ref lhs, ref rhs) => { - let binop = lower_binop(lctx, binop); - let lhs = lower_expr(lctx, lhs); - let rhs = lower_expr(lctx, rhs); - hir::ExprBinary(binop, lhs, rhs) - } - ExprKind::Unary(op, ref ohs) => { - let op = lower_unop(lctx, op); - let ohs = lower_expr(lctx, ohs); - hir::ExprUnary(op, ohs) - } - ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())), - ExprKind::Cast(ref expr, ref ty) => { - let expr = lower_expr(lctx, expr); - hir::ExprCast(expr, lower_ty(lctx, ty)) - } - ExprKind::Type(ref expr, ref ty) => { - let expr = lower_expr(lctx, expr); - hir::ExprType(expr, lower_ty(lctx, ty)) - } - ExprKind::AddrOf(m, ref ohs) => { - let m = lower_mutability(lctx, m); - let ohs = lower_expr(lctx, ohs); - hir::ExprAddrOf(m, ohs) - } - // More complicated than you might expect because the else branch - // might be `if let`. - ExprKind::If(ref cond, ref blk, ref else_opt) => { - let else_opt = else_opt.as_ref().map(|els| { - match els.node { - ExprKind::IfLet(..) => { - // wrap the if-let expr in a block - let span = els.span; - let els = lower_expr(lctx, els); - let id = lctx.next_id(); - let blk = P(hir::Block { - stmts: hir_vec![], - expr: Some(els), - id: id, - rules: hir::DefaultBlock, - span: span, - }); - expr_block(lctx, blk, None) - } - _ => lower_expr(lctx, els), - } - }); + // Desugar ExprBox: `in (PLACE) EXPR` + ExprKind::InPlace(ref placer, ref value_expr) => { + // to: + // + // let p = PLACE; + // let mut place = Placer::make_place(p); + // let raw_place = Place::pointer(&mut place); + // push_unsafe!({ + // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); + // InPlace::finalize(place) + // }) + let placer_expr = self.lower_expr(placer); + let value_expr = self.lower_expr(value_expr); + + let placer_ident = self.str_to_ident("placer"); + let place_ident = self.str_to_ident("place"); + let p_ptr_ident = self.str_to_ident("p_ptr"); + + let make_place = ["ops", "Placer", "make_place"]; + let place_pointer = ["ops", "Place", "pointer"]; + let move_val_init = ["intrinsics", "move_val_init"]; + let inplace_finalize = ["ops", "InPlace", "finalize"]; + + let make_call = |this: &mut LoweringContext, p, args| { + let path = core_path(this, e.span, p); + let path = expr_path(this, path, None); + expr_call(this, e.span, path, args, None) + }; - hir::ExprIf(lower_expr(lctx, cond), lower_block(lctx, blk), else_opt) - } - ExprKind::While(ref cond, ref body, opt_ident) => { - hir::ExprWhile(lower_expr(lctx, cond), lower_block(lctx, body), - opt_ident.map(|ident| lower_ident(lctx, ident))) - } - ExprKind::Loop(ref body, opt_ident) => { - hir::ExprLoop(lower_block(lctx, body), - opt_ident.map(|ident| lower_ident(lctx, ident))) - } - ExprKind::Match(ref expr, ref arms) => { - hir::ExprMatch(lower_expr(lctx, expr), - arms.iter().map(|x| lower_arm(lctx, x)).collect(), - hir::MatchSource::Normal) - } - ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => { - lctx.with_parent_def(e.id, |lctx| { - hir::ExprClosure(lower_capture_clause(lctx, capture_clause), - lower_fn_decl(lctx, decl), - lower_block(lctx, body), - fn_decl_span) - }) - } - ExprKind::Block(ref blk) => hir::ExprBlock(lower_block(lctx, blk)), - ExprKind::Assign(ref el, ref er) => { - hir::ExprAssign(lower_expr(lctx, el), lower_expr(lctx, er)) - } - ExprKind::AssignOp(op, ref el, ref er) => { - hir::ExprAssignOp(lower_binop(lctx, op), - lower_expr(lctx, el), - lower_expr(lctx, er)) - } - ExprKind::Field(ref el, ident) => { - hir::ExprField(lower_expr(lctx, el), respan(ident.span, ident.node.name)) - } - ExprKind::TupField(ref el, ident) => { - hir::ExprTupField(lower_expr(lctx, el), ident) - } - ExprKind::Index(ref el, ref er) => { - hir::ExprIndex(lower_expr(lctx, el), lower_expr(lctx, er)) - } - ExprKind::Range(ref e1, ref e2, lims) => { - fn make_struct(lctx: &mut LoweringContext, - ast_expr: &Expr, - path: &[&str], - fields: &[(&str, &P)]) -> P { - let strs = std_path(lctx, &iter::once(&"ops") - .chain(path) - .map(|s| *s) - .collect::>()); - - let structpath = path_global(ast_expr.span, strs); - - let hir_expr = if fields.len() == 0 { - expr_path(lctx, - structpath, - ast_expr.attrs.clone()) - } else { - let fields = fields.into_iter().map(|&(s, e)| { - let expr = lower_expr(lctx, &e); - let signal_block = signal_block_expr(lctx, - hir_vec![], - expr, - e.span, - hir::PopUnstableBlock, - None); - field(token::intern(s), signal_block, ast_expr.span) - }).collect(); - let attrs = ast_expr.attrs.clone(); - - expr_struct(lctx, ast_expr.span, structpath, fields, None, attrs) + let mk_stmt_let = |this: &mut LoweringContext, bind, expr| { + stmt_let(this, e.span, false, bind, expr, None) }; - signal_block_expr(lctx, - hir_vec![], - hir_expr, - ast_expr.span, - hir::PushUnstableBlock, - None) - } + let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| { + stmt_let(this, e.span, true, bind, expr, None) + }; - use syntax::ast::RangeLimits::*; + // let placer = ; + let (s1, placer_binding) = { + let placer_expr = signal_block_expr(self, + hir_vec![], + placer_expr, + e.span, + hir::PopUnstableBlock, + None); + mk_stmt_let(self, placer_ident, placer_expr) + }; - return match (e1, e2, lims) { - (&None, &None, HalfOpen) => - make_struct(lctx, e, &["RangeFull"], - &[]), + // let mut place = Placer::make_place(placer); + let (s2, place_binding) = { + let placer = expr_ident(self, e.span, placer_ident, None, placer_binding); + let call = make_call(self, &make_place, hir_vec![placer]); + mk_stmt_let_mut(self, place_ident, call) + }; - (&Some(ref e1), &None, HalfOpen) => - make_struct(lctx, e, &["RangeFrom"], - &[("start", e1)]), + // let p_ptr = Place::pointer(&mut place); + let (s3, p_ptr_binding) = { + let agent = expr_ident(self, e.span, place_ident, None, place_binding); + let args = hir_vec![expr_mut_addr_of(self, e.span, agent, None)]; + let call = make_call(self, &place_pointer, args); + mk_stmt_let(self, p_ptr_ident, call) + }; - (&None, &Some(ref e2), HalfOpen) => - make_struct(lctx, e, &["RangeTo"], - &[("end", e2)]), + // pop_unsafe!(EXPR)); + let pop_unsafe_expr = { + let value_expr = signal_block_expr(self, + hir_vec![], + value_expr, + e.span, + hir::PopUnstableBlock, + None); + signal_block_expr(self, + hir_vec![], + value_expr, + e.span, + hir::PopUnsafeBlock(hir::CompilerGenerated), None) + }; - (&Some(ref e1), &Some(ref e2), HalfOpen) => - make_struct(lctx, e, &["Range"], - &[("start", e1), ("end", e2)]), + // push_unsafe!({ + // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); + // InPlace::finalize(place) + // }) + let expr = { + let ptr = expr_ident(self, e.span, p_ptr_ident, None, p_ptr_binding); + let call_move_val_init = + hir::StmtSemi( + make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]), + self.next_id()); + let call_move_val_init = respan(e.span, call_move_val_init); + + let place = expr_ident(self, e.span, place_ident, None, place_binding); + let call = make_call(self, &inplace_finalize, hir_vec![place]); + signal_block_expr(self, + hir_vec![call_move_val_init], + call, + e.span, + hir::PushUnsafeBlock(hir::CompilerGenerated), None) + }; - (&None, &Some(ref e2), Closed) => - make_struct(lctx, e, &["RangeToInclusive"], - &[("end", e2)]), + return signal_block_expr(self, + hir_vec![s1, s2, s3], + expr, + e.span, + hir::PushUnstableBlock, + e.attrs.clone()); + } - (&Some(ref e1), &Some(ref e2), Closed) => - make_struct(lctx, e, &["RangeInclusive", "NonEmpty"], - &[("start", e1), ("end", e2)]), + ExprKind::Vec(ref exprs) => { + hir::ExprVec(exprs.iter().map(|x| self.lower_expr(x)).collect()) + } + ExprKind::Repeat(ref expr, ref count) => { + let expr = self.lower_expr(expr); + let count = self.lower_expr(count); + hir::ExprRepeat(expr, count) + } + ExprKind::Tup(ref elts) => { + hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect()) + } + ExprKind::Call(ref f, ref args) => { + let f = self.lower_expr(f); + hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect()) + } + ExprKind::MethodCall(i, ref tps, ref args) => { + let tps = tps.iter().map(|x| self.lower_ty(x)).collect(); + let args = args.iter().map(|x| self.lower_expr(x)).collect(); + hir::ExprMethodCall(respan(i.span, i.node.name), tps, args) + } + ExprKind::Binary(binop, ref lhs, ref rhs) => { + let binop = self.lower_binop(binop); + let lhs = self.lower_expr(lhs); + let rhs = self.lower_expr(rhs); + hir::ExprBinary(binop, lhs, rhs) + } + ExprKind::Unary(op, ref ohs) => { + let op = self.lower_unop(op); + let ohs = self.lower_expr(ohs); + hir::ExprUnary(op, ohs) + } + ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())), + ExprKind::Cast(ref expr, ref ty) => { + let expr = self.lower_expr(expr); + hir::ExprCast(expr, self.lower_ty(ty)) + } + ExprKind::Type(ref expr, ref ty) => { + let expr = self.lower_expr(expr); + hir::ExprType(expr, self.lower_ty(ty)) + } + ExprKind::AddrOf(m, ref ohs) => { + let m = self.lower_mutability(m); + let ohs = self.lower_expr(ohs); + hir::ExprAddrOf(m, ohs) + } + // More complicated than you might expect because the else branch + // might be `if let`. + ExprKind::If(ref cond, ref blk, ref else_opt) => { + let else_opt = else_opt.as_ref().map(|els| { + match els.node { + ExprKind::IfLet(..) => { + // wrap the if-let expr in a block + let span = els.span; + let els = self.lower_expr(els); + let id = self.next_id(); + let blk = P(hir::Block { + stmts: hir_vec![], + expr: Some(els), + id: id, + rules: hir::DefaultBlock, + span: span, + }); + expr_block(self, blk, None) + } + _ => self.lower_expr(els), + } + }); - _ => panic!(lctx.id_assigner.diagnostic() - .span_fatal(e.span, "inclusive range with no end")), - }; - } - ExprKind::Path(ref qself, ref path) => { - let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| { - hir::QSelf { - ty: lower_ty(lctx, ty), - position: position, + hir::ExprIf(self.lower_expr(cond), self.lower_block(blk), else_opt) + } + ExprKind::While(ref cond, ref body, opt_ident) => { + hir::ExprWhile(self.lower_expr(cond), self.lower_block(body), + opt_ident.map(|ident| self.lower_ident(ident))) + } + ExprKind::Loop(ref body, opt_ident) => { + hir::ExprLoop(self.lower_block(body), + opt_ident.map(|ident| self.lower_ident(ident))) + } + ExprKind::Match(ref expr, ref arms) => { + hir::ExprMatch(self.lower_expr(expr), + arms.iter().map(|x| self.lower_arm(x)).collect(), + hir::MatchSource::Normal) + } + ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => { + self.with_parent_def(e.id, |this| { + hir::ExprClosure(this.lower_capture_clause(capture_clause), + this.lower_fn_decl(decl), + this.lower_block(body), + fn_decl_span) + }) + } + ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)), + ExprKind::Assign(ref el, ref er) => { + hir::ExprAssign(self.lower_expr(el), self.lower_expr(er)) + } + ExprKind::AssignOp(op, ref el, ref er) => { + hir::ExprAssignOp(self.lower_binop(op), + self.lower_expr(el), + self.lower_expr(er)) + } + ExprKind::Field(ref el, ident) => { + hir::ExprField(self.lower_expr(el), respan(ident.span, ident.node.name)) + } + ExprKind::TupField(ref el, ident) => { + hir::ExprTupField(self.lower_expr(el), ident) + } + ExprKind::Index(ref el, ref er) => { + hir::ExprIndex(self.lower_expr(el), self.lower_expr(er)) + } + ExprKind::Range(ref e1, ref e2, lims) => { + fn make_struct(this: &mut LoweringContext, + ast_expr: &Expr, + path: &[&str], + fields: &[(&str, &P)]) -> P { + let strs = std_path(this, &iter::once(&"ops") + .chain(path) + .map(|s| *s) + .collect::>()); + + let structpath = path_global(ast_expr.span, strs); + + let hir_expr = if fields.len() == 0 { + expr_path(this, + structpath, + ast_expr.attrs.clone()) + } else { + let fields = fields.into_iter().map(|&(s, e)| { + let expr = this.lower_expr(&e); + let signal_block = signal_block_expr(this, + hir_vec![], + expr, + e.span, + hir::PopUnstableBlock, + None); + field(token::intern(s), signal_block, ast_expr.span) + }).collect(); + let attrs = ast_expr.attrs.clone(); + + expr_struct(this, ast_expr.span, structpath, fields, None, attrs) + }; + + signal_block_expr(this, + hir_vec![], + hir_expr, + ast_expr.span, + hir::PushUnstableBlock, + None) } - }); - hir::ExprPath(hir_qself, lower_path_full(lctx, path, qself.is_none())) - } - ExprKind::Break(opt_ident) => hir::ExprBreak(opt_ident.map(|sp_ident| { - respan(sp_ident.span, lower_ident(lctx, sp_ident.node)) - })), - ExprKind::Again(opt_ident) => hir::ExprAgain(opt_ident.map(|sp_ident| { - respan(sp_ident.span, lower_ident(lctx, sp_ident.node)) - })), - ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| lower_expr(lctx, x))), - ExprKind::InlineAsm(InlineAsm { - ref inputs, - ref outputs, - ref asm, - asm_str_style, - ref clobbers, - volatile, - alignstack, - dialect, - expn_id, - }) => hir::ExprInlineAsm(hir::InlineAsm { - inputs: inputs.iter().map(|&(ref c, _)| c.clone()).collect(), - outputs: outputs.iter() - .map(|out| { - hir::InlineAsmOutput { - constraint: out.constraint.clone(), - is_rw: out.is_rw, - is_indirect: out.is_indirect, - } - }) - .collect(), - asm: asm.clone(), - asm_str_style: asm_str_style, - clobbers: clobbers.clone().into(), - volatile: volatile, - alignstack: alignstack, - dialect: dialect, - expn_id: expn_id, - }, outputs.iter().map(|out| lower_expr(lctx, &out.expr)).collect(), - inputs.iter().map(|&(_, ref input)| lower_expr(lctx, input)).collect()), - ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { - hir::ExprStruct(lower_path(lctx, path), - fields.iter().map(|x| lower_field(lctx, x)).collect(), - maybe_expr.as_ref().map(|x| lower_expr(lctx, x))) - } - ExprKind::Paren(ref ex) => { - // merge attributes into the inner expression. - return lower_expr(lctx, ex).map(|mut ex| { - ex.attrs.update(|attrs| { - attrs.prepend(e.attrs.clone()) + + use syntax::ast::RangeLimits::*; + + return match (e1, e2, lims) { + (&None, &None, HalfOpen) => + make_struct(self, e, &["RangeFull"], + &[]), + + (&Some(ref e1), &None, HalfOpen) => + make_struct(self, e, &["RangeFrom"], + &[("start", e1)]), + + (&None, &Some(ref e2), HalfOpen) => + make_struct(self, e, &["RangeTo"], + &[("end", e2)]), + + (&Some(ref e1), &Some(ref e2), HalfOpen) => + make_struct(self, e, &["Range"], + &[("start", e1), ("end", e2)]), + + (&None, &Some(ref e2), Closed) => + make_struct(self, e, &["RangeToInclusive"], + &[("end", e2)]), + + (&Some(ref e1), &Some(ref e2), Closed) => + make_struct(self, e, &["RangeInclusive", "NonEmpty"], + &[("start", e1), ("end", e2)]), + + _ => panic!(self.id_assigner.diagnostic() + .span_fatal(e.span, "inclusive range with no end")), + }; + } + ExprKind::Path(ref qself, ref path) => { + let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| { + hir::QSelf { + ty: self.lower_ty(ty), + position: position, + } }); - ex - }); - } + hir::ExprPath(hir_qself, self.lower_path_full(path, qself.is_none())) + } + ExprKind::Break(opt_ident) => hir::ExprBreak(opt_ident.map(|sp_ident| { + respan(sp_ident.span, self.lower_ident(sp_ident.node)) + })), + ExprKind::Again(opt_ident) => hir::ExprAgain(opt_ident.map(|sp_ident| { + respan(sp_ident.span, self.lower_ident(sp_ident.node)) + })), + ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))), + ExprKind::InlineAsm(InlineAsm { + ref inputs, + ref outputs, + ref asm, + asm_str_style, + ref clobbers, + volatile, + alignstack, + dialect, + expn_id, + }) => hir::ExprInlineAsm(hir::InlineAsm { + inputs: inputs.iter().map(|&(ref c, _)| c.clone()).collect(), + outputs: outputs.iter() + .map(|out| { + hir::InlineAsmOutput { + constraint: out.constraint.clone(), + is_rw: out.is_rw, + is_indirect: out.is_indirect, + } + }) + .collect(), + asm: asm.clone(), + asm_str_style: asm_str_style, + clobbers: clobbers.clone().into(), + volatile: volatile, + alignstack: alignstack, + dialect: dialect, + expn_id: expn_id, + }, outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(), + inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect()), + ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { + hir::ExprStruct(self.lower_path(path), + fields.iter().map(|x| self.lower_field(x)).collect(), + maybe_expr.as_ref().map(|x| self.lower_expr(x))) + } + ExprKind::Paren(ref ex) => { + // merge attributes into the inner expression. + return self.lower_expr(ex).map(|mut ex| { + ex.attrs.update(|attrs| { + attrs.prepend(e.attrs.clone()) + }); + ex + }); + } - // Desugar ExprIfLet - // From: `if let = []` - ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => { - // to: - // - // match { - // => , - // [_ if => ,] - // _ => [ | ()] - // } - - // ` => ` - let pat_arm = { - let body = lower_block(lctx, body); - let body_expr = expr_block(lctx, body, None); - arm(hir_vec![lower_pat(lctx, pat)], body_expr) - }; - - // `[_ if => ,]` - let mut else_opt = else_opt.as_ref().map(|e| lower_expr(lctx, e)); - let else_if_arms = { - let mut arms = vec![]; - loop { - let else_opt_continue = else_opt.and_then(|els| { - els.and_then(|els| { - match els.node { - // else if - hir::ExprIf(cond, then, else_opt) => { - let pat_under = pat_wild(lctx, e.span); - arms.push(hir::Arm { - attrs: hir_vec![], - pats: hir_vec![pat_under], - guard: Some(cond), - body: expr_block(lctx, then, None), - }); - else_opt.map(|else_opt| (else_opt, true)) + // Desugar ExprIfLet + // From: `if let = []` + ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => { + // to: + // + // match { + // => , + // [_ if => ,] + // _ => [ | ()] + // } + + // ` => ` + let pat_arm = { + let body = self.lower_block(body); + let body_expr = expr_block(self, body, None); + arm(hir_vec![self.lower_pat(pat)], body_expr) + }; + + // `[_ if => ,]` + let mut else_opt = else_opt.as_ref().map(|e| self.lower_expr(e)); + let else_if_arms = { + let mut arms = vec![]; + loop { + let else_opt_continue = else_opt.and_then(|els| { + els.and_then(|els| { + match els.node { + // else if + hir::ExprIf(cond, then, else_opt) => { + let pat_under = pat_wild(self, e.span); + arms.push(hir::Arm { + attrs: hir_vec![], + pats: hir_vec![pat_under], + guard: Some(cond), + body: expr_block(self, then, None), + }); + else_opt.map(|else_opt| (else_opt, true)) + } + _ => Some((P(els), false)), } - _ => Some((P(els), false)), + }) + }); + match else_opt_continue { + Some((e, true)) => { + else_opt = Some(e); + } + Some((e, false)) => { + else_opt = Some(e); + break; + } + None => { + else_opt = None; + break; } - }) - }); - match else_opt_continue { - Some((e, true)) => { - else_opt = Some(e); - } - Some((e, false)) => { - else_opt = Some(e); - break; - } - None => { - else_opt = None; - break; } } - } - arms - }; - - let contains_else_clause = else_opt.is_some(); - - // `_ => [ | ()]` - let else_arm = { - let pat_under = pat_wild(lctx, e.span); - let else_expr = - else_opt.unwrap_or_else( - || expr_tuple(lctx, e.span, hir_vec![], None)); - arm(hir_vec![pat_under], else_expr) - }; - - let mut arms = Vec::with_capacity(else_if_arms.len() + 2); - arms.push(pat_arm); - arms.extend(else_if_arms); - arms.push(else_arm); - - let sub_expr = lower_expr(lctx, sub_expr); - // add attributes to the outer returned expr node - return expr(lctx, - e.span, - hir::ExprMatch(sub_expr, - arms.into(), - hir::MatchSource::IfLetDesugar { - contains_else_clause: contains_else_clause, - }), - e.attrs.clone()); - } + arms + }; - // Desugar ExprWhileLet - // From: `[opt_ident]: while let = ` - ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => { - // to: - // - // [opt_ident]: loop { - // match { - // => , - // _ => break - // } - // } - - // ` => ` - let pat_arm = { - let body = lower_block(lctx, body); - let body_expr = expr_block(lctx, body, None); - arm(hir_vec![lower_pat(lctx, pat)], body_expr) - }; - - // `_ => break` - let break_arm = { - let pat_under = pat_wild(lctx, e.span); - let break_expr = expr_break(lctx, e.span, None); - arm(hir_vec![pat_under], break_expr) - }; - - // `match { ... }` - let arms = hir_vec![pat_arm, break_arm]; - let sub_expr = lower_expr(lctx, sub_expr); - let match_expr = expr(lctx, - e.span, - hir::ExprMatch(sub_expr, - arms, - hir::MatchSource::WhileLetDesugar), - None); - - // `[opt_ident]: loop { ... }` - let loop_block = block_expr(lctx, match_expr); - let loop_expr = hir::ExprLoop(loop_block, - opt_ident.map(|ident| lower_ident(lctx, ident))); - // add attributes to the outer returned expr node - let attrs = e.attrs.clone(); - return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs }); - } + let contains_else_clause = else_opt.is_some(); - // Desugar ExprForLoop - // From: `[opt_ident]: for in ` - ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => { - // to: - // - // { - // let result = match ::std::iter::IntoIterator::into_iter() { - // mut iter => { - // [opt_ident]: loop { - // match ::std::iter::Iterator::next(&mut iter) { - // ::std::option::Option::Some() => , - // ::std::option::Option::None => break - // } - // } - // } - // }; - // result - // } - - // expand - let head = lower_expr(lctx, head); - - let iter = lctx.str_to_ident("iter"); - - // `::std::option::Option::Some() => ` - let pat_arm = { - let body_block = lower_block(lctx, body); - let body_span = body_block.span; - let body_expr = P(hir::Expr { - id: lctx.next_id(), - node: hir::ExprBlock(body_block), - span: body_span, - attrs: None, - }); - let pat = lower_pat(lctx, pat); - let some_pat = pat_some(lctx, e.span, pat); + // `_ => [ | ()]` + let else_arm = { + let pat_under = pat_wild(self, e.span); + let else_expr = + else_opt.unwrap_or_else( + || expr_tuple(self, e.span, hir_vec![], None)); + arm(hir_vec![pat_under], else_expr) + }; - arm(hir_vec![some_pat], body_expr) - }; + let mut arms = Vec::with_capacity(else_if_arms.len() + 2); + arms.push(pat_arm); + arms.extend(else_if_arms); + arms.push(else_arm); + + let sub_expr = self.lower_expr(sub_expr); + // add attributes to the outer returned expr node + return expr(self, + e.span, + hir::ExprMatch(sub_expr, + arms.into(), + hir::MatchSource::IfLetDesugar { + contains_else_clause: contains_else_clause, + }), + e.attrs.clone()); + } - // `::std::option::Option::None => break` - let break_arm = { - let break_expr = expr_break(lctx, e.span, None); + // Desugar ExprWhileLet + // From: `[opt_ident]: while let = ` + ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => { + // to: + // + // [opt_ident]: loop { + // match { + // => , + // _ => break + // } + // } + + // ` => ` + let pat_arm = { + let body = self.lower_block(body); + let body_expr = expr_block(self, body, None); + arm(hir_vec![self.lower_pat(pat)], body_expr) + }; - arm(hir_vec![pat_none(lctx, e.span)], break_expr) - }; + // `_ => break` + let break_arm = { + let pat_under = pat_wild(self, e.span); + let break_expr = expr_break(self, e.span, None); + arm(hir_vec![pat_under], break_expr) + }; - // `mut iter` - let iter_pat = - pat_ident_binding_mode(lctx, e.span, iter, hir::BindByValue(hir::MutMutable)); + // `match { ... }` + let arms = hir_vec![pat_arm, break_arm]; + let sub_expr = self.lower_expr(sub_expr); + let match_expr = expr(self, + e.span, + hir::ExprMatch(sub_expr, + arms, + hir::MatchSource::WhileLetDesugar), + None); + + // `[opt_ident]: loop { ... }` + let loop_block = block_expr(self, match_expr); + let loop_expr = hir::ExprLoop(loop_block, + opt_ident.map(|ident| self.lower_ident(ident))); + // add attributes to the outer returned expr node + let attrs = e.attrs.clone(); + return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs }); + } - // `match ::std::iter::Iterator::next(&mut iter) { ... }` - let match_expr = { - let next_path = { - let strs = std_path(lctx, &["iter", "Iterator", "next"]); + // Desugar ExprForLoop + // From: `[opt_ident]: for in ` + ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => { + // to: + // + // { + // let result = match ::std::iter::IntoIterator::into_iter() { + // mut iter => { + // [opt_ident]: loop { + // match ::std::iter::Iterator::next(&mut iter) { + // ::std::option::Option::Some() => , + // ::std::option::Option::None => break + // } + // } + // } + // }; + // result + // } + + // expand + let head = self.lower_expr(head); + + let iter = self.str_to_ident("iter"); + + // `::std::option::Option::Some() => ` + let pat_arm = { + let body_block = self.lower_block(body); + let body_span = body_block.span; + let body_expr = P(hir::Expr { + id: self.next_id(), + node: hir::ExprBlock(body_block), + span: body_span, + attrs: None, + }); + let pat = self.lower_pat(pat); + let some_pat = pat_some(self, e.span, pat); - path_global(e.span, strs) + arm(hir_vec![some_pat], body_expr) }; - let iter = expr_ident(lctx, e.span, iter, None, iter_pat.id); - let ref_mut_iter = expr_mut_addr_of(lctx, e.span, iter, None); - let next_path = expr_path(lctx, next_path, None); - let next_expr = expr_call(lctx, - e.span, - next_path, - hir_vec![ref_mut_iter], - None); - let arms = hir_vec![pat_arm, break_arm]; - expr(lctx, - e.span, - hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar), - None) - }; + // `::std::option::Option::None => break` + let break_arm = { + let break_expr = expr_break(self, e.span, None); - // `[opt_ident]: loop { ... }` - let loop_block = block_expr(lctx, match_expr); - let loop_expr = hir::ExprLoop(loop_block, - opt_ident.map(|ident| lower_ident(lctx, ident))); - let loop_expr = - P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None }); + arm(hir_vec![pat_none(self, e.span)], break_expr) + }; - // `mut iter => { ... }` - let iter_arm = arm(hir_vec![iter_pat], loop_expr); + // `mut iter` + let iter_pat = pat_ident_binding_mode(self, e.span, iter, + hir::BindByValue(hir::MutMutable)); + + // `match ::std::iter::Iterator::next(&mut iter) { ... }` + let match_expr = { + let next_path = { + let strs = std_path(self, &["iter", "Iterator", "next"]); + + path_global(e.span, strs) + }; + let iter = expr_ident(self, e.span, iter, None, iter_pat.id); + let ref_mut_iter = expr_mut_addr_of(self, e.span, iter, None); + let next_path = expr_path(self, next_path, None); + let next_expr = expr_call(self, + e.span, + next_path, + hir_vec![ref_mut_iter], + None); + let arms = hir_vec![pat_arm, break_arm]; + + expr(self, + e.span, + hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar), + None) + }; - // `match ::std::iter::IntoIterator::into_iter() { ... }` - let into_iter_expr = { - let into_iter_path = { - let strs = std_path(lctx, &["iter", "IntoIterator", "into_iter"]); + // `[opt_ident]: loop { ... }` + let loop_block = block_expr(self, match_expr); + let loop_expr = hir::ExprLoop(loop_block, + opt_ident.map(|ident| self.lower_ident(ident))); + let loop_expr = + P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None }); - path_global(e.span, strs) - }; + // `mut iter => { ... }` + let iter_arm = arm(hir_vec![iter_pat], loop_expr); - let into_iter = expr_path(lctx, into_iter_path, None); - expr_call(lctx, e.span, into_iter, hir_vec![head], None) - }; - - let match_expr = expr_match(lctx, - e.span, - into_iter_expr, - hir_vec![iter_arm], - hir::MatchSource::ForLoopDesugar, - None); - - // `{ let _result = ...; _result }` - // underscore prevents an unused_variables lint if the head diverges - let result_ident = lctx.str_to_ident("_result"); - let (let_stmt, let_stmt_binding) = - stmt_let(lctx, e.span, false, result_ident, match_expr, None); - - let result = expr_ident(lctx, e.span, result_ident, None, let_stmt_binding); - let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result)); - // add the attributes to the outer returned expr node - return expr_block(lctx, block, e.attrs.clone()); - } + // `match ::std::iter::IntoIterator::into_iter() { ... }` + let into_iter_expr = { + let into_iter_path = { + let strs = std_path(self, &["iter", "IntoIterator", "into_iter"]); - // Desugar ExprKind::Try - // From: `?` - ExprKind::Try(ref sub_expr) => { - // to: - // - // { - // match { - // Ok(val) => val, - // Err(err) => { - // return Err(From::from(err)) - // } - // } - // } + path_global(e.span, strs) + }; - // expand - let sub_expr = lower_expr(lctx, sub_expr); - - // Ok(val) => val - let ok_arm = { - let val_ident = lctx.str_to_ident("val"); - let val_pat = pat_ident(lctx, e.span, val_ident); - let val_expr = expr_ident(lctx, e.span, val_ident, None, val_pat.id); - let ok_pat = pat_ok(lctx, e.span, val_pat); - - arm(hir_vec![ok_pat], val_expr) - }; - - // Err(err) => return Err(From::from(err)) - let err_arm = { - let err_ident = lctx.str_to_ident("err"); - let err_local = pat_ident(lctx, e.span, err_ident); - let from_expr = { - let path = std_path(lctx, &["convert", "From", "from"]); - let path = path_global(e.span, path); - let from = expr_path(lctx, path, None); - let err_expr = expr_ident(lctx, e.span, err_ident, None, err_local.id); - - expr_call(lctx, e.span, from, hir_vec![err_expr], None) + let into_iter = expr_path(self, into_iter_path, None); + expr_call(self, e.span, into_iter, hir_vec![head], None) }; - let err_expr = { - let path = std_path(lctx, &["result", "Result", "Err"]); - let path = path_global(e.span, path); - let err_ctor = expr_path(lctx, path, None); - expr_call(lctx, e.span, err_ctor, hir_vec![from_expr], None) + + let match_expr = expr_match(self, + e.span, + into_iter_expr, + hir_vec![iter_arm], + hir::MatchSource::ForLoopDesugar, + None); + + // `{ let _result = ...; _result }` + // underscore prevents an unused_variables lint if the head diverges + let result_ident = self.str_to_ident("_result"); + let (let_stmt, let_stmt_binding) = + stmt_let(self, e.span, false, result_ident, match_expr, None); + + let result = expr_ident(self, e.span, result_ident, None, let_stmt_binding); + let block = block_all(self, e.span, hir_vec![let_stmt], Some(result)); + // add the attributes to the outer returned expr node + return expr_block(self, block, e.attrs.clone()); + } + + // Desugar ExprKind::Try + // From: `?` + ExprKind::Try(ref sub_expr) => { + // to: + // + // { + // match { + // Ok(val) => val, + // Err(err) => { + // return Err(From::from(err)) + // } + // } + // } + + // expand + let sub_expr = self.lower_expr(sub_expr); + + // Ok(val) => val + let ok_arm = { + let val_ident = self.str_to_ident("val"); + let val_pat = pat_ident(self, e.span, val_ident); + let val_expr = expr_ident(self, e.span, val_ident, None, val_pat.id); + let ok_pat = pat_ok(self, e.span, val_pat); + + arm(hir_vec![ok_pat], val_expr) }; - let err_pat = pat_err(lctx, e.span, err_local); - let ret_expr = expr(lctx, e.span, - hir::Expr_::ExprRet(Some(err_expr)), None); - arm(hir_vec![err_pat], ret_expr) - }; + // Err(err) => return Err(From::from(err)) + let err_arm = { + let err_ident = self.str_to_ident("err"); + let err_local = pat_ident(self, e.span, err_ident); + let from_expr = { + let path = std_path(self, &["convert", "From", "from"]); + let path = path_global(e.span, path); + let from = expr_path(self, path, None); + let err_expr = expr_ident(self, e.span, err_ident, None, err_local.id); + + expr_call(self, e.span, from, hir_vec![err_expr], None) + }; + let err_expr = { + let path = std_path(self, &["result", "Result", "Err"]); + let path = path_global(e.span, path); + let err_ctor = expr_path(self, path, None); + expr_call(self, e.span, err_ctor, hir_vec![from_expr], None) + }; + let err_pat = pat_err(self, e.span, err_local); + let ret_expr = expr(self, e.span, + hir::Expr_::ExprRet(Some(err_expr)), None); + + arm(hir_vec![err_pat], ret_expr) + }; - return expr_match(lctx, e.span, sub_expr, hir_vec![err_arm, ok_arm], - hir::MatchSource::TryDesugar, None); - } + return expr_match(self, e.span, sub_expr, hir_vec![err_arm, ok_arm], + hir::MatchSource::TryDesugar, None); + } - ExprKind::Mac(_) => panic!("Shouldn't exist here"), - }, - span: e.span, - attrs: e.attrs.clone(), - }) -} + ExprKind::Mac(_) => panic!("Shouldn't exist here"), + }, + span: e.span, + attrs: e.attrs.clone(), + }) + } -fn lower_stmt(lctx: &mut LoweringContext, s: &Stmt) -> hir::Stmt { - match s.node { - StmtKind::Decl(ref d, id) => { - Spanned { - node: hir::StmtDecl(lower_decl(lctx, d), id), - span: s.span, + fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt { + match s.node { + StmtKind::Decl(ref d, id) => { + Spanned { + node: hir::StmtDecl(self.lower_decl(d), id), + span: s.span, + } } - } - StmtKind::Expr(ref e, id) => { - Spanned { - node: hir::StmtExpr(lower_expr(lctx, e), id), - span: s.span, + StmtKind::Expr(ref e, id) => { + Spanned { + node: hir::StmtExpr(self.lower_expr(e), id), + span: s.span, + } } - } - StmtKind::Semi(ref e, id) => { - Spanned { - node: hir::StmtSemi(lower_expr(lctx, e), id), - span: s.span, + StmtKind::Semi(ref e, id) => { + Spanned { + node: hir::StmtSemi(self.lower_expr(e), id), + span: s.span, + } } + StmtKind::Mac(..) => panic!("Shouldn't exist here"), } - StmtKind::Mac(..) => panic!("Shouldn't exist here"), } -} -fn lower_capture_clause(_lctx: &mut LoweringContext, c: CaptureBy) -> hir::CaptureClause { - match c { - CaptureBy::Value => hir::CaptureByValue, - CaptureBy::Ref => hir::CaptureByRef, + fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause { + match c { + CaptureBy::Value => hir::CaptureByValue, + CaptureBy::Ref => hir::CaptureByRef, + } } -} -fn lower_visibility(lctx: &mut LoweringContext, v: &Visibility) -> hir::Visibility { - match *v { - Visibility::Public => hir::Public, - Visibility::Crate(_) => hir::Visibility::Crate, - Visibility::Restricted { ref path, id } => - hir::Visibility::Restricted { path: P(lower_path(lctx, path)), id: id }, - Visibility::Inherited => hir::Inherited, + fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility { + match *v { + Visibility::Public => hir::Public, + Visibility::Crate(_) => hir::Visibility::Crate, + Visibility::Restricted { ref path, id } => + hir::Visibility::Restricted { path: P(self.lower_path(path)), id: id }, + Visibility::Inherited => hir::Inherited, + } } -} -fn lower_defaultness(_lctx: &mut LoweringContext, d: Defaultness) -> hir::Defaultness { - match d { - Defaultness::Default => hir::Defaultness::Default, - Defaultness::Final => hir::Defaultness::Final, + fn lower_defaultness(&mut self, d: Defaultness) -> hir::Defaultness { + match d { + Defaultness::Default => hir::Defaultness::Default, + Defaultness::Final => hir::Defaultness::Final, + } } -} -fn lower_block_check_mode(lctx: &mut LoweringContext, b: &BlockCheckMode) -> hir::BlockCheckMode { - match *b { - BlockCheckMode::Default => hir::DefaultBlock, - BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(lower_unsafe_source(lctx, u)), + fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode { + match *b { + BlockCheckMode::Default => hir::DefaultBlock, + BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(self.lower_unsafe_source(u)), + } } -} -fn lower_binding_mode(lctx: &mut LoweringContext, b: &BindingMode) -> hir::BindingMode { - match *b { - BindingMode::ByRef(m) => hir::BindByRef(lower_mutability(lctx, m)), - BindingMode::ByValue(m) => hir::BindByValue(lower_mutability(lctx, m)), + fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingMode { + match *b { + BindingMode::ByRef(m) => hir::BindByRef(self.lower_mutability(m)), + BindingMode::ByValue(m) => hir::BindByValue(self.lower_mutability(m)), + } } -} -fn lower_unsafe_source(_lctx: &mut LoweringContext, u: UnsafeSource) -> hir::UnsafeSource { - match u { - CompilerGenerated => hir::CompilerGenerated, - UserProvided => hir::UserProvided, + fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource { + match u { + CompilerGenerated => hir::CompilerGenerated, + UserProvided => hir::UserProvided, + } } -} -fn lower_impl_polarity(_lctx: &mut LoweringContext, i: ImplPolarity) -> hir::ImplPolarity { - match i { - ImplPolarity::Positive => hir::ImplPolarity::Positive, - ImplPolarity::Negative => hir::ImplPolarity::Negative, + fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity { + match i { + ImplPolarity::Positive => hir::ImplPolarity::Positive, + ImplPolarity::Negative => hir::ImplPolarity::Negative, + } } -} -fn lower_trait_bound_modifier(_lctx: &mut LoweringContext, - f: TraitBoundModifier) - -> hir::TraitBoundModifier { - match f { - TraitBoundModifier::None => hir::TraitBoundModifier::None, - TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe, + fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier { + match f { + TraitBoundModifier::None => hir::TraitBoundModifier::None, + TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe, + } } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 66b1b28a0e505..492d36cfb31a5 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -37,7 +37,7 @@ use rustc_typeck as typeck; use rustc_privacy; use rustc_plugin::registry::Registry; use rustc_plugin as plugin; -use rustc::hir::lowering::{lower_crate, LoweringContext}; +use rustc::hir::lowering::LoweringContext; use rustc_passes::{no_asm, loops, consts, rvalues, static_recursion}; use rustc_const_eval::check_match; use super::Compilation; @@ -787,8 +787,8 @@ pub fn lower_and_resolve<'a>(sess: &Session, // Lower ast -> hir. let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { - let mut lcx = LoweringContext::new(sess, Some(krate), &mut resolver); - hir_map::Forest::new(lower_crate(&mut lcx, krate), dep_graph) + let krate = LoweringContext::new(sess, Some(krate), &mut resolver).lower_crate(krate); + hir_map::Forest::new(krate, dep_graph) }); (ty::CrateAnalysis { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index ce525b716ff2c..8c17ef02615fe 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -57,7 +57,7 @@ use rustc_serialize::{Encodable, EncoderHelpers}; #[cfg(test)] use syntax::parse; #[cfg(test)] use syntax::ast::NodeId; #[cfg(test)] use rustc::hir::print as pprust; -#[cfg(test)] use rustc::hir::lowering::{lower_item, LoweringContext, DummyResolver}; +#[cfg(test)] use rustc::hir::lowering::{LoweringContext, DummyResolver}; struct DecodeContext<'a, 'b, 'tcx: 'a> { tcx: &'a TyCtxt<'tcx>, @@ -1347,7 +1347,7 @@ fn roundtrip(in_item: hir::Item) { fn test_basic() { let cx = mk_ctxt(); with_testing_context(|lcx| { - roundtrip(lower_item(lcx, "e_item!(&cx, + roundtrip(lcx.lower_item("e_item!(&cx, fn foo() {} ).unwrap())); }); @@ -1357,7 +1357,7 @@ fn test_basic() { fn test_smalltalk() { let cx = mk_ctxt(); with_testing_context(|lcx| { - roundtrip(lower_item(lcx, "e_item!(&cx, + roundtrip(lcx.lower_item("e_item!(&cx, fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed. ).unwrap())); }); @@ -1367,7 +1367,7 @@ fn test_smalltalk() { fn test_more() { let cx = mk_ctxt(); with_testing_context(|lcx| { - roundtrip(lower_item(lcx, "e_item!(&cx, + roundtrip(lcx.lower_item("e_item!(&cx, fn foo(x: usize, y: usize) -> usize { let z = x + y; return z; @@ -1387,10 +1387,10 @@ fn test_simplification() { ).unwrap(); let cx = mk_ctxt(); with_testing_context(|lcx| { - let hir_item = lower_item(lcx, &item); + let hir_item = lcx.lower_item(&item); let item_in = InlinedItemRef::Item(&hir_item); let item_out = simplify_ast(item_in); - let item_exp = InlinedItem::Item(P(lower_item(lcx, "e_item!(&cx, + let item_exp = InlinedItem::Item(P(lcx.lower_item("e_item!(&cx, fn new_int_alist() -> alist { return alist {eq_fn: eq_int, data: Vec::new()}; } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 0f518900ea787..d4c08552edfc3 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -28,7 +28,7 @@ use rustc::hir::map as hir_map; use rustc::session::{self, config}; use rustc::session::config::{get_unstable_features_setting, OutputType}; use rustc::session::search_paths::{SearchPaths, PathKind}; -use rustc::hir::lowering::{lower_crate, LoweringContext, DummyResolver}; +use rustc::hir::lowering::{LoweringContext, DummyResolver}; use rustc_back::dynamic_lib::DynamicLibrary; use rustc_back::tempdir::TempDir; use rustc_driver::{driver, Compilation}; @@ -98,8 +98,7 @@ pub fn run(input: &str, let defs = &RefCell::new(hir_map::collect_definitions(&krate)); let mut dummy_resolver = DummyResolver; - let mut lcx = LoweringContext::new(&sess, Some(&krate), &mut dummy_resolver); - let krate = lower_crate(&mut lcx, &krate); + let krate = LoweringContext::new(&sess, Some(&krate), &mut dummy_resolver).lower_crate(&krate); let opts = scrape_test_config(&krate); From 3927ff4fecea17f56a57c59253afce3acdc89bec Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 10 May 2016 01:15:11 +0000 Subject: [PATCH 08/50] Make the remaining functions in `hir::lowering` methods of `LoweringContext` --- src/librustc/hir/lowering.rs | 794 +++++++++++++++++------------------ 1 file changed, 383 insertions(+), 411 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 0f65c5c64e491..0c7123a570e14 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -965,58 +965,55 @@ impl<'a> LoweringContext<'a> { let inplace_finalize = ["ops", "InPlace", "finalize"]; let make_call = |this: &mut LoweringContext, p, args| { - let path = core_path(this, e.span, p); - let path = expr_path(this, path, None); - expr_call(this, e.span, path, args, None) + let path = this.core_path(e.span, p); + let path = this.expr_path(path, None); + this.expr_call(e.span, path, args, None) }; let mk_stmt_let = |this: &mut LoweringContext, bind, expr| { - stmt_let(this, e.span, false, bind, expr, None) + this.stmt_let(e.span, false, bind, expr, None) }; let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| { - stmt_let(this, e.span, true, bind, expr, None) + this.stmt_let(e.span, true, bind, expr, None) }; // let placer = ; let (s1, placer_binding) = { - let placer_expr = signal_block_expr(self, - hir_vec![], - placer_expr, - e.span, - hir::PopUnstableBlock, - None); + let placer_expr = self.signal_block_expr(hir_vec![], + placer_expr, + e.span, + hir::PopUnstableBlock, + None); mk_stmt_let(self, placer_ident, placer_expr) }; // let mut place = Placer::make_place(placer); let (s2, place_binding) = { - let placer = expr_ident(self, e.span, placer_ident, None, placer_binding); + let placer = self.expr_ident(e.span, placer_ident, None, placer_binding); let call = make_call(self, &make_place, hir_vec![placer]); mk_stmt_let_mut(self, place_ident, call) }; // let p_ptr = Place::pointer(&mut place); let (s3, p_ptr_binding) = { - let agent = expr_ident(self, e.span, place_ident, None, place_binding); - let args = hir_vec![expr_mut_addr_of(self, e.span, agent, None)]; + let agent = self.expr_ident(e.span, place_ident, None, place_binding); + let args = hir_vec![self.expr_mut_addr_of(e.span, agent, None)]; let call = make_call(self, &place_pointer, args); mk_stmt_let(self, p_ptr_ident, call) }; // pop_unsafe!(EXPR)); let pop_unsafe_expr = { - let value_expr = signal_block_expr(self, - hir_vec![], - value_expr, - e.span, - hir::PopUnstableBlock, - None); - signal_block_expr(self, - hir_vec![], - value_expr, - e.span, - hir::PopUnsafeBlock(hir::CompilerGenerated), None) + let value_expr = self.signal_block_expr(hir_vec![], + value_expr, + e.span, + hir::PopUnstableBlock, + None); + self.signal_block_expr(hir_vec![], + value_expr, + e.span, + hir::PopUnsafeBlock(hir::CompilerGenerated), None) }; // push_unsafe!({ @@ -1024,28 +1021,26 @@ impl<'a> LoweringContext<'a> { // InPlace::finalize(place) // }) let expr = { - let ptr = expr_ident(self, e.span, p_ptr_ident, None, p_ptr_binding); + let ptr = self.expr_ident(e.span, p_ptr_ident, None, p_ptr_binding); let call_move_val_init = hir::StmtSemi( make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]), self.next_id()); let call_move_val_init = respan(e.span, call_move_val_init); - let place = expr_ident(self, e.span, place_ident, None, place_binding); + let place = self.expr_ident(e.span, place_ident, None, place_binding); let call = make_call(self, &inplace_finalize, hir_vec![place]); - signal_block_expr(self, - hir_vec![call_move_val_init], - call, - e.span, - hir::PushUnsafeBlock(hir::CompilerGenerated), None) + self.signal_block_expr(hir_vec![call_move_val_init], + call, + e.span, + hir::PushUnsafeBlock(hir::CompilerGenerated), None) }; - return signal_block_expr(self, - hir_vec![s1, s2, s3], - expr, - e.span, - hir::PushUnstableBlock, - e.attrs.clone()); + return self.signal_block_expr(hir_vec![s1, s2, s3], + expr, + e.span, + hir::PushUnstableBlock, + e.attrs.clone()); } ExprKind::Vec(ref exprs) => { @@ -1110,7 +1105,7 @@ impl<'a> LoweringContext<'a> { rules: hir::DefaultBlock, span: span, }); - expr_block(self, blk, None) + self.expr_block(blk, None) } _ => self.lower_expr(els), } @@ -1162,47 +1157,42 @@ impl<'a> LoweringContext<'a> { ast_expr: &Expr, path: &[&str], fields: &[(&str, &P)]) -> P { - let strs = std_path(this, &iter::once(&"ops") + let strs = this.std_path(&iter::once(&"ops") .chain(path) .map(|s| *s) .collect::>()); - let structpath = path_global(ast_expr.span, strs); + let structpath = this.path_global(ast_expr.span, strs); let hir_expr = if fields.len() == 0 { - expr_path(this, - structpath, - ast_expr.attrs.clone()) + this.expr_path(structpath, ast_expr.attrs.clone()) } else { let fields = fields.into_iter().map(|&(s, e)| { let expr = this.lower_expr(&e); - let signal_block = signal_block_expr(this, - hir_vec![], - expr, - e.span, - hir::PopUnstableBlock, - None); - field(token::intern(s), signal_block, ast_expr.span) + let signal_block = this.signal_block_expr(hir_vec![], + expr, + e.span, + hir::PopUnstableBlock, + None); + this.field(token::intern(s), signal_block, ast_expr.span) }).collect(); let attrs = ast_expr.attrs.clone(); - expr_struct(this, ast_expr.span, structpath, fields, None, attrs) + this.expr_struct(ast_expr.span, structpath, fields, None, attrs) }; - signal_block_expr(this, - hir_vec![], - hir_expr, - ast_expr.span, - hir::PushUnstableBlock, - None) + this.signal_block_expr(hir_vec![], + hir_expr, + ast_expr.span, + hir::PushUnstableBlock, + None) } use syntax::ast::RangeLimits::*; return match (e1, e2, lims) { (&None, &None, HalfOpen) => - make_struct(self, e, &["RangeFull"], - &[]), + make_struct(self, e, &["RangeFull"], &[]), (&Some(ref e1), &None, HalfOpen) => make_struct(self, e, &["RangeFrom"], @@ -1303,8 +1293,9 @@ impl<'a> LoweringContext<'a> { // ` => ` let pat_arm = { let body = self.lower_block(body); - let body_expr = expr_block(self, body, None); - arm(hir_vec![self.lower_pat(pat)], body_expr) + let body_expr = self.expr_block(body, None); + let pat = self.lower_pat(pat); + self.arm(hir_vec![pat], body_expr) }; // `[_ if => ,]` @@ -1317,12 +1308,12 @@ impl<'a> LoweringContext<'a> { match els.node { // else if hir::ExprIf(cond, then, else_opt) => { - let pat_under = pat_wild(self, e.span); + let pat_under = self.pat_wild(e.span); arms.push(hir::Arm { attrs: hir_vec![], pats: hir_vec![pat_under], guard: Some(cond), - body: expr_block(self, then, None), + body: self.expr_block(then, None), }); else_opt.map(|else_opt| (else_opt, true)) } @@ -1351,11 +1342,10 @@ impl<'a> LoweringContext<'a> { // `_ => [ | ()]` let else_arm = { - let pat_under = pat_wild(self, e.span); + let pat_under = self.pat_wild(e.span); let else_expr = - else_opt.unwrap_or_else( - || expr_tuple(self, e.span, hir_vec![], None)); - arm(hir_vec![pat_under], else_expr) + else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![], None)); + self.arm(hir_vec![pat_under], else_expr) }; let mut arms = Vec::with_capacity(else_if_arms.len() + 2); @@ -1365,14 +1355,13 @@ impl<'a> LoweringContext<'a> { let sub_expr = self.lower_expr(sub_expr); // add attributes to the outer returned expr node - return expr(self, - e.span, - hir::ExprMatch(sub_expr, - arms.into(), - hir::MatchSource::IfLetDesugar { - contains_else_clause: contains_else_clause, - }), - e.attrs.clone()); + return self.expr(e.span, + hir::ExprMatch(sub_expr, + arms.into(), + hir::MatchSource::IfLetDesugar { + contains_else_clause: contains_else_clause, + }), + e.attrs.clone()); } // Desugar ExprWhileLet @@ -1390,29 +1379,29 @@ impl<'a> LoweringContext<'a> { // ` => ` let pat_arm = { let body = self.lower_block(body); - let body_expr = expr_block(self, body, None); - arm(hir_vec![self.lower_pat(pat)], body_expr) + let body_expr = self.expr_block(body, None); + let pat = self.lower_pat(pat); + self.arm(hir_vec![pat], body_expr) }; // `_ => break` let break_arm = { - let pat_under = pat_wild(self, e.span); - let break_expr = expr_break(self, e.span, None); - arm(hir_vec![pat_under], break_expr) + let pat_under = self.pat_wild(e.span); + let break_expr = self.expr_break(e.span, None); + self.arm(hir_vec![pat_under], break_expr) }; // `match { ... }` let arms = hir_vec![pat_arm, break_arm]; let sub_expr = self.lower_expr(sub_expr); - let match_expr = expr(self, - e.span, - hir::ExprMatch(sub_expr, - arms, - hir::MatchSource::WhileLetDesugar), - None); + let match_expr = self.expr(e.span, + hir::ExprMatch(sub_expr, + arms, + hir::MatchSource::WhileLetDesugar), + None); // `[opt_ident]: loop { ... }` - let loop_block = block_expr(self, match_expr); + let loop_block = self.block_expr(match_expr); let loop_expr = hir::ExprLoop(loop_block, opt_ident.map(|ident| self.lower_ident(ident))); // add attributes to the outer returned expr node @@ -1455,84 +1444,81 @@ impl<'a> LoweringContext<'a> { attrs: None, }); let pat = self.lower_pat(pat); - let some_pat = pat_some(self, e.span, pat); + let some_pat = self.pat_some(e.span, pat); - arm(hir_vec![some_pat], body_expr) + self.arm(hir_vec![some_pat], body_expr) }; // `::std::option::Option::None => break` let break_arm = { - let break_expr = expr_break(self, e.span, None); - - arm(hir_vec![pat_none(self, e.span)], break_expr) + let break_expr = self.expr_break(e.span, None); + let pat = self.pat_none(e.span); + self.arm(hir_vec![pat], break_expr) }; // `mut iter` - let iter_pat = pat_ident_binding_mode(self, e.span, iter, - hir::BindByValue(hir::MutMutable)); + let iter_pat = self.pat_ident_binding_mode(e.span, iter, + hir::BindByValue(hir::MutMutable)); // `match ::std::iter::Iterator::next(&mut iter) { ... }` let match_expr = { let next_path = { - let strs = std_path(self, &["iter", "Iterator", "next"]); + let strs = self.std_path(&["iter", "Iterator", "next"]); - path_global(e.span, strs) + self.path_global(e.span, strs) }; - let iter = expr_ident(self, e.span, iter, None, iter_pat.id); - let ref_mut_iter = expr_mut_addr_of(self, e.span, iter, None); - let next_path = expr_path(self, next_path, None); - let next_expr = expr_call(self, - e.span, - next_path, - hir_vec![ref_mut_iter], - None); + let iter = self.expr_ident(e.span, iter, None, iter_pat.id); + let ref_mut_iter = self.expr_mut_addr_of(e.span, iter, None); + let next_path = self.expr_path(next_path, None); + let next_expr = self.expr_call(e.span, + next_path, + hir_vec![ref_mut_iter], + None); let arms = hir_vec![pat_arm, break_arm]; - expr(self, - e.span, - hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar), - None) + self.expr(e.span, + hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar), + None) }; // `[opt_ident]: loop { ... }` - let loop_block = block_expr(self, match_expr); + let loop_block = self.block_expr(match_expr); let loop_expr = hir::ExprLoop(loop_block, opt_ident.map(|ident| self.lower_ident(ident))); let loop_expr = P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None }); // `mut iter => { ... }` - let iter_arm = arm(hir_vec![iter_pat], loop_expr); + let iter_arm = self.arm(hir_vec![iter_pat], loop_expr); // `match ::std::iter::IntoIterator::into_iter() { ... }` let into_iter_expr = { let into_iter_path = { - let strs = std_path(self, &["iter", "IntoIterator", "into_iter"]); + let strs = self.std_path(&["iter", "IntoIterator", "into_iter"]); - path_global(e.span, strs) + self.path_global(e.span, strs) }; - let into_iter = expr_path(self, into_iter_path, None); - expr_call(self, e.span, into_iter, hir_vec![head], None) + let into_iter = self.expr_path(into_iter_path, None); + self.expr_call(e.span, into_iter, hir_vec![head], None) }; - let match_expr = expr_match(self, - e.span, - into_iter_expr, - hir_vec![iter_arm], - hir::MatchSource::ForLoopDesugar, - None); + let match_expr = self.expr_match(e.span, + into_iter_expr, + hir_vec![iter_arm], + hir::MatchSource::ForLoopDesugar, + None); // `{ let _result = ...; _result }` // underscore prevents an unused_variables lint if the head diverges let result_ident = self.str_to_ident("_result"); let (let_stmt, let_stmt_binding) = - stmt_let(self, e.span, false, result_ident, match_expr, None); + self.stmt_let(e.span, false, result_ident, match_expr, None); - let result = expr_ident(self, e.span, result_ident, None, let_stmt_binding); - let block = block_all(self, e.span, hir_vec![let_stmt], Some(result)); + let result = self.expr_ident(e.span, result_ident, None, let_stmt_binding); + let block = self.block_all(e.span, hir_vec![let_stmt], Some(result)); // add the attributes to the outer returned expr node - return expr_block(self, block, e.attrs.clone()); + return self.expr_block(block, e.attrs.clone()); } // Desugar ExprKind::Try @@ -1555,40 +1541,40 @@ impl<'a> LoweringContext<'a> { // Ok(val) => val let ok_arm = { let val_ident = self.str_to_ident("val"); - let val_pat = pat_ident(self, e.span, val_ident); - let val_expr = expr_ident(self, e.span, val_ident, None, val_pat.id); - let ok_pat = pat_ok(self, e.span, val_pat); + let val_pat = self.pat_ident(e.span, val_ident); + let val_expr = self.expr_ident(e.span, val_ident, None, val_pat.id); + let ok_pat = self.pat_ok(e.span, val_pat); - arm(hir_vec![ok_pat], val_expr) + self.arm(hir_vec![ok_pat], val_expr) }; // Err(err) => return Err(From::from(err)) let err_arm = { let err_ident = self.str_to_ident("err"); - let err_local = pat_ident(self, e.span, err_ident); + let err_local = self.pat_ident(e.span, err_ident); let from_expr = { - let path = std_path(self, &["convert", "From", "from"]); - let path = path_global(e.span, path); - let from = expr_path(self, path, None); - let err_expr = expr_ident(self, e.span, err_ident, None, err_local.id); + let path = self.std_path(&["convert", "From", "from"]); + let path = self.path_global(e.span, path); + let from = self.expr_path(path, None); + let err_expr = self.expr_ident(e.span, err_ident, None, err_local.id); - expr_call(self, e.span, from, hir_vec![err_expr], None) + self.expr_call(e.span, from, hir_vec![err_expr], None) }; let err_expr = { - let path = std_path(self, &["result", "Result", "Err"]); - let path = path_global(e.span, path); - let err_ctor = expr_path(self, path, None); - expr_call(self, e.span, err_ctor, hir_vec![from_expr], None) + let path = self.std_path(&["result", "Result", "Err"]); + let path = self.path_global(e.span, path); + let err_ctor = self.expr_path(path, None); + self.expr_call(e.span, err_ctor, hir_vec![from_expr], None) }; - let err_pat = pat_err(self, e.span, err_local); - let ret_expr = expr(self, e.span, - hir::Expr_::ExprRet(Some(err_expr)), None); + let err_pat = self.pat_err(e.span, err_local); + let ret_expr = self.expr(e.span, + hir::Expr_::ExprRet(Some(err_expr)), None); - arm(hir_vec![err_pat], ret_expr) + self.arm(hir_vec![err_pat], ret_expr) }; - return expr_match(self, e.span, sub_expr, hir_vec![err_arm, ok_arm], - hir::MatchSource::TryDesugar, None); + return self.expr_match(e.span, sub_expr, hir_vec![err_arm, ok_arm], + hir::MatchSource::TryDesugar, None); } ExprKind::Mac(_) => panic!("Shouldn't exist here"), @@ -1680,310 +1666,296 @@ impl<'a> LoweringContext<'a> { TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe, } } -} -// Helper methods for building HIR. + // Helper methods for building HIR. -fn arm(pats: hir::HirVec>, expr: P) -> hir::Arm { - hir::Arm { - attrs: hir_vec![], - pats: pats, - guard: None, - body: expr, + fn arm(&mut self, pats: hir::HirVec>, expr: P) -> hir::Arm { + hir::Arm { + attrs: hir_vec![], + pats: pats, + guard: None, + body: expr, + } } -} -fn field(name: Name, expr: P, span: Span) -> hir::Field { - hir::Field { - name: Spanned { - node: name, + fn field(&mut self, name: Name, expr: P, span: Span) -> hir::Field { + hir::Field { + name: Spanned { + node: name, + span: span, + }, span: span, - }, - span: span, - expr: expr, + expr: expr, + } } -} -fn expr_break(lctx: &mut LoweringContext, span: Span, - attrs: ThinAttributes) -> P { - expr(lctx, span, hir::ExprBreak(None), attrs) -} + fn expr_break(&mut self, span: Span, attrs: ThinAttributes) -> P { + self.expr(span, hir::ExprBreak(None), attrs) + } -fn expr_call(lctx: &mut LoweringContext, - span: Span, - e: P, - args: hir::HirVec>, - attrs: ThinAttributes) - -> P { - expr(lctx, span, hir::ExprCall(e, args), attrs) -} + fn expr_call(&mut self, + span: Span, + e: P, + args: hir::HirVec>, + attrs: ThinAttributes) + -> P { + self.expr(span, hir::ExprCall(e, args), attrs) + } -fn expr_ident(lctx: &mut LoweringContext, span: Span, id: hir::Ident, - attrs: ThinAttributes, binding: NodeId) -> P { - let expr = expr(lctx, span, hir::ExprPath(None, path_ident(span, id)), attrs); + fn expr_ident(&mut self, span: Span, id: hir::Ident, attrs: ThinAttributes, binding: NodeId) + -> P { + let expr_path = hir::ExprPath(None, self.path_ident(span, id)); + let expr = self.expr(span, expr_path, attrs); - let def = lctx.resolver.definitions().map(|defs| { - Def::Local(defs.local_def_id(binding), binding) - }).unwrap_or(Def::Err); - lctx.resolver.record_resolution(expr.id, def); + let def = self.resolver.definitions().map(|defs| { + Def::Local(defs.local_def_id(binding), binding) + }).unwrap_or(Def::Err); + self.resolver.record_resolution(expr.id, def); - expr -} + expr + } -fn expr_mut_addr_of(lctx: &mut LoweringContext, span: Span, e: P, - attrs: ThinAttributes) -> P { - expr(lctx, span, hir::ExprAddrOf(hir::MutMutable, e), attrs) -} + fn expr_mut_addr_of(&mut self, span: Span, e: P, attrs: ThinAttributes) + -> P { + self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), attrs) + } -fn expr_path(lctx: &mut LoweringContext, path: hir::Path, - attrs: ThinAttributes) -> P { - let def = lctx.resolver.resolve_generated_global_path(&path, true); - let expr = expr(lctx, path.span, hir::ExprPath(None, path), attrs); - lctx.resolver.record_resolution(expr.id, def); - expr -} + fn expr_path(&mut self, path: hir::Path, attrs: ThinAttributes) -> P { + let def = self.resolver.resolve_generated_global_path(&path, true); + let expr = self.expr(path.span, hir::ExprPath(None, path), attrs); + self.resolver.record_resolution(expr.id, def); + expr + } -fn expr_match(lctx: &mut LoweringContext, - span: Span, - arg: P, - arms: hir::HirVec, - source: hir::MatchSource, - attrs: ThinAttributes) - -> P { - expr(lctx, span, hir::ExprMatch(arg, arms, source), attrs) -} + fn expr_match(&mut self, + span: Span, + arg: P, + arms: hir::HirVec, + source: hir::MatchSource, + attrs: ThinAttributes) + -> P { + self.expr(span, hir::ExprMatch(arg, arms, source), attrs) + } -fn expr_block(lctx: &mut LoweringContext, b: P, - attrs: ThinAttributes) -> P { - expr(lctx, b.span, hir::ExprBlock(b), attrs) -} + fn expr_block(&mut self, b: P, attrs: ThinAttributes) -> P { + self.expr(b.span, hir::ExprBlock(b), attrs) + } -fn expr_tuple(lctx: &mut LoweringContext, sp: Span, exprs: hir::HirVec>, - attrs: ThinAttributes) -> P { - expr(lctx, sp, hir::ExprTup(exprs), attrs) -} + fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec>, attrs: ThinAttributes) + -> P { + self.expr(sp, hir::ExprTup(exprs), attrs) + } -fn expr_struct(lctx: &mut LoweringContext, - sp: Span, - path: hir::Path, - fields: hir::HirVec, - e: Option>, - attrs: ThinAttributes) -> P { - let def = lctx.resolver.resolve_generated_global_path(&path, false); - let expr = expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs); - lctx.resolver.record_resolution(expr.id, def); - expr + fn expr_struct(&mut self, + sp: Span, + path: hir::Path, + fields: hir::HirVec, + e: Option>, + attrs: ThinAttributes) -> P { + let def = self.resolver.resolve_generated_global_path(&path, false); + let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs); + self.resolver.record_resolution(expr.id, def); + expr + } -} + fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinAttributes) -> P { + P(hir::Expr { + id: self.next_id(), + node: node, + span: span, + attrs: attrs, + }) + } -fn expr(lctx: &mut LoweringContext, span: Span, node: hir::Expr_, - attrs: ThinAttributes) -> P { - P(hir::Expr { - id: lctx.next_id(), - node: node, - span: span, - attrs: attrs, - }) -} + fn stmt_let(&mut self, + sp: Span, + mutbl: bool, + ident: hir::Ident, + ex: P, + attrs: ThinAttributes) + -> (hir::Stmt, NodeId) { + let pat = if mutbl { + self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable)) + } else { + self.pat_ident(sp, ident) + }; + let pat_id = pat.id; + let local = P(hir::Local { + pat: pat, + ty: None, + init: Some(ex), + id: self.next_id(), + span: sp, + attrs: attrs, + }); + let decl = respan(sp, hir::DeclLocal(local)); + (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id) + } -fn stmt_let(lctx: &mut LoweringContext, - sp: Span, - mutbl: bool, - ident: hir::Ident, - ex: P, - attrs: ThinAttributes) - -> (hir::Stmt, NodeId) { - let pat = if mutbl { - pat_ident_binding_mode(lctx, sp, ident, hir::BindByValue(hir::MutMutable)) - } else { - pat_ident(lctx, sp, ident) - }; - let pat_id = pat.id; - let local = P(hir::Local { - pat: pat, - ty: None, - init: Some(ex), - id: lctx.next_id(), - span: sp, - attrs: attrs, - }); - let decl = respan(sp, hir::DeclLocal(local)); - (respan(sp, hir::StmtDecl(P(decl), lctx.next_id())), pat_id) -} + fn block_expr(&mut self, expr: P) -> P { + self.block_all(expr.span, hir::HirVec::new(), Some(expr)) + } -fn block_expr(lctx: &mut LoweringContext, expr: P) -> P { - block_all(lctx, expr.span, hir::HirVec::new(), Some(expr)) -} + fn block_all(&mut self, span: Span, stmts: hir::HirVec, expr: Option>) + -> P { + P(hir::Block { + stmts: stmts, + expr: expr, + id: self.next_id(), + rules: hir::DefaultBlock, + span: span, + }) + } -fn block_all(lctx: &mut LoweringContext, - span: Span, - stmts: hir::HirVec, - expr: Option>) - -> P { - P(hir::Block { - stmts: stmts, - expr: expr, - id: lctx.next_id(), - rules: hir::DefaultBlock, - span: span, - }) -} + fn pat_ok(&mut self, span: Span, pat: P) -> P { + let ok = self.std_path(&["result", "Result", "Ok"]); + let path = self.path_global(span, ok); + self.pat_enum(span, path, hir_vec![pat]) + } -fn pat_ok(lctx: &mut LoweringContext, span: Span, pat: P) -> P { - let ok = std_path(lctx, &["result", "Result", "Ok"]); - let path = path_global(span, ok); - pat_enum(lctx, span, path, hir_vec![pat]) -} + fn pat_err(&mut self, span: Span, pat: P) -> P { + let err = self.std_path(&["result", "Result", "Err"]); + let path = self.path_global(span, err); + self.pat_enum(span, path, hir_vec![pat]) + } -fn pat_err(lctx: &mut LoweringContext, span: Span, pat: P) -> P { - let err = std_path(lctx, &["result", "Result", "Err"]); - let path = path_global(span, err); - pat_enum(lctx, span, path, hir_vec![pat]) -} + fn pat_some(&mut self, span: Span, pat: P) -> P { + let some = self.std_path(&["option", "Option", "Some"]); + let path = self.path_global(span, some); + self.pat_enum(span, path, hir_vec![pat]) + } -fn pat_some(lctx: &mut LoweringContext, span: Span, pat: P) -> P { - let some = std_path(lctx, &["option", "Option", "Some"]); - let path = path_global(span, some); - pat_enum(lctx, span, path, hir_vec![pat]) -} + fn pat_none(&mut self, span: Span) -> P { + let none = self.std_path(&["option", "Option", "None"]); + let path = self.path_global(span, none); + self.pat_enum(span, path, hir_vec![]) + } -fn pat_none(lctx: &mut LoweringContext, span: Span) -> P { - let none = std_path(lctx, &["option", "Option", "None"]); - let path = path_global(span, none); - pat_enum(lctx, span, path, hir_vec![]) -} + fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec>) + -> P { + let def = self.resolver.resolve_generated_global_path(&path, true); + let pt = if subpats.is_empty() { + hir::PatKind::Path(path) + } else { + hir::PatKind::TupleStruct(path, Some(subpats)) + }; + let pat = self.pat(span, pt); + self.resolver.record_resolution(pat.id, def); + pat + } -fn pat_enum(lctx: &mut LoweringContext, - span: Span, - path: hir::Path, - subpats: hir::HirVec>) - -> P { - let def = lctx.resolver.resolve_generated_global_path(&path, true); - let pt = if subpats.is_empty() { - hir::PatKind::Path(path) - } else { - hir::PatKind::TupleStruct(path, Some(subpats)) - }; - let pat = pat(lctx, span, pt); - lctx.resolver.record_resolution(pat.id, def); - pat -} + fn pat_ident(&mut self, span: Span, ident: hir::Ident) -> P { + self.pat_ident_binding_mode(span, ident, hir::BindByValue(hir::MutImmutable)) + } -fn pat_ident(lctx: &mut LoweringContext, span: Span, ident: hir::Ident) -> P { - pat_ident_binding_mode(lctx, span, ident, hir::BindByValue(hir::MutImmutable)) -} + fn pat_ident_binding_mode(&mut self, span: Span, ident: hir::Ident, bm: hir::BindingMode) + -> P { + let pat_ident = hir::PatKind::Ident(bm, + Spanned { + span: span, + node: ident, + }, + None); -fn pat_ident_binding_mode(lctx: &mut LoweringContext, - span: Span, - ident: hir::Ident, - bm: hir::BindingMode) - -> P { - let pat_ident = hir::PatKind::Ident(bm, - Spanned { - span: span, - node: ident, - }, - None); - - let pat = pat(lctx, span, pat_ident); - - let parent_def = lctx.parent_def; - let def = lctx.resolver.definitions().map(|defs| { - let def_path_data = DefPathData::Binding(ident.name); - let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data); - Def::Local(DefId::local(def_index), pat.id) - }).unwrap_or(Def::Err); - lctx.resolver.record_resolution(pat.id, def); - - pat -} + let pat = self.pat(span, pat_ident); -fn pat_wild(lctx: &mut LoweringContext, span: Span) -> P { - pat(lctx, span, hir::PatKind::Wild) -} + let parent_def = self.parent_def; + let def = self.resolver.definitions().map(|defs| { + let def_path_data = DefPathData::Binding(ident.name); + let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data); + Def::Local(DefId::local(def_index), pat.id) + }).unwrap_or(Def::Err); + self.resolver.record_resolution(pat.id, def); -fn pat(lctx: &mut LoweringContext, span: Span, pat: hir::PatKind) -> P { - P(hir::Pat { - id: lctx.next_id(), - node: pat, - span: span, - }) -} + pat + } -fn path_ident(span: Span, id: hir::Ident) -> hir::Path { - path(span, vec![id]) -} + fn pat_wild(&mut self, span: Span) -> P { + self.pat(span, hir::PatKind::Wild) + } -fn path(span: Span, strs: Vec) -> hir::Path { - path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) -} + fn pat(&mut self, span: Span, pat: hir::PatKind) -> P { + P(hir::Pat { + id: self.next_id(), + node: pat, + span: span, + }) + } -fn path_global(span: Span, strs: Vec) -> hir::Path { - path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) -} + fn path_ident(&mut self, span: Span, id: hir::Ident) -> hir::Path { + self.path(span, vec![id]) + } -fn path_all(sp: Span, - global: bool, - mut idents: Vec, - lifetimes: hir::HirVec, - types: hir::HirVec>, - bindings: hir::HirVec) - -> hir::Path { - let last_identifier = idents.pop().unwrap(); - let mut segments: Vec = idents.into_iter() - .map(|ident| { - hir::PathSegment { - identifier: ident, - parameters: hir::PathParameters::none(), - } - }) - .collect(); - segments.push(hir::PathSegment { - identifier: last_identifier, - parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { - lifetimes: lifetimes, - types: types, - bindings: bindings, - }), - }); - hir::Path { - span: sp, - global: global, - segments: segments.into(), + fn path(&mut self, span: Span, strs: Vec) -> hir::Path { + self.path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) } -} -fn std_path(lctx: &mut LoweringContext, components: &[&str]) -> Vec { - let mut v = Vec::new(); - if let Some(s) = lctx.crate_root { - v.push(hir::Ident::from_name(token::intern(s))); + fn path_global(&mut self, span: Span, strs: Vec) -> hir::Path { + self.path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) } - v.extend(components.iter().map(|s| hir::Ident::from_name(token::intern(s)))); - return v; -} -// Given suffix ["b","c","d"], returns path `::std::b::c::d` when -// `fld.cx.use_std`, and `::core::b::c::d` otherwise. -fn core_path(lctx: &mut LoweringContext, span: Span, components: &[&str]) -> hir::Path { - let idents = std_path(lctx, components); - path_global(span, idents) -} + fn path_all(&mut self, + sp: Span, + global: bool, + mut idents: Vec, + lifetimes: hir::HirVec, + types: hir::HirVec>, + bindings: hir::HirVec) + -> hir::Path { + let last_identifier = idents.pop().unwrap(); + let mut segments: Vec = idents.into_iter().map(|ident| { + hir::PathSegment { + identifier: ident, + parameters: hir::PathParameters::none(), + } + }).collect(); -fn signal_block_expr(lctx: &mut LoweringContext, - stmts: hir::HirVec, - expr: P, - span: Span, - rule: hir::BlockCheckMode, - attrs: ThinAttributes) - -> P { - let id = lctx.next_id(); - expr_block(lctx, - P(hir::Block { - rules: rule, - span: span, - id: id, - stmts: stmts, - expr: Some(expr), - }), - attrs) + segments.push(hir::PathSegment { + identifier: last_identifier, + parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { + lifetimes: lifetimes, + types: types, + bindings: bindings, + }), + }); + hir::Path { + span: sp, + global: global, + segments: segments.into(), + } + } + + fn std_path(&mut self, components: &[&str]) -> Vec { + let mut v = Vec::new(); + if let Some(s) = self.crate_root { + v.push(hir::Ident::from_name(token::intern(s))); + } + v.extend(components.iter().map(|s| hir::Ident::from_name(token::intern(s)))); + return v; + } + + // Given suffix ["b","c","d"], returns path `::std::b::c::d` when + // `fld.cx.use_std`, and `::core::b::c::d` otherwise. + fn core_path(&mut self, span: Span, components: &[&str]) -> hir::Path { + let idents = self.std_path(components); + self.path_global(span, idents) + } + + fn signal_block_expr(&mut self, + stmts: hir::HirVec, + expr: P, + span: Span, + rule: hir::BlockCheckMode, + attrs: ThinAttributes) + -> P { + let id = self.next_id(); + let block = P(hir::Block { + rules: rule, + span: span, + id: id, + stmts: stmts, + expr: Some(expr), + }); + self.expr_block(block, attrs) + } } From 33978b0728640f3345479bd3fc0055a36507cf32 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 10 May 2016 05:29:13 +0000 Subject: [PATCH 09/50] Refactor `hir::lowering` API --- src/librustc/hir/lowering.rs | 35 ++++++++++++++++-------------- src/librustc_driver/driver.rs | 5 ++--- src/librustc_metadata/astencode.rs | 2 +- src/librustdoc/test.rs | 4 ++-- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 0c7123a570e14..5ca99a7db67f5 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -91,30 +91,33 @@ impl Resolver for DummyResolver { } } -impl<'a> LoweringContext<'a> { - pub fn new(id_assigner: &'a NodeIdAssigner, - c: Option<&Crate>, - resolver: &'a mut Resolver) - -> LoweringContext<'a> { - let crate_root = c.and_then(|c| { - if std_inject::no_core(c) { - None - } else if std_inject::no_std(c) { - Some("core") - } else { - Some("std") - } - }); +pub fn lower_crate(krate: &Crate, id_assigner: &NodeIdAssigner, resolver: &mut Resolver) + -> hir::Crate { + LoweringContext { + crate_root: if std_inject::no_core(krate) { + None + } else if std_inject::no_std(krate) { + Some("core") + } else { + Some("std") + }, + id_assigner: id_assigner, + parent_def: None, + resolver: resolver, + }.lower_crate(krate) +} +impl<'a> LoweringContext<'a> { + pub fn testing_context(id_assigner: &'a NodeIdAssigner, resolver: &'a mut Resolver) -> Self { LoweringContext { - crate_root: crate_root, + crate_root: None, id_assigner: id_assigner, parent_def: None, resolver: resolver, } } - pub fn lower_crate(&mut self, c: &Crate) -> hir::Crate { + fn lower_crate(&mut self, c: &Crate) -> hir::Crate { struct ItemLowerer<'lcx, 'interner: 'lcx> { items: BTreeMap, lctx: &'lcx mut LoweringContext<'interner>, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 492d36cfb31a5..01e2b410c1b24 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -37,7 +37,7 @@ use rustc_typeck as typeck; use rustc_privacy; use rustc_plugin::registry::Registry; use rustc_plugin as plugin; -use rustc::hir::lowering::LoweringContext; +use rustc::hir::lowering::lower_crate; use rustc_passes::{no_asm, loops, consts, rvalues, static_recursion}; use rustc_const_eval::check_match; use super::Compilation; @@ -787,8 +787,7 @@ pub fn lower_and_resolve<'a>(sess: &Session, // Lower ast -> hir. let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { - let krate = LoweringContext::new(sess, Some(krate), &mut resolver).lower_crate(krate); - hir_map::Forest::new(krate, dep_graph) + hir_map::Forest::new(lower_crate(krate, sess, &mut resolver), dep_graph) }); (ty::CrateAnalysis { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 8c17ef02615fe..2a847c4c19538 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -1329,7 +1329,7 @@ fn mk_ctxt() -> parse::ParseSess { fn with_testing_context T>(f: F) -> T { let assigner = FakeNodeIdAssigner; let mut resolver = DummyResolver; - let mut lcx = LoweringContext::new(&assigner, None, &mut resolver); + let mut lcx = LoweringContext::testing_context(&assigner, &mut resolver); f(&mut lcx) } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index d4c08552edfc3..44c3ded4a115a 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -28,7 +28,7 @@ use rustc::hir::map as hir_map; use rustc::session::{self, config}; use rustc::session::config::{get_unstable_features_setting, OutputType}; use rustc::session::search_paths::{SearchPaths, PathKind}; -use rustc::hir::lowering::{LoweringContext, DummyResolver}; +use rustc::hir::lowering::{lower_crate, DummyResolver}; use rustc_back::dynamic_lib::DynamicLibrary; use rustc_back::tempdir::TempDir; use rustc_driver::{driver, Compilation}; @@ -98,7 +98,7 @@ pub fn run(input: &str, let defs = &RefCell::new(hir_map::collect_definitions(&krate)); let mut dummy_resolver = DummyResolver; - let krate = LoweringContext::new(&sess, Some(&krate), &mut dummy_resolver).lower_crate(&krate); + let krate = lower_crate(&krate, &sess, &mut dummy_resolver); let opts = scrape_test_config(&krate); From 66404f34d255eb7304a6ecf8350589684e62951d Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Tue, 10 May 2016 11:06:30 +0200 Subject: [PATCH 10/50] Simplify text --- src/libcore/sync/atomic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index cf3e45cf3de79..e141a92c3ee3d 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -142,13 +142,13 @@ pub enum Ordering { #[stable(feature = "rust1", since = "1.0.0")] Relaxed, /// When coupled with a store, all previous writes become visible - /// to another thread that performs a load with `Acquire` ordering + /// to the other threads that perform a load with `Acquire` ordering /// on the same value. #[stable(feature = "rust1", since = "1.0.0")] Release, /// When coupled with a load, all subsequent loads will see data /// written before a store with `Release` ordering on the same value - /// in another thread. + /// in other threads. #[stable(feature = "rust1", since = "1.0.0")] Acquire, /// When coupled with a load, uses `Acquire` ordering, and with a store From 9ac468b841cf01e7b575f4c20d10df8096c31f7a Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 May 2016 15:34:25 +0200 Subject: [PATCH 11/50] Store a reference rather than a RefCell in LocalCrateReader. --- src/librustc_driver/driver.rs | 2 +- src/librustc_driver/test.rs | 2 +- src/librustc_metadata/creader.rs | 9 ++++----- src/librustdoc/core.rs | 2 +- src/test/run-make/execution-engine/test.rs | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e72204e5e22de..8841480f7f644 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -148,7 +148,7 @@ pub fn compile_input(sess: &Session, time(sess.time_passes(), "external crate/lib resolution", - || LocalCrateReader::new(sess, &cstore, defs, &expanded_crate, &id) + || LocalCrateReader::new(sess, &cstore, &defs.borrow(), &expanded_crate, &id) .read_crates(&dep_graph)); time(sess.time_passes(), diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 869bbb723ef41..ed9a092b6ff2f 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -121,7 +121,7 @@ fn test_env(source_string: &str, let dep_graph = DepGraph::new(false); let krate = driver::assign_node_ids(&sess, krate); let defs = &RefCell::new(hir_map::collect_definitions(&krate)); - LocalCrateReader::new(&sess, &cstore, defs, &krate, "test_crate").read_crates(&dep_graph); + LocalCrateReader::new(&sess, &cstore, &defs.borrow(), &krate, "test_crate").read_crates(&dep_graph); let _ignore = dep_graph.in_ignore(); let (_, resolutions, mut hir_forest) = { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 190e8552d199a..2b02a745bef74 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -46,7 +46,7 @@ pub struct LocalCrateReader<'a> { cstore: &'a CStore, creader: CrateReader<'a>, krate: &'a ast::Crate, - defintions: &'a RefCell, + defintions: &'a hir_map::Definitions, } pub struct CrateReader<'a> { @@ -843,7 +843,7 @@ impl<'a> CrateReader<'a> { impl<'a> LocalCrateReader<'a> { pub fn new(sess: &'a Session, cstore: &'a CStore, - defs: &'a RefCell, + defs: &'a hir_map::Definitions, krate: &'a ast::Crate, local_crate_name: &str) -> LocalCrateReader<'a> { @@ -902,9 +902,8 @@ impl<'a> LocalCrateReader<'a> { PathKind::Crate, true); - let defs = self.defintions.borrow(); - let def_id = defs.opt_local_def_id(i.id).unwrap(); - let len = defs.def_path(def_id.index).data.len(); + let def_id = self.defintions.opt_local_def_id(i.id).unwrap(); + let len = self.defintions.def_path(def_id.index).data.len(); self.creader.update_extern_crate(cnum, ExternCrate { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e5fc84037ce57..77a780805a695 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -154,7 +154,7 @@ pub fn run_core(search_paths: SearchPaths, let dep_graph = DepGraph::new(false); let defs = &RefCell::new(hir_map::collect_definitions(&krate)); - LocalCrateReader::new(&sess, &cstore, &defs, &krate, &name).read_crates(&dep_graph); + LocalCrateReader::new(&sess, &cstore, &defs.borrow(), &krate, &name).read_crates(&dep_graph); // Lower ast -> hir and resolve. let (analysis, resolutions, mut hir_forest) = { diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index 98412c08df520..f46846c34a5ef 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -241,7 +241,7 @@ fn compile_program(input: &str, sysroot: PathBuf) let dep_graph = DepGraph::new(sess.opts.build_dep_graph()); let krate = driver::assign_node_ids(&sess, krate); let defs = RefCell::new(ast_map::collect_definitions(&krate)); - LocalCrateReader::new(&sess, &cstore, &defs, &krate, &id).read_crates(&dep_graph); + LocalCrateReader::new(&sess, &cstore, &defs.borrow(), &krate, &id).read_crates(&dep_graph); let (analysis, resolutions, mut hir_forest) = { let defs = &mut *defs.borrow_mut(); driver::lower_and_resolve(&sess, &id, defs, &krate, dep_graph, MakeGlobMap::No) From 8d3531d3db513bd71ad1ac041ad9a2172ec34012 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 May 2016 15:36:50 +0200 Subject: [PATCH 12/50] Correct typo in LocalCrateReader::definitions. --- src/librustc_metadata/creader.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 2b02a745bef74..62c208dbcb2a4 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -46,7 +46,7 @@ pub struct LocalCrateReader<'a> { cstore: &'a CStore, creader: CrateReader<'a>, krate: &'a ast::Crate, - defintions: &'a hir_map::Definitions, + definitions: &'a hir_map::Definitions, } pub struct CrateReader<'a> { @@ -852,7 +852,7 @@ impl<'a> LocalCrateReader<'a> { cstore: cstore, creader: CrateReader::new(sess, cstore, local_crate_name), krate: krate, - defintions: defs, + definitions: defs, } } @@ -902,8 +902,8 @@ impl<'a> LocalCrateReader<'a> { PathKind::Crate, true); - let def_id = self.defintions.opt_local_def_id(i.id).unwrap(); - let len = self.defintions.def_path(def_id.index).data.len(); + let def_id = self.definitions.opt_local_def_id(i.id).unwrap(); + let len = self.definitions.def_path(def_id.index).data.len(); self.creader.update_extern_crate(cnum, ExternCrate { From e919f251800b792e15b3c72cdfb19e539cd74971 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 May 2016 15:34:52 +0200 Subject: [PATCH 13/50] Delay wrapping Definitions into a RefCell around LocalCrateReader. --- src/librustc_driver/driver.rs | 13 +++++++------ src/librustc_driver/test.rs | 9 +++++---- src/librustdoc/core.rs | 9 +++++---- src/test/run-make/execution-engine/test.rs | 11 ++++++----- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 8841480f7f644..3f9fa0a23c2d8 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -142,13 +142,13 @@ pub fn compile_input(sess: &Session, let dep_graph = DepGraph::new(sess.opts.build_dep_graph()); // Collect defintions for def ids. - let defs = &RefCell::new(time(sess.time_passes(), - "collecting defs", - || hir_map::collect_definitions(&expanded_crate))); + let mut defs = time(sess.time_passes(), + "collecting defs", + || hir_map::collect_definitions(&expanded_crate)); time(sess.time_passes(), "external crate/lib resolution", - || LocalCrateReader::new(sess, &cstore, &defs.borrow(), &expanded_crate, &id) + || LocalCrateReader::new(sess, &cstore, &defs, &expanded_crate, &id) .read_crates(&dep_graph)); time(sess.time_passes(), @@ -156,8 +156,8 @@ pub fn compile_input(sess: &Session, || lint::check_ast_crate(sess, &expanded_crate)); let (analysis, resolutions, mut hir_forest) = { - let defs = &mut *defs.borrow_mut(); - lower_and_resolve(sess, &id, defs, &expanded_crate, dep_graph, control.make_glob_map) + lower_and_resolve(sess, &id, &mut defs, &expanded_crate, dep_graph, + control.make_glob_map) }; // Discard MTWT tables that aren't required past lowering to HIR. @@ -165,6 +165,7 @@ pub fn compile_input(sess: &Session, syntax::ext::mtwt::clear_tables(); } + let defs = &RefCell::new(defs); let arenas = ty::CtxtArenas::new(); // Construct the HIR map diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index ed9a092b6ff2f..59713c66afcb6 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -120,15 +120,16 @@ fn test_env(source_string: &str, let dep_graph = DepGraph::new(false); let krate = driver::assign_node_ids(&sess, krate); - let defs = &RefCell::new(hir_map::collect_definitions(&krate)); - LocalCrateReader::new(&sess, &cstore, &defs.borrow(), &krate, "test_crate").read_crates(&dep_graph); + let mut defs = hir_map::collect_definitions(&krate); + LocalCrateReader::new(&sess, &cstore, &defs, &krate, "test_crate").read_crates(&dep_graph); let _ignore = dep_graph.in_ignore(); let (_, resolutions, mut hir_forest) = { - let (defs, dep_graph) = (&mut *defs.borrow_mut(), dep_graph.clone()); - driver::lower_and_resolve(&sess, "test-crate", defs, &krate, dep_graph, MakeGlobMap::No) + driver::lower_and_resolve(&sess, "test-crate", &mut defs, &krate, dep_graph.clone(), + MakeGlobMap::No) }; + let defs = &RefCell::new(defs); let arenas = ty::CtxtArenas::new(); let ast_map = hir_map::map_crate(&mut hir_forest, defs); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 77a780805a695..857a1176f496a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -153,15 +153,16 @@ pub fn run_core(search_paths: SearchPaths, let krate = driver::assign_node_ids(&sess, krate); let dep_graph = DepGraph::new(false); - let defs = &RefCell::new(hir_map::collect_definitions(&krate)); - LocalCrateReader::new(&sess, &cstore, &defs.borrow(), &krate, &name).read_crates(&dep_graph); + let mut defs = hir_map::collect_definitions(&krate); + LocalCrateReader::new(&sess, &cstore, &defs, &krate, &name).read_crates(&dep_graph); // Lower ast -> hir and resolve. let (analysis, resolutions, mut hir_forest) = { - let defs = &mut *defs.borrow_mut(); - driver::lower_and_resolve(&sess, &name, defs, &krate, dep_graph, resolve::MakeGlobMap::No) + driver::lower_and_resolve(&sess, &name, &mut defs, &krate, dep_graph, + resolve::MakeGlobMap::No) }; + let defs = &RefCell::new(defs); let arenas = ty::CtxtArenas::new(); let hir_map = hir_map::map_crate(&mut hir_forest, defs); diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index f46846c34a5ef..0d10f31556644 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -240,14 +240,15 @@ fn compile_program(input: &str, sysroot: PathBuf) let dep_graph = DepGraph::new(sess.opts.build_dep_graph()); let krate = driver::assign_node_ids(&sess, krate); - let defs = RefCell::new(ast_map::collect_definitions(&krate)); - LocalCrateReader::new(&sess, &cstore, &defs.borrow(), &krate, &id).read_crates(&dep_graph); + let mut defs = ast_map::collect_definitions(&krate); + LocalCrateReader::new(&sess, &cstore, &defs, &krate, &id).read_crates(&dep_graph); let (analysis, resolutions, mut hir_forest) = { - let defs = &mut *defs.borrow_mut(); - driver::lower_and_resolve(&sess, &id, defs, &krate, dep_graph, MakeGlobMap::No) + driver::lower_and_resolve(&sess, &id, &mut defs, &krate, dep_graph, MakeGlobMap::No) }; + + let defs = &RefCell::new(defs); let arenas = ty::CtxtArenas::new(); - let ast_map = ast_map::map_crate(&mut hir_forest, &defs); + let ast_map = ast_map::map_crate(&mut hir_forest, defs); abort_on_err(driver::phase_3_run_analysis_passes( &sess, ast_map, analysis, resolutions, &arenas, &id, From e5a91b7ba1a22e34c7d09105e7a115e696ffcd0f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 10 May 2016 21:26:34 +0300 Subject: [PATCH 14/50] mir: don't attempt to promote Unpromotable constant temps. --- src/librustc_mir/transform/qualify_consts.rs | 24 +++++++++++++++----- src/test/run-pass/issue-33537.rs | 24 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass/issue-33537.rs diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 90823528973b9..e7693d2691bfd 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -65,13 +65,18 @@ bitflags! { // pointer comparisons, ptr-to-int casts, etc. const NOT_CONST = 1 << 6, + // Refers to temporaries which cannot be promoted as + // promote_consts decided they weren't simple enough. + const NOT_PROMOTABLE = 1 << 7, + // Borrows of temporaries can be promoted only // if they have none of the above qualifications. - const UNPROMOTABLE = !0, + const NEVER_PROMOTE = !0, // Const items can only have MUTABLE_INTERIOR - // without producing an error. - const CONST_ERROR = !Qualif::MUTABLE_INTERIOR.bits + // and NOT_PROMOTABLE without producing an error. + const CONST_ERROR = !Qualif::MUTABLE_INTERIOR.bits & + !Qualif::NOT_PROMOTABLE.bits } } @@ -502,6 +507,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx> { self.add(Qualif::NOT_CONST); } Lvalue::Temp(index) => { + if !self.temp_promotion_state[index as usize].is_promotable() { + self.add(Qualif::NOT_PROMOTABLE); + } + if let Some(qualif) = self.temp_qualif[index as usize] { self.add(qualif); } else { @@ -687,8 +696,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx> { // We might have a candidate for promotion. let candidate = Candidate::Ref(self.location); if self.mode == Mode::Fn || self.mode == Mode::ConstFn { - if !self.qualif.intersects(Qualif::UNPROMOTABLE) { - self.promotion_candidates.push(candidate); + if !self.qualif.intersects(Qualif::NEVER_PROMOTE) { + // We can only promote direct borrows of temps. + if let Lvalue::Temp(_) = *lvalue { + self.promotion_candidates.push(candidate); + } } } } @@ -780,7 +792,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx> { this.visit_operand(arg); if is_shuffle && i == 2 && this.mode == Mode::Fn { let candidate = Candidate::ShuffleIndices(bb); - if !this.qualif.intersects(Qualif::UNPROMOTABLE) { + if !this.qualif.intersects(Qualif::NEVER_PROMOTE) { this.promotion_candidates.push(candidate); } else { span_err!(this.tcx.sess, this.span, E0526, diff --git a/src/test/run-pass/issue-33537.rs b/src/test/run-pass/issue-33537.rs new file mode 100644 index 0000000000000..24f4c9f590b11 --- /dev/null +++ b/src/test/run-pass/issue-33537.rs @@ -0,0 +1,24 @@ +// Copyright 2016 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(const_fn)] + +const fn foo() -> *const i8 { + b"foo" as *const _ as *const i8 +} + +const fn bar() -> i32 { + *&{(1, 2, 3).1} +} + +fn main() { + assert_eq!(foo(), b"foo" as *const _ as *const i8); + assert_eq!(bar(), 2); +} From 85e02429b2ef07e11a40ebf6df28b37bcba528b2 Mon Sep 17 00:00:00 2001 From: Cristian Oliveira Date: Wed, 4 May 2016 00:40:53 -0300 Subject: [PATCH 15/50] Add error description for E0455 - Adding name attribute to the sample code - Fix description sentences --- src/librustc_metadata/diagnostics.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/diagnostics.rs index 8fa23de9a2d16..ae9f500c5de59 100644 --- a/src/librustc_metadata/diagnostics.rs +++ b/src/librustc_metadata/diagnostics.rs @@ -26,6 +26,27 @@ name. Example: ``` "##, +E0455: r##" +Linking with `kind=framework` is only supported when targeting OS X, +as frameworks are specific to that operating system. + +Erroneous code example: + +```compile_fail" +#[link(name = "FooCoreServices", kind = "framework")] extern {} +// OS used to compile is Linux for example +``` + +To solve this error you can use conditional compilation: + +``` +#[cfg_attr(target="macos", link(name = "FooCoreServices", kind = "framework"))] +extern {} +``` + +See more: https://doc.rust-lang.org/book/conditional-compilation.html +"##, + E0458: r##" An unknown "kind" was specified for a link attribute. Erroneous code example: @@ -73,7 +94,6 @@ well, and you link to them the same way. } register_diagnostics! { - E0455, // native frameworks are only available on OSX targets E0456, // plugin `..` is not available for triple `..` E0457, // plugin `..` only found in rlib format, but must be available... E0514, // metadata version mismatch From 7a9f4c22ff974ec68300f68c46df49d3f83329de Mon Sep 17 00:00:00 2001 From: ggomez Date: Tue, 10 May 2016 10:54:29 +0200 Subject: [PATCH 16/50] Add E0500 error explanation --- src/librustc_borrowck/diagnostics.rs | 48 +++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 8d9b88e899be2..2c38bc36dc3d4 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -378,6 +378,53 @@ let c = &i; // still ok! ``` "##, +E0500: r##" +A borrowed variable was used in another closure. Example of erroneous code: + +```compile_fail +fn you_know_nothing(jon_snow: &mut i32) { + let nights_watch = || { + *jon_snow = 2; + }; + let starks = || { + *jon_snow = 3; // error: closure requires unique access to `jon_snow` + // but it is already borrowed + }; +} + +In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it +cannot be borrowed by the `starks` closure at the same time. To fix this issue, +you can put the closure in its own scope: + +``` +fn you_know_nothing(jon_snow: &mut i32) { + { + let nights_watch = || { + *jon_snow = 2; + }; + } // At this point, `jon_snow` is free. + let starks = || { + *jon_snow = 3; + }; +} +``` + +Or, if the type implements the `Clone` trait, you can clone it between +closures: + +``` +fn you_know_nothing(jon_snow: &mut i32) { + let mut jon_copy = jon_snow.clone(); + let nights_watch = || { + jon_copy = 2; + }; + let starks = || { + *jon_snow = 3; + }; +} +``` +"##, + E0501: r##" This error indicates that a mutable variable is being used while it is still captured by a closure. Because the closure has borrowed the variable, it is not @@ -753,7 +800,6 @@ fn main() { register_diagnostics! { E0385, // {} in an aliasable location E0388, // {} in a static location - E0500, // closure requires unique access to `..` but .. is already borrowed E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ... E0503, // cannot use `..` because it was mutably borrowed E0504, // cannot move `..` into closure because it is borrowed From 5511e6568f41b7ca9d57b0055c193be187e437d8 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 May 2016 15:43:51 +0200 Subject: [PATCH 17/50] Hand ownership of the Definitions to map_crate. --- src/librustc/hir/map/mod.rs | 6 +++--- src/librustc_driver/driver.rs | 1 - src/librustc_driver/test.rs | 2 -- src/librustdoc/core.rs | 1 - src/librustdoc/test.rs | 2 +- src/test/run-make/execution-engine/test.rs | 2 -- 6 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 92f8c9249c842..f0eb580cfd57e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -196,7 +196,7 @@ pub struct Map<'ast> { /// plain old integers. map: RefCell>>, - definitions: &'ast RefCell, + definitions: RefCell, } impl<'ast> Map<'ast> { @@ -790,7 +790,7 @@ pub fn collect_definitions<'ast>(krate: &'ast ast::Crate) -> Definitions { } pub fn map_crate<'ast>(forest: &'ast mut Forest, - definitions: &'ast RefCell) + definitions: Definitions) -> Map<'ast> { let mut collector = NodeCollector::root(&forest.krate); intravisit::walk_crate(&mut collector, &forest.krate); @@ -816,7 +816,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, forest: forest, dep_graph: forest.dep_graph.clone(), map: RefCell::new(map), - definitions: definitions, + definitions: RefCell::new(definitions), } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 3f9fa0a23c2d8..a979410ca94de 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -165,7 +165,6 @@ pub fn compile_input(sess: &Session, syntax::ext::mtwt::clear_tables(); } - let defs = &RefCell::new(defs); let arenas = ty::CtxtArenas::new(); // Construct the HIR map diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 59713c66afcb6..270376bda766e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -29,7 +29,6 @@ use rustc_metadata::cstore::CStore; use rustc_metadata::creader::LocalCrateReader; use rustc::hir::map as hir_map; use rustc::session::{self, config}; -use std::cell::RefCell; use std::rc::Rc; use syntax::ast; use syntax::abi::Abi; @@ -129,7 +128,6 @@ fn test_env(source_string: &str, MakeGlobMap::No) }; - let defs = &RefCell::new(defs); let arenas = ty::CtxtArenas::new(); let ast_map = hir_map::map_crate(&mut hir_forest, defs); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 857a1176f496a..e5919a4b35ff6 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -162,7 +162,6 @@ pub fn run_core(search_paths: SearchPaths, resolve::MakeGlobMap::No) }; - let defs = &RefCell::new(defs); let arenas = ty::CtxtArenas::new(); let hir_map = hir_map::map_crate(&mut hir_forest, defs); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index fc548924e2964..c57452b6e2fc3 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -95,7 +95,7 @@ pub fn run(input: &str, .expect("phase_2_configure_and_expand aborted in rustdoc!"); let krate = driver::assign_node_ids(&sess, krate); let dep_graph = DepGraph::new(false); - let defs = &RefCell::new(hir_map::collect_definitions(&krate)); + let defs = hir_map::collect_definitions(&krate); let mut dummy_resolver = DummyResolver; let lcx = LoweringContext::new(&sess, Some(&krate), &mut dummy_resolver); diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index 0d10f31556644..a2893fa2f0dc0 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -20,7 +20,6 @@ extern crate rustc_metadata; extern crate rustc_resolve; #[macro_use] extern crate syntax; -use std::cell::RefCell; use std::ffi::{CStr, CString}; use std::mem::transmute; use std::path::PathBuf; @@ -246,7 +245,6 @@ fn compile_program(input: &str, sysroot: PathBuf) driver::lower_and_resolve(&sess, &id, &mut defs, &krate, dep_graph, MakeGlobMap::No) }; - let defs = &RefCell::new(defs); let arenas = ty::CtxtArenas::new(); let ast_map = ast_map::map_crate(&mut hir_forest, defs); From c0e321abcbc25c47e55a808628fb7e65b3fe0f98 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 May 2016 15:52:33 +0200 Subject: [PATCH 18/50] Make LocalCrateReader private to creader. --- src/librustc_driver/driver.rs | 5 ++-- src/librustc_driver/test.rs | 4 ++-- src/librustc_metadata/creader.rs | 27 +++++++++++++++------- src/librustdoc/core.rs | 4 ++-- src/test/run-make/execution-engine/test.rs | 4 ++-- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index a979410ca94de..d2a5e12009ec4 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -28,7 +28,7 @@ use rustc_borrowck as borrowck; use rustc_incremental; use rustc_resolve as resolve; use rustc_metadata::macro_import; -use rustc_metadata::creader::LocalCrateReader; +use rustc_metadata::creader::read_local_crates; use rustc_metadata::cstore::CStore; use rustc_trans::back::link; use rustc_trans::back::write; @@ -148,8 +148,7 @@ pub fn compile_input(sess: &Session, time(sess.time_passes(), "external crate/lib resolution", - || LocalCrateReader::new(sess, &cstore, &defs, &expanded_crate, &id) - .read_crates(&dep_graph)); + || read_local_crates(sess, &cstore, &defs, &expanded_crate, &id, &dep_graph)); time(sess.time_passes(), "early lint checks", diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 270376bda766e..5c62d236844ee 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -26,7 +26,7 @@ use rustc::traits::ProjectionMode; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::infer::{self, InferOk, InferResult, TypeOrigin}; use rustc_metadata::cstore::CStore; -use rustc_metadata::creader::LocalCrateReader; +use rustc_metadata::creader::read_local_crates; use rustc::hir::map as hir_map; use rustc::session::{self, config}; use std::rc::Rc; @@ -120,7 +120,7 @@ fn test_env(source_string: &str, let dep_graph = DepGraph::new(false); let krate = driver::assign_node_ids(&sess, krate); let mut defs = hir_map::collect_definitions(&krate); - LocalCrateReader::new(&sess, &cstore, &defs, &krate, "test_crate").read_crates(&dep_graph); + read_local_crates(&sess, &cstore, &defs, &krate, "test_crate", &dep_graph); let _ignore = dep_graph.in_ignore(); let (_, resolutions, mut hir_forest) = { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 62c208dbcb2a4..63c6af704bbfe 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -41,7 +41,7 @@ use syntax::parse::token::InternedString; use syntax::visit; use log; -pub struct LocalCrateReader<'a> { +struct LocalCrateReader<'a> { sess: &'a Session, cstore: &'a CStore, creader: CrateReader<'a>, @@ -841,12 +841,12 @@ impl<'a> CrateReader<'a> { } impl<'a> LocalCrateReader<'a> { - pub fn new(sess: &'a Session, - cstore: &'a CStore, - defs: &'a hir_map::Definitions, - krate: &'a ast::Crate, - local_crate_name: &str) - -> LocalCrateReader<'a> { + fn new(sess: &'a Session, + cstore: &'a CStore, + defs: &'a hir_map::Definitions, + krate: &'a ast::Crate, + local_crate_name: &str) + -> LocalCrateReader<'a> { LocalCrateReader { sess: sess, cstore: cstore, @@ -859,7 +859,7 @@ impl<'a> LocalCrateReader<'a> { // Traverses an AST, reading all the information about use'd crates and // extern libraries necessary for later resolving, typechecking, linking, // etc. - pub fn read_crates(&mut self, dep_graph: &DepGraph) { + fn read_crates(&mut self, dep_graph: &DepGraph) { let _task = dep_graph.in_task(DepNode::CrateReader); self.process_crate(self.krate); @@ -981,6 +981,17 @@ impl<'a> LocalCrateReader<'a> { } } +/// Traverses an AST, reading all the information about use'd crates and extern +/// libraries necessary for later resolving, typechecking, linking, etc. +pub fn read_local_crates(sess: & Session, + cstore: & CStore, + defs: & hir_map::Definitions, + krate: & ast::Crate, + local_crate_name: &str, + dep_graph: &DepGraph) { + LocalCrateReader::new(sess, cstore, defs, krate, local_crate_name).read_crates(dep_graph) +} + /// Imports the codemap from an external crate into the codemap of the crate /// currently being compiled (the "local crate"). /// diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e5919a4b35ff6..67eb268af08f6 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -21,7 +21,7 @@ use rustc::lint; use rustc_trans::back::link; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; -use rustc_metadata::creader::LocalCrateReader; +use rustc_metadata::creader::read_local_crates; use syntax::{ast, codemap, errors}; use syntax::errors::emitter::ColorConfig; @@ -154,7 +154,7 @@ pub fn run_core(search_paths: SearchPaths, let dep_graph = DepGraph::new(false); let mut defs = hir_map::collect_definitions(&krate); - LocalCrateReader::new(&sess, &cstore, &defs, &krate, &name).read_crates(&dep_graph); + read_local_crates(&sess, &cstore, &defs, &krate, &name, &dep_graph); // Lower ast -> hir and resolve. let (analysis, resolutions, mut hir_forest) = { diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index a2893fa2f0dc0..0ad113b8d8b38 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -34,7 +34,7 @@ use rustc::session::config::{self, basic_options, build_configuration, Input, Op use rustc::session::build_session; use rustc_driver::{driver, abort_on_err}; use rustc_resolve::MakeGlobMap; -use rustc_metadata::creader::LocalCrateReader; +use rustc_metadata::creader::read_local_crates; use rustc_metadata::cstore::CStore; use libc::c_void; @@ -240,7 +240,7 @@ fn compile_program(input: &str, sysroot: PathBuf) let dep_graph = DepGraph::new(sess.opts.build_dep_graph()); let krate = driver::assign_node_ids(&sess, krate); let mut defs = ast_map::collect_definitions(&krate); - LocalCrateReader::new(&sess, &cstore, &defs, &krate, &id).read_crates(&dep_graph); + read_local_crates(&sess, &cstore, &defs, &krate, &id, &dep_graph); let (analysis, resolutions, mut hir_forest) = { driver::lower_and_resolve(&sess, &id, &mut defs, &krate, dep_graph, MakeGlobMap::No) }; From 00f6513259c12af733d22398b1ea77cff67b7beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Tue, 10 May 2016 21:03:47 +0200 Subject: [PATCH 19/50] Only break critical edges where actually needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, to prepare for MIR trans, we break _all_ critical edges, although we only actually need to do this for edges originating from a call that gets translated to an invoke instruction in LLVM. This has the unfortunate effect of undoing a bunch of the things that SimplifyCfg has done. A particularly bad case arises when you have a C-like enum with N variants and a derived PartialEq implementation. In that case, the match on the (&lhs, &rhs) tuple gets translated into nested matches with N arms each and a basic block each, resulting in N² basic blocks. SimplifyCfg reduces that to roughly 2*N basic blocks, but breaking the critical edges means that we go back to N². In nickel.rs, there is such an enum with roughly N=800. So we get about 640K basic blocks or 2.5M lines of LLVM IR. LLVM takes a while to reduce that to the final "disr_a == disr_b". So before this patch, we had 2.5M lines of IR with 640K basic blocks, which took about about 3.6s in LLVM to get optimized and translated. After this patch, we get about 650K lines with about 1.6K basic blocks and spent a little less than 0.2s in LLVM. cc #33111 --- src/librustc_driver/driver.rs | 2 +- .../transform/break_cleanup_edges.rs | 111 +++++++++++++++++ .../transform/break_critical_edges.rs | 117 ------------------ src/librustc_mir/transform/mod.rs | 2 +- 4 files changed, 113 insertions(+), 119 deletions(-) create mode 100644 src/librustc_mir/transform/break_cleanup_edges.rs delete mode 100644 src/librustc_mir/transform/break_critical_edges.rs diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f0c2de2932775..519329a10d0a9 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1009,7 +1009,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads); passes.push_pass(box mir::transform::remove_dead_blocks::RemoveDeadBlocks); passes.push_pass(box mir::transform::erase_regions::EraseRegions); - passes.push_pass(box mir::transform::break_critical_edges::BreakCriticalEdges); + passes.push_pass(box mir::transform::break_cleanup_edges::BreakCleanupEdges); passes.run_passes(tcx, &mut mir_map); }); diff --git a/src/librustc_mir/transform/break_cleanup_edges.rs b/src/librustc_mir/transform/break_cleanup_edges.rs new file mode 100644 index 0000000000000..0eb6223a71e54 --- /dev/null +++ b/src/librustc_mir/transform/break_cleanup_edges.rs @@ -0,0 +1,111 @@ +// Copyright 2016 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. + +use rustc::ty::TyCtxt; +use rustc::mir::repr::*; +use rustc::mir::transform::{MirPass, MirSource, Pass}; + +use rustc_data_structures::bitvec::BitVector; + +use pretty; + +use traversal; + +pub struct BreakCleanupEdges; + +/** + * Breaks outgoing critical edges for call terminators in the MIR. + * + * Critical edges are edges that are neither the only edge leaving a + * block, nor the only edge entering one. + * + * When you want something to happen "along" an edge, you can either + * do at the end of the predecessor block, or at the start of the + * successor block. Critical edges have to be broken in order to prevent + * "edge actions" from affecting other edges. We need this for calls that are + * translated to LLVM invoke instructions, because invoke is a block terminator + * in LLVM so we can't insert any code to handle the call's result into the + * block that performs the call. + * + * This function will break those edges by inserting new blocks along them. + * + * NOTE: Simplify CFG will happily undo most of the work this pass does. + * + */ + +impl<'tcx> MirPass<'tcx> for BreakCleanupEdges { + fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { + let mut pred_count = vec![0u32; mir.basic_blocks.len()]; + + // Build the precedecessor map for the MIR + for (_, data) in traversal::preorder(mir) { + if let Some(ref term) = data.terminator { + for &tgt in term.successors().iter() { + pred_count[tgt.index()] += 1; + } + } + } + + let cleanup_map : BitVector = mir.basic_blocks + .iter().map(|bb| bb.is_cleanup).collect(); + + // We need a place to store the new blocks generated + let mut new_blocks = Vec::new(); + + let bbs = mir.all_basic_blocks(); + let cur_len = mir.basic_blocks.len(); + + for &bb in &bbs { + let data = mir.basic_block_data_mut(bb); + + if let Some(ref mut term) = data.terminator { + if term_is_invoke(term) { + let term_span = term.span; + let term_scope = term.scope; + let succs = term.successors_mut(); + for tgt in succs { + let num_preds = pred_count[tgt.index()]; + if num_preds > 1 { + // It's a critical edge, break it + let goto = Terminator { + span: term_span, + scope: term_scope, + kind: TerminatorKind::Goto { target: *tgt } + }; + let mut data = BasicBlockData::new(Some(goto)); + data.is_cleanup = cleanup_map.contains(tgt.index()); + + // Get the index it will be when inserted into the MIR + let idx = cur_len + new_blocks.len(); + new_blocks.push(data); + *tgt = BasicBlock::new(idx); + } + } + } + } + } + + pretty::dump_mir(tcx, "break_cleanup_edges", &0, src, mir, None); + debug!("Broke {} N edges", new_blocks.len()); + + mir.basic_blocks.extend_from_slice(&new_blocks); + } +} + +impl Pass for BreakCleanupEdges {} + +// Returns true if the terminator is a call that would use an invoke in LLVM. +fn term_is_invoke(term: &Terminator) -> bool { + match term.kind { + TerminatorKind::Call { cleanup: Some(_), .. } | + TerminatorKind::Drop { unwind: Some(_), .. } => true, + _ => false + } +} diff --git a/src/librustc_mir/transform/break_critical_edges.rs b/src/librustc_mir/transform/break_critical_edges.rs deleted file mode 100644 index a6af30b7eec08..0000000000000 --- a/src/librustc_mir/transform/break_critical_edges.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2016 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. - -use rustc::ty::TyCtxt; -use rustc::mir::repr::*; -use rustc::mir::transform::{MirPass, MirSource, Pass}; - -use rustc_data_structures::bitvec::BitVector; - -use traversal; - -pub struct BreakCriticalEdges; - -/** - * Breaks critical edges in the MIR. - * - * Critical edges are edges that are neither the only edge leaving a - * block, nor the only edge entering one. - * - * When you want something to happen "along" an edge, you can either - * do at the end of the predecessor block, or at the start of the - * successor block. Critical edges have to be broken in order to prevent - * "edge actions" from affecting other edges. - * - * This function will break those edges by inserting new blocks along them. - * - * A special case is Drop and Call terminators with unwind/cleanup successors, - * They use `invoke` in LLVM, which terminates a block, meaning that code cannot - * be inserted after them, so even if an edge is the only edge leaving a block - * like that, we still insert blocks if the edge is one of many entering the - * target. - * - * NOTE: Simplify CFG will happily undo most of the work this pass does. - * - */ - -impl<'tcx> MirPass<'tcx> for BreakCriticalEdges { - fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>, - _: MirSource, mir: &mut Mir<'tcx>) { - break_critical_edges(mir); - } -} - -impl Pass for BreakCriticalEdges {} - -fn break_critical_edges(mir: &mut Mir) { - let mut pred_count = vec![0u32; mir.basic_blocks.len()]; - - // Build the precedecessor map for the MIR - for (_, data) in traversal::preorder(mir) { - if let Some(ref term) = data.terminator { - for &tgt in term.successors().iter() { - pred_count[tgt.index()] += 1; - } - } - } - - let cleanup_map : BitVector = mir.basic_blocks - .iter().map(|bb| bb.is_cleanup).collect(); - - // We need a place to store the new blocks generated - let mut new_blocks = Vec::new(); - - let bbs = mir.all_basic_blocks(); - let cur_len = mir.basic_blocks.len(); - - for &bb in &bbs { - let data = mir.basic_block_data_mut(bb); - - if let Some(ref mut term) = data.terminator { - let is_invoke = term_is_invoke(term); - let term_span = term.span; - let term_scope = term.scope; - let succs = term.successors_mut(); - if succs.len() > 1 || (succs.len() > 0 && is_invoke) { - for tgt in succs { - let num_preds = pred_count[tgt.index()]; - if num_preds > 1 { - // It's a critical edge, break it - let goto = Terminator { - span: term_span, - scope: term_scope, - kind: TerminatorKind::Goto { target: *tgt } - }; - let mut data = BasicBlockData::new(Some(goto)); - data.is_cleanup = cleanup_map.contains(tgt.index()); - - // Get the index it will be when inserted into the MIR - let idx = cur_len + new_blocks.len(); - new_blocks.push(data); - *tgt = BasicBlock::new(idx); - } - } - } - } - } - - debug!("Broke {} N edges", new_blocks.len()); - - mir.basic_blocks.extend_from_slice(&new_blocks); -} - -// Returns true if the terminator would use an invoke in LLVM. -fn term_is_invoke(term: &Terminator) -> bool { - match term.kind { - TerminatorKind::Call { cleanup: Some(_), .. } | - TerminatorKind::Drop { unwind: Some(_), .. } => true, - _ => false - } -} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 51f5c3cd7f53d..0dcb7ef84d01d 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -13,6 +13,6 @@ pub mod simplify_cfg; pub mod erase_regions; pub mod no_landing_pads; pub mod type_check; -pub mod break_critical_edges; +pub mod break_cleanup_edges; pub mod promote_consts; pub mod qualify_consts; From 5541fdfcd1b94294fcd7d356c2948bb272d20b9f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 11 May 2016 20:09:50 +0300 Subject: [PATCH 20/50] Use symlink_metadata in tidy to avoid panicking on broken symlinks. --- src/tools/tidy/src/bins.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 43475f203d57c..e91b8fb0967a8 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -35,7 +35,7 @@ pub fn check(path: &Path, bad: &mut bool) { return } - let metadata = t!(fs::metadata(&file), &file); + let metadata = t!(fs::symlink_metadata(&file), &file); if metadata.mode() & 0o111 != 0 { println!("binary checked into source: {}", file.display()); *bad = true; From 4e5a2e01cf7fd13dccac12deaf7868f3855e54c5 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Tue, 10 May 2016 23:25:34 -0700 Subject: [PATCH 21/50] Remove unification despite ambiguity in projection --- src/librustc/traits/project.rs | 58 +--------------------------------- 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 4c338219ffbf7..a67188713c628 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -218,10 +218,7 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>( obligation.cause.clone(), obligation.recursion_depth) { Some(n) => n, - None => { - consider_unification_despite_ambiguity(selcx, obligation); - return Ok(None); - } + None => return Ok(None), }; debug!("project_and_unify_type: normalized_ty={:?} obligations={:?}", @@ -240,59 +237,6 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>( } } -fn consider_unification_despite_ambiguity<'cx, 'gcx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, - obligation: &ProjectionObligation<'tcx>) -{ - debug!("consider_unification_despite_ambiguity(obligation={:?})", - obligation); - - let def_id = obligation.predicate.projection_ty.trait_ref.def_id; - match selcx.tcx().lang_items.fn_trait_kind(def_id) { - Some(_) => { } - None => { return; } - } - - let infcx = selcx.infcx(); - let self_ty = obligation.predicate.projection_ty.trait_ref.self_ty(); - let self_ty = infcx.shallow_resolve(self_ty); - debug!("consider_unification_despite_ambiguity: self_ty.sty={:?}", - self_ty.sty); - match self_ty.sty { - ty::TyClosure(closure_def_id, substs) => { - let closure_typer = selcx.closure_typer(); - let closure_type = closure_typer.closure_type(closure_def_id, substs); - let ty::Binder((_, ret_type)) = - infcx.tcx.closure_trait_ref_and_return_type(def_id, - self_ty, - &closure_type.sig, - util::TupleArgumentsFlag::No); - // We don't have to normalize the return type here - this is only - // reached for TyClosure: Fn inputs where the closure kind is - // still unknown, which should only occur in typeck where the - // closure type is already normalized. - let (ret_type, _) = - infcx.replace_late_bound_regions_with_fresh_var( - obligation.cause.span, - infer::AssocTypeProjection(obligation.predicate.projection_ty.item_name), - &ty::Binder(ret_type)); - - debug!("consider_unification_despite_ambiguity: ret_type={:?}", - ret_type); - let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); - let obligation_ty = obligation.predicate.ty; - match infcx.eq_types(true, origin, obligation_ty, ret_type) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - } - Err(_) => { /* ignore errors */ } - } - } - _ => { } - } -} - /// Normalizes any associated type projections in `value`, replacing /// them with a fully resolved type where possible. The return value /// combines the normalized result and any additional obligations that From c91b1048847663fabf99cd48dd1d9bb1644bcd77 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 11 May 2016 20:30:20 +0100 Subject: [PATCH 22/50] Export OnceState from libstd --- src/libstd/sync/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index c20b422d40cf5..21008ee3989a7 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -31,7 +31,7 @@ pub use self::mutex::MUTEX_INIT; #[stable(feature = "rust1", since = "1.0.0")] pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::once::{Once, ONCE_INIT}; +pub use self::once::{Once, OnceState, ONCE_INIT}; #[stable(feature = "rust1", since = "1.0.0")] pub use sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; #[stable(feature = "rust1", since = "1.0.0")] From 5cbfa1285d7f3e6f93a5cd204ef9efbaefe222ed Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 11 May 2016 20:42:26 +0100 Subject: [PATCH 23/50] Fix typo in std::sync::Once documentation --- src/libstd/sync/once.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index e228d236a3ca7..d8a4a69c73cd3 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -218,7 +218,6 @@ impl Once { /// The closure `f` is yielded a structure which can be used to query the /// state of this `Once` (whether initialization has previously panicked or /// not). - /// poisoned or not. #[unstable(feature = "once_poison", issue = "31688")] pub fn call_once_force(&'static self, f: F) where F: FnOnce(&OnceState) { // same as above, just with a different parameter to `call_inner`. From 49b2cdf47c983d5ea8a576346d08120f0e3af30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Wed, 11 May 2016 21:31:19 +0200 Subject: [PATCH 24/50] [MIR trans] Optimize trans for biased switches Currently, all switches in MIR are exhausitive, meaning that we can have a lot of arms that all go to the same basic block, the extreme case being an if-let expression which results in just 2 possible cases, be might end up with hundreds of arms for large enums. To improve this situation and give LLVM less code to chew on, we can detect whether there's a pre-dominant target basic block in a switch and then promote this to be the default target, not translating the corresponding arms at all. In combination with #33544 this makes unoptimized MIR trans of nickel.rs as fast as using old trans and greatly improves the times for optimized builds, which are only 30-40% slower instead of ~300%. cc #33111 --- src/librustc_trans/mir/block.rs | 36 ++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index e1318396e317d..4e3386bc73677 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -24,6 +24,7 @@ use meth; use type_of; use glue; use type_::Type; +use rustc_data_structures::fnv::FnvHashMap; use super::{MirContext, TempRef, drop}; use super::constant::Const; @@ -95,17 +96,32 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { adt::trans_get_discr(bcx, &repr, discr_lvalue.llval, None, true) ); - // The else branch of the Switch can't be hit, so branch to an unreachable - // instruction so LLVM knows that - let unreachable_blk = self.unreachable_block(); - let switch = bcx.switch(discr, unreachable_blk.llbb, targets.len()); + let mut bb_hist = FnvHashMap(); + for target in targets { + *bb_hist.entry(target).or_insert(0) += 1; + } + let (default_bb, default_blk) = match bb_hist.iter().max_by_key(|&(_, c)| c) { + // If a single target basic blocks is predominant, promote that to be the + // default case for the switch instruction to reduce the size of the generated + // code. This is especially helpful in cases like an if-let on a huge enum. + // Note: This optimization is only valid for exhaustive matches. + Some((&&bb, &c)) if c > targets.len() / 2 => { + (Some(bb), self.blocks[bb.index()]) + } + // We're generating an exhaustive switch, so the else branch + // can't be hit. Branching to an unreachable instruction + // lets LLVM know this + _ => (None, self.unreachable_block()) + }; + let switch = bcx.switch(discr, default_blk.llbb, targets.len()); assert_eq!(adt_def.variants.len(), targets.len()); - for (adt_variant, target) in adt_def.variants.iter().zip(targets) { - let llval = bcx.with_block(|bcx| - adt::trans_case(bcx, &repr, Disr::from(adt_variant.disr_val)) - ); - let llbb = self.llblock(*target); - build::AddCase(switch, llval, llbb) + for (adt_variant, &target) in adt_def.variants.iter().zip(targets) { + if default_bb != Some(target) { + let llbb = self.llblock(target); + let llval = bcx.with_block(|bcx| adt::trans_case( + bcx, &repr, Disr::from(adt_variant.disr_val))); + build::AddCase(switch, llval, llbb) + } } } From fd70788e6d0439098ce31d75eda265721e8d3322 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 11 May 2016 22:45:49 +0300 Subject: [PATCH 25/50] Do not use const Rib for associated constants --- src/librustc_resolve/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index fc048c86dc9dd..094348a000a93 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1949,9 +1949,7 @@ impl<'a> Resolver<'a> { this.check_trait_item(impl_item.ident.name, impl_item.span, |n, s| ResolutionError::ConstNotMemberOfTrait(n, s)); - this.with_constant_rib(|this| { - visit::walk_impl_item(this, impl_item); - }); + visit::walk_impl_item(this, impl_item); } ImplItemKind::Method(ref sig, _) => { // If this is a trait impl, ensure the method From 5af829b0d0fba866afa28607f5c97542c7d04d5c Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 12 May 2016 00:30:08 +0300 Subject: [PATCH 26/50] Gen right parameter envirnoment for assoc consts --- src/librustc/ty/mod.rs | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 005d83da38dbf..114e81721ab28 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1260,7 +1260,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { match tcx.map.find(id) { Some(ast_map::NodeImplItem(ref impl_item)) => { match impl_item.node { - hir::ImplItemKind::Type(_) => { + hir::ImplItemKind::Type(_) | hir::ImplItemKind::Const(_, _) => { // associated types don't have their own entry (for some reason), // so for now just grab environment for the impl let impl_id = tcx.map.get_parent(id); @@ -1272,15 +1272,6 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { &predicates, tcx.region_maps.item_extent(id)) } - hir::ImplItemKind::Const(_, _) => { - let def_id = tcx.map.local_def_id(id); - let scheme = tcx.lookup_item_type(def_id); - let predicates = tcx.lookup_predicates(def_id); - tcx.construct_parameter_environment(impl_item.span, - &scheme.generics, - &predicates, - tcx.region_maps.item_extent(id)) - } hir::ImplItemKind::Method(_, ref body) => { let method_def_id = tcx.map.local_def_id(id); match tcx.impl_or_trait_item(method_def_id) { @@ -1303,7 +1294,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { } Some(ast_map::NodeTraitItem(trait_item)) => { match trait_item.node { - hir::TypeTraitItem(..) => { + hir::TypeTraitItem(..) | hir::ConstTraitItem(..) => { // associated types don't have their own entry (for some reason), // so for now just grab environment for the trait let trait_id = tcx.map.get_parent(id); @@ -1315,15 +1306,6 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { &predicates, tcx.region_maps.item_extent(id)) } - hir::ConstTraitItem(..) => { - let def_id = tcx.map.local_def_id(id); - let scheme = tcx.lookup_item_type(def_id); - let predicates = tcx.lookup_predicates(def_id); - tcx.construct_parameter_environment(trait_item.span, - &scheme.generics, - &predicates, - tcx.region_maps.item_extent(id)) - } hir::MethodTraitItem(_, ref body) => { // Use call-site for extent (unless this is a // trait method with no default; then fallback From 8628ccec8fa5792e5f278b8f9403aa175fe0a0f9 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 11 May 2016 14:40:24 -0700 Subject: [PATCH 27/50] Add inferred obligation storage to all Vtable variants and SelectionContext --- src/librustc/traits/mod.rs | 36 +++++++++++++----- src/librustc/traits/project.rs | 18 +++++---- src/librustc/traits/select.rs | 33 ++++++++++++---- src/librustc/traits/structural_impls.rs | 50 ++++++++++++++++++++----- src/librustc/traits/util.rs | 6 +-- src/librustc_trans/callee.rs | 4 +- src/librustc_trans/meth.rs | 5 ++- 7 files changed, 111 insertions(+), 41 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index f606d73a5493f..8ea6ad8475e6a 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -239,7 +239,7 @@ pub enum Vtable<'tcx, N> { VtableParam(Vec), /// Virtual calls through an object - VtableObject(VtableObjectData<'tcx>), + VtableObject(VtableObjectData<'tcx, N>), /// Successful resolution for a builtin trait. VtableBuiltin(VtableBuiltinData), @@ -250,7 +250,7 @@ pub enum Vtable<'tcx, N> { VtableClosure(VtableClosureData<'tcx, N>), /// Same as above, but for a fn pointer type with the given signature. - VtableFnPointer(ty::Ty<'tcx>), + VtableFnPointer(VtableFnPointerData<'tcx, N>), } /// Identifies a particular impl in the source, along with a set of @@ -293,14 +293,22 @@ pub struct VtableBuiltinData { /// A vtable for some object-safe trait `Foo` automatically derived /// for the object type `Foo`. #[derive(PartialEq,Eq,Clone)] -pub struct VtableObjectData<'tcx> { +pub struct VtableObjectData<'tcx, N> { /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits; this is the start of /// `upcast_trait_ref`'s methods in that vtable. - pub vtable_base: usize + pub vtable_base: usize, + + pub nested: Vec, +} + +#[derive(Clone, PartialEq, Eq)] +pub struct VtableFnPointerData<'tcx, N> { + pub fn_ty: ty::Ty<'tcx>, + pub nested: Vec } /// Creates predicate obligations from the generic bounds. @@ -569,7 +577,8 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableBuiltin(i) => i.nested, VtableDefaultImpl(d) => d.nested, VtableClosure(c) => c.nested, - VtableObject(_) | VtableFnPointer(..) => vec![] + VtableObject(d) => d.nested, + VtableFnPointer(d) => d.nested, } } @@ -578,18 +587,25 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableImpl(i) => VtableImpl(VtableImplData { impl_def_id: i.impl_def_id, substs: i.substs, - nested: i.nested.into_iter().map(f).collect() + nested: i.nested.into_iter().map(f).collect(), }), VtableParam(n) => VtableParam(n.into_iter().map(f).collect()), VtableBuiltin(i) => VtableBuiltin(VtableBuiltinData { - nested: i.nested.into_iter().map(f).collect() + nested: i.nested.into_iter().map(f).collect(), + }), + VtableObject(o) => VtableObject(VtableObjectData { + upcast_trait_ref: o.upcast_trait_ref, + vtable_base: o.vtable_base, + nested: o.nested.into_iter().map(f).collect(), }), - VtableObject(o) => VtableObject(o), VtableDefaultImpl(d) => VtableDefaultImpl(VtableDefaultImplData { trait_def_id: d.trait_def_id, - nested: d.nested.into_iter().map(f).collect() + nested: d.nested.into_iter().map(f).collect(), + }), + VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData { + fn_ty: p.fn_ty, + nested: p.nested.into_iter().map(f).collect(), }), - VtableFnPointer(f) => VtableFnPointer(f), VtableClosure(c) => VtableClosure(VtableClosureData { closure_def_id: c.closure_def_id, substs: c.substs, diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 4c338219ffbf7..efb2edc62bf4f 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -19,6 +19,7 @@ use super::PredicateObligation; use super::SelectionContext; use super::SelectionError; use super::VtableClosureData; +use super::VtableFnPointerData; use super::VtableImplData; use super::util; @@ -158,7 +159,7 @@ enum ProjectionTyCandidate<'tcx> { Closure(VtableClosureData<'tcx, PredicateObligation<'tcx>>), // fn pointer return type - FnPointer(Ty<'tcx>), + FnPointer(VtableFnPointerData<'tcx, PredicateObligation<'tcx>>), } struct ProjectionTyCandidateSet<'tcx> { @@ -929,9 +930,9 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( candidate_set.vec.push( ProjectionTyCandidate::Closure(data)); } - super::VtableFnPointer(fn_type) => { + super::VtableFnPointer(data) => { candidate_set.vec.push( - ProjectionTyCandidate::FnPointer(fn_type)); + ProjectionTyCandidate::FnPointer(data)); } super::VtableParam(..) => { // This case tell us nothing about the value of an @@ -997,8 +998,8 @@ fn confirm_candidate<'cx, 'gcx, 'tcx>( confirm_closure_candidate(selcx, obligation, closure_vtable) } - ProjectionTyCandidate::FnPointer(fn_type) => { - confirm_fn_pointer_candidate(selcx, obligation, fn_type) + ProjectionTyCandidate::FnPointer(fn_pointer_vtable) => { + confirm_fn_pointer_candidate(selcx, obligation, fn_pointer_vtable) } } } @@ -1006,10 +1007,13 @@ fn confirm_candidate<'cx, 'gcx, 'tcx>( fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>( selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - fn_type: Ty<'tcx>) + fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>) -> (Ty<'tcx>, Vec>) { - let fn_type = selcx.infcx().shallow_resolve(fn_type); + // FIXME(#32730) propagate obligations (fn pointer vtable nested obligations ONLY come from + // unification in inference) + assert!(fn_pointer_vtable.nested.is_empty()); + let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); let sig = fn_type.fn_sig(); confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 7d9a256a6e080..1c79e8c13ce3c 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -30,7 +30,7 @@ use super::SelectionResult; use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, VtableFnPointer, VtableObject, VtableDefaultImpl}; use super::{VtableImplData, VtableObjectData, VtableBuiltinData, - VtableClosureData, VtableDefaultImplData}; + VtableClosureData, VtableDefaultImplData, VtableFnPointerData}; use super::util; use hir::def_id::DefId; @@ -42,13 +42,24 @@ use traits; use ty::fast_reject; use ty::relate::TypeRelation; +use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec}; use std::cell::RefCell; use std::fmt; +use std::marker::PhantomData; use std::rc::Rc; use syntax::abi::Abi; use hir; use util::nodemap::FnvHashMap; +struct InferredObligationsSnapshotVecDelegate<'tcx> { + phantom: PhantomData<&'tcx i32>, +} +impl<'tcx> SnapshotVecDelegate for InferredObligationsSnapshotVecDelegate<'tcx> { + type Value = PredicateObligation<'tcx>; + type Undo = (); + fn reverse(_: &mut Vec, _: Self::Undo) {} +} + pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, @@ -74,6 +85,8 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { /// there is no type that the user could *actually name* that /// would satisfy it. This avoids crippling inference, basically. intercrate: bool, + + inferred_obligations: SnapshotVec>, } // A stack that walks back up the stack frame. @@ -300,6 +313,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { infcx: infcx, freshener: infcx.freshener(), intercrate: false, + inferred_obligations: SnapshotVec::new(), } } @@ -308,6 +322,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { infcx: infcx, freshener: infcx.freshener(), intercrate: true, + inferred_obligations: SnapshotVec::new(), } } @@ -1977,9 +1992,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } FnPointerCandidate => { - let fn_type = + let data = self.confirm_fn_pointer_candidate(obligation)?; - Ok(VtableFnPointer(fn_type)) + Ok(VtableFnPointer(data)) } ProjectionCandidate => { @@ -2227,7 +2242,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn confirm_object_candidate(&mut self, obligation: &TraitObligation<'tcx>) - -> VtableObjectData<'tcx> + -> VtableObjectData<'tcx, PredicateObligation<'tcx>> { debug!("confirm_object_candidate({:?})", obligation); @@ -2279,15 +2294,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } + // FIXME(#32730) propagate obligations VtableObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base: vtable_base, + nested: vec![] } } - fn confirm_fn_pointer_candidate(&mut self, - obligation: &TraitObligation<'tcx>) - -> Result,SelectionError<'tcx>> + fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>) + -> Result>, SelectionError<'tcx>> { debug!("confirm_fn_pointer_candidate({:?})", obligation); @@ -2305,7 +2321,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.confirm_poly_trait_refs(obligation.cause.clone(), obligation.predicate.to_poly_trait_ref(), trait_ref)?; - Ok(self_ty) + // FIXME(#32730) propagate obligations + Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] }) } fn confirm_closure_candidate(&mut self, diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 1495ae72ab344..e210d2da94cfd 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -99,11 +99,20 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableDefaultImplData { } } -impl<'tcx> fmt::Debug for traits::VtableObjectData<'tcx> { +impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "VtableObject(upcast={:?}, vtable_base={})", + write!(f, "VtableObject(upcast={:?}, vtable_base={}, nested={:?})", self.upcast_trait_ref, - self.vtable_base) + self.vtable_base, + self.nested) + } +} + +impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "VtableFnPointer(fn_ty={:?}, nested={:?})", + self.fn_ty, + self.nested) } } @@ -185,19 +194,26 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { }) }) } - traits::VtableFnPointer(ty) => { - tcx.lift(&ty).map(traits::VtableFnPointer) + traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => { + tcx.lift(&fn_ty).map(|fn_ty| { + traits::VtableFnPointer(traits::VtableFnPointerData { + fn_ty: fn_ty, + nested: nested, + }) + }) } traits::VtableParam(n) => Some(traits::VtableParam(n)), traits::VtableBuiltin(d) => Some(traits::VtableBuiltin(d)), traits::VtableObject(traits::VtableObjectData { upcast_trait_ref, - vtable_base + vtable_base, + nested }) => { tcx.lift(&upcast_trait_ref).map(|trait_ref| { traits::VtableObject(traits::VtableObjectData { upcast_trait_ref: trait_ref, - vtable_base: vtable_base + vtable_base: vtable_base, + nested: nested }) }) } @@ -276,16 +292,30 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinDa } } -impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> { +impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx, N> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { traits::VtableObjectData { upcast_trait_ref: self.upcast_trait_ref.fold_with(folder), - vtable_base: self.vtable_base + vtable_base: self.vtable_base, + nested: self.nested.fold_with(folder), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.upcast_trait_ref.visit_with(visitor) || self.nested.visit_with(visitor) + } +} + +impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableFnPointerData<'tcx, N> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + traits::VtableFnPointerData { + fn_ty: self.fn_ty.fold_with(folder), + nested: self.nested.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.upcast_trait_ref.visit_with(visitor) + self.fn_ty.visit_with(visitor) || self.nested.visit_with(visitor) } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 010add012379d..f8149565aa66b 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -473,9 +473,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Given an upcast trait object described by `object`, returns the /// index of the method `method_def_id` (which should be part of /// `object.upcast_trait_ref`) within the vtable for `object`. - pub fn get_vtable_index_of_object_method(self, - object: &super::VtableObjectData<'tcx>, - method_def_id: DefId) -> usize { + pub fn get_vtable_index_of_object_method(self, + object: &super::VtableObjectData<'tcx, N>, + method_def_id: DefId) -> usize { // Count number of methods preceding the one we are selecting and // add them to the total offset. // Skip over associated types and constants. diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 3fb8605412075..179fbe84eec06 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -188,9 +188,9 @@ impl<'tcx> Callee<'tcx> { }; Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty)) } - traits::VtableFnPointer(fn_ty) => { + traits::VtableFnPointer(vtable_fn_pointer) => { let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap(); - let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, fn_ty); + let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, vtable_fn_pointer.fn_ty); let method_ty = def_ty(tcx, def_id, substs); let fn_ptr_ty = match method_ty.sty { diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 9b279a397f864..64ee18fccef37 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -176,7 +176,10 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trait_closure_kind); vec![llfn].into_iter() } - traits::VtableFnPointer(bare_fn_ty) => { + traits::VtableFnPointer( + traits::VtableFnPointerData { + fn_ty: bare_fn_ty, + nested: _ }) => { let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap(); vec![trans_fn_pointer_shim(ccx, trait_closure_kind, bare_fn_ty)].into_iter() } From ec7c483d679b70d50690cf477ef00106a5b97fc2 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 11 May 2016 14:56:52 -0700 Subject: [PATCH 28/50] Don't mutate the inference context when assembling --- src/librustc/traits/select.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 1c79e8c13ce3c..431813493bc8e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1463,7 +1463,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } - self.infcx.in_snapshot(|snapshot| { + self.infcx.probe(|snapshot| { let (self_ty, _) = self.infcx().skolemize_late_bound_regions(&obligation.self_ty(), snapshot); let poly_trait_ref = match self_ty.sty { From d3218fae7b5a4a0ba9b02903dc12d36ff94a1388 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 12 May 2016 00:48:47 +0300 Subject: [PATCH 29/50] =?UTF-8?q?Check=20the=20constants=E2=80=99=20parame?= =?UTF-8?q?ter=20environment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/librustc_typeck/check/mod.rs | 3 ++- .../associated-const-outer-ty-refs.rs | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/associated-const-outer-ty-refs.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f428023da9b82..648d1f94e6215 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1151,7 +1151,8 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, sp: Span, e: &'tcx hir::Expr, id: ast::NodeId) { - ccx.inherited(None).enter(|inh| { + let param_env = ParameterEnvironment::for_item(ccx.tcx, id); + ccx.inherited(Some(param_env)).enter(|inh| { let rty = ccx.tcx.node_id_to_type(id); let fcx = FnCtxt::new(&inh, ty::FnConverging(rty), e.id); let declty = fcx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(id)).ty; diff --git a/src/test/run-pass/associated-const-outer-ty-refs.rs b/src/test/run-pass/associated-const-outer-ty-refs.rs new file mode 100644 index 0000000000000..a603b225132d4 --- /dev/null +++ b/src/test/run-pass/associated-const-outer-ty-refs.rs @@ -0,0 +1,21 @@ +// Copyright 2016 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(associated_consts)] + +trait Lattice { + const BOTTOM: Self; +} + +// FIXME(#33573): this should work without the 'static lifetime bound. +impl Lattice for Option { + const BOTTOM: Option = None; +} + +fn main(){} From f52b655621dc0e3ba8d2b37de9a68f96a65ab660 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 11 May 2016 17:22:13 -0700 Subject: [PATCH 30/50] Plumb inference obligations through selection --- src/librustc/traits/mod.rs | 12 ++ src/librustc/traits/select.rs | 172 ++++++++++++------- src/librustc_data_structures/snapshot_vec.rs | 8 + 3 files changed, 126 insertions(+), 66 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8ea6ad8475e6a..65df056fd424b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -582,6 +582,18 @@ impl<'tcx, N> Vtable<'tcx, N> { } } + fn nested_obligations_mut(&mut self) -> &mut Vec { + match self { + &mut VtableImpl(ref mut i) => &mut i.nested, + &mut VtableParam(ref mut n) => n, + &mut VtableBuiltin(ref mut i) => &mut i.nested, + &mut VtableDefaultImpl(ref mut d) => &mut d.nested, + &mut VtableClosure(ref mut c) => &mut c.nested, + &mut VtableObject(ref mut d) => &mut d.nested, + &mut VtableFnPointer(ref mut d) => &mut d.nested, + } + } + pub fn map(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M { match self { VtableImpl(i) => VtableImpl(VtableImplData { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 431813493bc8e..5307749b87b6a 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -346,6 +346,46 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.infcx.projection_mode() } + /// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection + /// context's self. + fn in_snapshot(&mut self, f: F) -> R + where F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> R + { + // The irrefutable nature of the operation means we don't need to snapshot the + // inferred_obligations vector. + self.infcx.in_snapshot(|snapshot| f(self, snapshot)) + } + + /// Wraps a probe s.t. obligations collected during it are ignored and old obligations are + /// retained. + fn probe(&mut self, f: F) -> R + where F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> R + { + let inferred_obligations_snapshot = self.inferred_obligations.start_snapshot(); + let result = self.infcx.probe(|snapshot| f(self, snapshot)); + self.inferred_obligations.rollback_to(inferred_obligations_snapshot); + result + } + + /// Wraps a commit_if_ok s.t. obligations collected during it are not returned in selection if + /// the transaction fails and s.t. old obligations are retained. + fn commit_if_ok(&mut self, f: F) -> Result where + F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> Result + { + let inferred_obligations_snapshot = self.inferred_obligations.start_snapshot(); + match self.infcx.commit_if_ok(|snapshot| f(self, snapshot)) { + Ok(ok) => { + self.inferred_obligations.commit(inferred_obligations_snapshot); + Ok(ok) + }, + Err(err) => { + self.inferred_obligations.rollback_to(inferred_obligations_snapshot); + Err(err) + } + } + } + + /////////////////////////////////////////////////////////////////////////// // Selection // @@ -374,7 +414,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let stack = self.push_stack(TraitObligationStackList::empty(), obligation); match self.candidate_from_obligation(&stack)? { None => Ok(None), - Some(candidate) => Ok(Some(self.confirm_candidate(obligation, candidate)?)), + Some(candidate) => { + let mut candidate = self.confirm_candidate(obligation, candidate)?; + // FIXME(#32730) remove this assertion once inferred obligations are propagated + // from inference + assert!(self.inferred_obligations.len() == 0); + let inferred_obligations = (*self.inferred_obligations).into_iter().cloned(); + candidate.nested_obligations_mut().extend(inferred_obligations); + Ok(Some(candidate)) + }, } } @@ -396,8 +444,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_obligation({:?})", obligation); - self.infcx.probe(|_| { - self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + self.probe(|this, _| { + this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) .may_apply() }) } @@ -412,8 +460,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_obligation_conservatively({:?})", obligation); - self.infcx.probe(|_| { - self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + self.probe(|this, _| { + this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) == EvaluatedToOk }) } @@ -475,8 +523,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // does this code ever run? match self.infcx.equality_predicate(obligation.cause.span, p) { Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.inferred_obligations.extend(obligations); EvaluatedToOk }, Err(_) => EvaluatedToErr @@ -658,11 +705,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("evaluate_candidate: depth={} candidate={:?}", stack.obligation.recursion_depth, candidate); - let result = self.infcx.probe(|_| { + let result = self.probe(|this, _| { let candidate = (*candidate).clone(); - match self.confirm_candidate(stack.obligation, candidate) { + match this.confirm_candidate(stack.obligation, candidate) { Ok(selection) => { - self.evaluate_predicates_recursively( + this.evaluate_predicates_recursively( stack.list(), selection.nested_obligations().iter()) } @@ -1122,8 +1169,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("assemble_candidates_for_projected_tys: trait_def_id={:?}", trait_def_id); - let result = self.infcx.probe(|snapshot| { - self.match_projection_obligation_against_bounds_from_trait(obligation, + let result = self.probe(|this, snapshot| { + this.match_projection_obligation_against_bounds_from_trait(obligation, snapshot) }); @@ -1171,12 +1218,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { util::elaborate_predicates(self.tcx(), bounds.predicates.into_vec()) .filter_to_traits() .find( - |bound| self.infcx.probe( - |_| self.match_projection(obligation, - bound.clone(), - skol_trait_predicate.trait_ref.clone(), - &skol_map, - snapshot))); + |bound| self.probe( + |this, _| this.match_projection(obligation, + bound.clone(), + skol_trait_predicate.trait_ref.clone(), + &skol_map, + snapshot))); debug!("match_projection_obligation_against_bounds_from_trait: \ matching_bound={:?}", @@ -1211,8 +1258,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { trait_bound.clone(), ty::Binder(skol_trait_ref.clone())) { Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.inferred_obligations.extend(obligations); } Err(_) => { return false; } } @@ -1254,10 +1300,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { where_clause_trait_ref: ty::PolyTraitRef<'tcx>) -> EvaluationResult { - self.infcx().probe(move |_| { - match self.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { + self.probe(move |this, _| { + match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { - self.evaluate_predicates_recursively(stack.list(), obligations.iter()) + this.evaluate_predicates_recursively(stack.list(), obligations.iter()) } Err(()) => EvaluatedToErr } @@ -1376,8 +1422,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.tcx(), obligation.predicate.0.trait_ref.self_ty(), |impl_def_id| { - self.infcx.probe(|snapshot| { - if let Ok(_) = self.match_impl(impl_def_id, obligation, snapshot) { + self.probe(|this, snapshot| { + if let Ok(_) = this.match_impl(impl_def_id, obligation, snapshot) { candidates.vec.push(ImplCandidate(impl_def_id)); } }); @@ -1463,12 +1509,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } - self.infcx.probe(|snapshot| { + self.probe(|this, snapshot| { let (self_ty, _) = - self.infcx().skolemize_late_bound_regions(&obligation.self_ty(), snapshot); + this.infcx().skolemize_late_bound_regions(&obligation.self_ty(), snapshot); let poly_trait_ref = match self_ty.sty { ty::TyTrait(ref data) => { - match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { + match this.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { if data.bounds.builtin_bounds.contains(&bound) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ @@ -1480,7 +1526,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => {} } - data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) + data.principal_trait_ref_with_self_ty(this.tcx(), self_ty) } ty::TyInfer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -1501,11 +1547,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // For example, we may be trying to upcast `Foo` to `Bar`, // but `Foo` is declared as `trait Foo : Bar`. let upcast_trait_refs = - util::supertraits(self.tcx(), poly_trait_ref) + util::supertraits(this.tcx(), poly_trait_ref) .filter(|upcast_trait_ref| { - self.infcx.probe(|_| { + this.probe(|this, _| { let upcast_trait_ref = upcast_trait_ref.clone(); - self.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok() + this.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok() }) }) .count(); @@ -1909,23 +1955,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { types.skip_binder().into_iter().flat_map(|ty| { // binder moved -\ let ty: ty::Binder> = ty::Binder(ty); // <----------/ - self.infcx.in_snapshot(|snapshot| { + self.in_snapshot(|this, snapshot| { let (skol_ty, skol_map) = - self.infcx().skolemize_late_bound_regions(&ty, snapshot); + this.infcx().skolemize_late_bound_regions(&ty, snapshot); let Normalized { value: normalized_ty, mut obligations } = - project::normalize_with_depth(self, + project::normalize_with_depth(this, cause.clone(), recursion_depth, &skol_ty); let skol_obligation = - self.tcx().predicate_for_trait_def( + this.tcx().predicate_for_trait_def( cause.clone(), trait_def_id, recursion_depth, normalized_ty, vec![]); obligations.push(skol_obligation); - self.infcx().plug_leaks(skol_map, snapshot, &obligations) + this.infcx().plug_leaks(skol_map, snapshot, &obligations) }) }).collect() } @@ -2012,9 +2058,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.in_snapshot(|snapshot| { + self.in_snapshot(|this, snapshot| { let result = - self.match_projection_obligation_against_bounds_from_trait(obligation, + this.match_projection_obligation_against_bounds_from_trait(obligation, snapshot); assert!(result); }) @@ -2155,12 +2201,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { trait_def_id, nested); - let trait_obligations = self.infcx.in_snapshot(|snapshot| { + let trait_obligations = self.in_snapshot(|this, snapshot| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); let (trait_ref, skol_map) = - self.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot); - let cause = self.derived_cause(obligation, ImplDerivedObligation); - self.impl_or_trait_obligations(cause, + this.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot); + let cause = this.derived_cause(obligation, ImplDerivedObligation); + this.impl_or_trait_obligations(cause, obligation.recursion_depth + 1, trait_def_id, &trait_ref.substs, @@ -2189,13 +2235,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.in_snapshot(|snapshot| { + self.in_snapshot(|this, snapshot| { let (substs, skol_map) = - self.rematch_impl(impl_def_id, obligation, + this.rematch_impl(impl_def_id, obligation, snapshot); debug!("confirm_impl_candidate substs={:?}", substs); - let cause = self.derived_cause(obligation, ImplDerivedObligation); - self.vtable_impl(impl_def_id, substs, cause, + let cause = this.derived_cause(obligation, ImplDerivedObligation); + this.vtable_impl(impl_def_id, substs, cause, obligation.recursion_depth + 1, skol_map, snapshot) }) @@ -2266,6 +2312,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let vtable_base; { + let tcx = self.tcx(); + // We want to find the first supertrait in the list of // supertraits that we can unify with, and do that // unification. We know that there is exactly one in the list @@ -2273,11 +2321,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // reported an ambiguity. (When we do find a match, also // record it for later.) let nonmatching = - util::supertraits(self.tcx(), poly_trait_ref) + util::supertraits(tcx, poly_trait_ref) .take_while(|&t| { match - self.infcx.commit_if_ok( - |_| self.match_poly_trait_ref(obligation, t)) + self.commit_if_ok( + |this, _| this.match_poly_trait_ref(obligation, t)) { Ok(_) => { upcast_trait_ref = Some(t); false } Err(_) => { true } @@ -2289,12 +2337,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // entries, so that we can compute the offset for the selected // trait. vtable_base = - nonmatching.map(|t| self.tcx().count_own_vtable_entries(t)) + nonmatching.map(|t| tcx.count_own_vtable_entries(t)) .sum(); } - // FIXME(#32730) propagate obligations VtableObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base: vtable_base, @@ -2321,7 +2368,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.confirm_poly_trait_refs(obligation.cause.clone(), obligation.predicate.to_poly_trait_ref(), trait_ref)?; - // FIXME(#32730) propagate obligations Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] }) } @@ -2401,8 +2447,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { origin, expected_trait_ref.clone(), obligation_trait_ref.clone()) - // FIXME(#32730) propagate obligations - .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())) + .map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations)) .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)) } @@ -2437,8 +2482,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let InferOk { obligations, .. } = self.infcx.sub_types(false, origin, new_trait, target) .map_err(|_| Unimplemented)?; - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.inferred_obligations.extend(obligations); // Register one obligation for 'a: 'b. let cause = ObligationCause::new(obligation.cause.span, @@ -2511,8 +2555,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let InferOk { obligations, .. } = self.infcx.sub_types(false, origin, a, b) .map_err(|_| Unimplemented)?; - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.inferred_obligations.extend(obligations); } // Struct -> Struct. @@ -2571,8 +2614,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let InferOk { obligations, .. } = self.infcx.sub_types(false, origin, new_struct, target) .map_err(|_| Unimplemented)?; - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.inferred_obligations.extend(obligations); // Construct the nested Field: Unsize> predicate. nested.push(tcx.predicate_for_trait_def( @@ -2666,8 +2708,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("match_impl: failed eq_trait_refs due to `{}`", e); () })?; - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.inferred_obligations.extend(obligations); if let Err(e) = self.infcx.leak_check(false, &skol_map, snapshot) { debug!("match_impl: failed leak check due to `{}`", e); @@ -2720,7 +2761,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// Returns `Ok` if `poly_trait_ref` being true implies that the /// obligation is satisfied. - fn match_poly_trait_ref(&self, + fn match_poly_trait_ref(&mut self, obligation: &TraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Result<(),()> @@ -2734,8 +2775,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { origin, poly_trait_ref, obligation.predicate.to_poly_trait_ref()) - // FIXME(#32730) propagate obligations - .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())) + .map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations)) .map_err(|_| ()) } diff --git a/src/librustc_data_structures/snapshot_vec.rs b/src/librustc_data_structures/snapshot_vec.rs index 614e7aae74bbc..dac074ab91e1b 100644 --- a/src/librustc_data_structures/snapshot_vec.rs +++ b/src/librustc_data_structures/snapshot_vec.rs @@ -213,3 +213,11 @@ impl ops::IndexMut for SnapshotVec { self.get_mut(index) } } + +impl Extend for SnapshotVec { + fn extend(&mut self, iterable: T) where T: IntoIterator { + for item in iterable { + self.push(item); + } + } +} From 6458b0454f66f9cf16a4b50b8e0874b950326ef3 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Thu, 12 May 2016 00:05:25 -0400 Subject: [PATCH 31/50] Cleanup formatting and wording for `std::env::temp_dir` docs. --- src/libstd/env.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 9dc6a26cdeed3..6956dc0d901a4 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -452,16 +452,16 @@ pub fn home_dir() -> Option { /// Returns the path of a temporary directory. /// -/// On Unix, returns the value of the 'TMPDIR' environment variable if it is -/// set, otherwise for non-Android it returns '/tmp'. If Android, since there -/// is no global temporary folder (it is usually allocated per-app), we return -/// '/data/local/tmp'. -/// -/// On Windows, returns the value of, in order, the 'TMP', 'TEMP', -/// 'USERPROFILE' environment variable if any are set and not the empty -/// string. Otherwise, tmpdir returns the path of the Windows directory. This -/// behavior is identical to that of [GetTempPath][msdn], which this function -/// uses internally. +/// On Unix, returns the value of the `TMPDIR` environment variable if it is +/// set, otherwise for non-Android it returns `/tmp`. If Android, since there +/// is no global temporary folder (it is usually allocated per-app), it returns +/// `/data/local/tmp`. +/// +/// On Windows, returns the value of, in order, the `TMP`, `TEMP`, +/// `USERPROFILE` environment variable if any are set and not the empty +/// string. Otherwise, `temp_dir` returns the path of the Windows directory. +/// This behavior is identical to that of [`GetTempPath`][msdn], which this +/// function uses internally. /// /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx /// From a7902b12e8045c1781c71e171f715344c38b6c01 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Thu, 12 May 2016 13:42:57 +0900 Subject: [PATCH 32/50] Tighten span for E0063 --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f428023da9b82..1afc6e1e33edf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3299,7 +3299,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expr_ty = self.instantiate_type(def.def_id(), path); self.write_ty(expr.id, expr_ty); - self.check_expr_struct_fields(expr_ty, expr.span, variant, fields, + self.check_expr_struct_fields(expr_ty, path.span, variant, fields, base_expr.is_none()); if let &Some(ref base_expr) = base_expr { self.check_expr_has_type(base_expr, expr_ty); From 3c2ec1349b3b2de101ec03e06e6d1a60d60a29c1 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 10 May 2016 23:21:18 +0300 Subject: [PATCH 33/50] rustc: use a simpler scheme for plugin registrar symbol names. --- src/librustc/session/mod.rs | 10 ++++++++++ src/librustc_metadata/creader.rs | 14 +++++++++----- src/librustc_metadata/decoder.rs | 8 -------- src/librustc_plugin/load.rs | 3 ++- src/librustc_trans/base.rs | 6 ++++++ 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 1bea01c4849e7..2e4cbfd86279b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::def_id::DefIndex; +use hir::svh::Svh; use lint; use middle::cstore::CrateStore; use middle::dependency_format; @@ -310,6 +312,14 @@ impl Session { pub fn nonzeroing_move_hints(&self) -> bool { self.opts.debugging_opts.enable_nonzeroing_move_hints } + + /// Returns the symbol name for the registrar function, + /// given the crate Svh and the function DefIndex. + pub fn generate_plugin_registrar_symbol(&self, svh: &Svh, index: DefIndex) + -> String { + format!("__rustc_plugin_registrar__{}_{}", svh, index.as_usize()) + } + pub fn sysroot<'a>(&'a self) -> &'a Path { match self.opts.maybe_sysroot { Some (ref sysroot) => sysroot, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 190e8552d199a..45fee38070c22 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -17,6 +17,7 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use decoder; use loader::{self, CratePaths}; +use rustc::hir::def_id::DefIndex; use rustc::hir::svh::Svh; use rustc::dep_graph::{DepGraph, DepNode}; use rustc::session::{config, Session}; @@ -578,9 +579,10 @@ impl<'a> CrateReader<'a> { macros } - /// Look for a plugin registrar. Returns library path and symbol name. + /// Look for a plugin registrar. Returns library path, crate + /// SVH and DefIndex of the registrar function. pub fn find_plugin_registrar(&mut self, span: Span, name: &str) - -> Option<(PathBuf, String)> { + -> Option<(PathBuf, Svh, DefIndex)> { let ekrate = self.read_extension_crate(span, &CrateInfo { name: name.to_string(), ident: name.to_string(), @@ -598,12 +600,14 @@ impl<'a> CrateReader<'a> { span_fatal!(self.sess, span, E0456, "{}", &message[..]); } + let svh = decoder::get_crate_hash(ekrate.metadata.as_slice()); let registrar = - decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice()) - .map(|id| decoder::get_symbol_from_buf(ekrate.metadata.as_slice(), id)); + decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice()); match (ekrate.dylib.as_ref(), registrar) { - (Some(dylib), Some(reg)) => Some((dylib.to_path_buf(), reg)), + (Some(dylib), Some(reg)) => { + Some((dylib.to_path_buf(), svh, reg)) + } (None, Some(_)) => { span_err!(self.sess, span, E0457, "plugin `{}` only found in rlib format, but must be available \ diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e233dda7e91ee..0d11998f21c58 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -613,14 +613,6 @@ pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String { return item_symbol(cdata.lookup_item(id)); } -/// If you have a crate_metadata, call get_symbol instead -pub fn get_symbol_from_buf(data: &[u8], id: DefIndex) -> String { - let index = load_index(data); - let pos = index.lookup_item(data, id).unwrap(); - let doc = reader::doc_at(data, pos as usize).unwrap().doc; - item_symbol(doc) -} - /// Iterates over the language items in the given crate. pub fn each_lang_item(cdata: Cmd, mut f: F) -> bool where F: FnMut(DefIndex, usize) -> bool, diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 036e46c380398..11e1841f7493e 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -101,7 +101,8 @@ impl<'a> PluginLoader<'a> { fn load_plugin(&mut self, span: Span, name: &str, args: Vec>) { let registrar = self.reader.find_plugin_registrar(span, name); - if let Some((lib, symbol)) = registrar { + if let Some((lib, svh, index)) = registrar { + let symbol = self.sess.generate_plugin_registrar_symbol(&svh, index); let fun = self.dylink_registrar(span, lib, symbol); self.plugins.push(PluginRegistrar { fun: fun, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 7665b730caddf..5526f530a1a18 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2435,6 +2435,12 @@ pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> String { let id = ccx.tcx().map.as_local_node_id(instance.def).unwrap(); + if ccx.sess().plugin_registrar_fn.get() == Some(id) { + let svh = &ccx.link_meta().crate_hash; + let idx = instance.def.index; + return ccx.sess().generate_plugin_registrar_symbol(svh, idx); + } + match ccx.external_srcs().borrow().get(&id) { Some(&did) => { let sym = ccx.sess().cstore.item_symbol(did); From fc0872aeb62b5550692a77c4501a5ebac89585a5 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 10 May 2016 23:24:17 +0300 Subject: [PATCH 34/50] trans: remove unused symbol_names::exported_name_with_suffix. --- src/librustc_trans/back/symbol_names.rs | 30 +++++-------------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 0cf82d66b2b68..0495cf5eb6718 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -116,7 +116,7 @@ pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> def_path_to_string(tcx, &def_path) } -pub fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String { +fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String { let mut s = String::with_capacity(def_path.data.len() * 16); s.push_str(&tcx.crate_name(def_path.krate)); @@ -187,14 +187,13 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>, - suffix: Option<&str>) - -> String { +pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + instance: &Instance<'tcx>) + -> String { let &Instance { def: mut def_id, ref substs } = instance; - debug!("exported_name_with_opt_suffix(def_id={:?}, substs={:?}, suffix={:?})", - def_id, substs, suffix); + debug!("exported_name(def_id={:?}, substs={:?})", + def_id, substs); if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) { if let Some(&src_def_id) = ccx.external_srcs().borrow().get(&node_id) { @@ -242,10 +241,6 @@ fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, }; ccx.tcx().push_item_path(&mut buffer, def_id); - if let Some(suffix) = suffix { - buffer.push(suffix); - } - mangle(buffer.names.into_iter(), Some(&hash[..])) } @@ -264,19 +259,6 @@ impl ItemPathBuffer for SymbolPathBuffer { } } -pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>) - -> String { - exported_name_with_opt_suffix(ccx, instance, None) -} - -pub fn exported_name_with_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>, - suffix: &str) - -> String { - exported_name_with_opt_suffix(ccx, instance, Some(suffix)) -} - /// Only symbols that are invisible outside their compilation unit should use a /// name generated by this function. pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, From 06e00c494633b7f11a054a24f5487e36c66658ea Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 01:22:56 +0300 Subject: [PATCH 35/50] trans: move exported_name's logic into symbol_names. --- src/librustc_trans/back/symbol_names.rs | 64 +++++++++++++++++-------- src/librustc_trans/base.rs | 44 +---------------- src/librustc_trans/callee.rs | 5 +- src/librustc_trans/closure.rs | 2 +- src/librustc_trans/consts.rs | 9 ++-- src/librustc_trans/context.rs | 4 ++ src/librustc_trans/monomorphize.rs | 2 +- src/librustc_trans/symbol_names_test.rs | 2 +- 8 files changed, 62 insertions(+), 70 deletions(-) diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 0495cf5eb6718..dffd0beafe51b 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -97,17 +97,18 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. -use common::{CrateContext, gensym_name}; +use common::{CrateContext, SharedCrateContext, gensym_name}; use monomorphize::Instance; use util::sha2::{Digest, Sha256}; -use rustc::middle::cstore; +use rustc::middle::{cstore, weak_lang_items}; use rustc::hir::def_id::DefId; use rustc::ty::{self, TyCtxt, TypeFoldable}; -use rustc::ty::item_path::{ItemPathBuffer, RootMode}; +use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; use rustc::hir::map::definitions::{DefPath, DefPathData}; use std::fmt::Write; +use syntax::attr; use syntax::parse::token::{self, InternedString}; use serialize::hex::ToHex; @@ -134,7 +135,7 @@ fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) s } -fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, +fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // path to the item this name is for def_path: &DefPath, @@ -152,9 +153,9 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("get_symbol_hash(def_path={:?}, parameters={:?})", def_path, parameters); - let tcx = ccx.tcx(); + let tcx = scx.tcx(); - let mut hash_state = ccx.symbol_hasher().borrow_mut(); + let mut hash_state = scx.symbol_hasher().borrow_mut(); hash_state.reset(); @@ -187,22 +188,47 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>) +pub fn exported_name<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, + instance: Instance<'tcx>) -> String { - let &Instance { def: mut def_id, ref substs } = instance; + let Instance { def: def_id, ref substs } = instance; debug!("exported_name(def_id={:?}, substs={:?})", def_id, substs); - if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) { - if let Some(&src_def_id) = ccx.external_srcs().borrow().get(&node_id) { - def_id = src_def_id; + let node_id = scx.tcx().map.as_local_node_id(instance.def); + + if let Some(id) = node_id { + if scx.sess().plugin_registrar_fn.get() == Some(id) { + let svh = &scx.link_meta().crate_hash; + let idx = instance.def.index; + return scx.sess().generate_plugin_registrar_symbol(svh, idx); } } - let def_path = ccx.tcx().def_path(def_id); - assert_eq!(def_path.krate, def_id.krate); + // FIXME(eddyb) Precompute a custom symbol name based on attributes. + let attrs; + let attrs = if let Some(id) = node_id { + scx.tcx().map.attrs(id) + } else { + attrs = scx.sess().cstore.item_attrs(def_id); + &attrs[..] + }; + + if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), attrs) { + // Use provided name + return name.to_string(); + } + + if attr::contains_name(attrs, "no_mangle") { + // Don't mangle + return scx.tcx().item_name(instance.def).as_str().to_string() + } + if let Some(name) = weak_lang_items::link_name(attrs) { + return name.to_string(); + } + + let def_path = scx.tcx().def_path(def_id); // We want to compute the "type" of this item. Unfortunately, some // kinds of items (e.g., closures) don't have an entry in the @@ -211,11 +237,11 @@ pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let mut ty_def_id = def_id; let instance_ty; loop { - let key = ccx.tcx().def_key(ty_def_id); + let key = scx.tcx().def_key(ty_def_id); match key.disambiguated_data.data { DefPathData::TypeNs(_) | DefPathData::ValueNs(_) => { - instance_ty = ccx.tcx().lookup_item_type(ty_def_id); + instance_ty = scx.tcx().lookup_item_type(ty_def_id); break; } _ => { @@ -232,9 +258,9 @@ pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // Erase regions because they may not be deterministic when hashed // and should not matter anyhow. - let instance_ty = ccx.tcx().erase_regions(&instance_ty.ty); + let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); - let hash = get_symbol_hash(ccx, &def_path, instance_ty, substs.types.as_slice()); + let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice()); let mut buffer = SymbolPathBuffer { names: Vec::with_capacity(def_path.data.len()) @@ -271,7 +297,7 @@ pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx> data: vec![], krate: cstore::LOCAL_CRATE, }; - let hash = get_symbol_hash(ccx, &def_path, t, &[]); + let hash = get_symbol_hash(ccx.shared(), &def_path, t, &[]); mangle(path.iter().cloned(), Some(&hash[..])) } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 5526f530a1a18..5fe2aaa35e31d 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2429,47 +2429,6 @@ pub fn create_entry_wrapper(ccx: &CrateContext, sp: Span, main_llfn: ValueRef) { } } -pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: Instance<'tcx>, - attrs: &[ast::Attribute]) - -> String { - let id = ccx.tcx().map.as_local_node_id(instance.def).unwrap(); - - if ccx.sess().plugin_registrar_fn.get() == Some(id) { - let svh = &ccx.link_meta().crate_hash; - let idx = instance.def.index; - return ccx.sess().generate_plugin_registrar_symbol(svh, idx); - } - - match ccx.external_srcs().borrow().get(&id) { - Some(&did) => { - let sym = ccx.sess().cstore.item_symbol(did); - debug!("found item {} in other crate...", sym); - return sym; - } - None => {} - } - - match attr::find_export_name_attr(ccx.sess().diagnostic(), attrs) { - // Use provided name - Some(name) => name.to_string(), - _ => { - if attr::contains_name(attrs, "no_mangle") { - // Don't mangle - ccx.tcx().map.name(id).as_str().to_string() - } else { - match weak_lang_items::link_name(attrs) { - Some(name) => name.to_string(), - None => { - // Usual name mangling - symbol_names::exported_name(ccx, &instance) - } - } - } - } - } -} - pub fn imported_name(name: ast::Name, attrs: &[ast::Attribute]) -> InternedString { match attr::first_attr_value_str_by_name(attrs, "link_name") { Some(ln) => ln.clone(), @@ -2826,7 +2785,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reachable_symbols.extend(syms.into_iter().filter(|did| { sess.cstore.is_extern_item(shared_ccx.tcx(), *did) }).map(|did| { - sess.cstore.item_symbol(did) + let instance = Instance::mono(shared_ccx.tcx(), did); + symbol_names::exported_name(&shared_ccx, instance) })); } } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 3fb8605412075..9694a8b59769f 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -512,7 +512,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, Some(hir_map::NodeImplItem(&hir::ImplItem { ref attrs, id, span, node: hir::ImplItemKind::Method(..), .. })) => { - let sym = exported_name(ccx, instance, attrs); + let sym = symbol_names::exported_name(ccx.shared(), instance); if declare::get_defined_value(ccx, &sym).is_some() { ccx.sess().span_fatal(span, @@ -530,7 +530,8 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, None => { attrs = ccx.sess().cstore.item_attrs(def_id); - (ccx.sess().cstore.item_symbol(def_id), &attrs[..], None) + let sym = symbol_names::exported_name(ccx.shared(), instance); + (sym, &attrs[..], None) } ref variant => { diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 1c393f8091eee..8d273dfe1953c 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -150,7 +150,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, return llfn; } - let symbol = symbol_names::exported_name(ccx, &instance); + let symbol = symbol_names::exported_name(ccx.shared(), instance); // Compute the rust-call form of the closure call method. let sig = &tcx.closure_type(closure_id, substs).sig; diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 7775ed3fc68ae..f26af29b89e24 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -19,7 +19,8 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use {abi, adt, closure, debuginfo, expr, machine}; -use base::{self, exported_name, imported_name, push_ctxt}; +use base::{self, imported_name, push_ctxt}; +use back::symbol_names; use callee::Callee; use collector::{self, TransItem}; use common::{type_is_sized, C_nil, const_get_elt}; @@ -1020,13 +1021,13 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) let llty = type_of::type_of(ccx, ty); match ccx.tcx().map.get(id) { hir_map::NodeItem(&hir::Item { - ref attrs, span, node: hir::ItemStatic(..), .. + span, node: hir::ItemStatic(..), .. }) => { // If this static came from an external crate, then // we need to get the symbol from metadata instead of // using the current crate's name/version // information in the hash of the symbol - let sym = exported_name(ccx, instance, attrs); + let sym = symbol_names::exported_name(ccx.shared(), instance); debug!("making {}", sym); // Create the global before evaluating the initializer; @@ -1103,7 +1104,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) } else { // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? // FIXME(nagisa): investigate whether it can be changed into define_global - let name = ccx.sess().cstore.item_symbol(def_id); + let name = symbol_names::exported_name(ccx.shared(), instance); let g = declare::declare_global(ccx, &name, type_of::type_of(ccx, ty)); // Thread-local statics in some other crate need to *always* be linked // against in a thread-local fashion, so we need to be sure to apply the diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 61137d7f377c2..8e8c690efb99b 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -487,6 +487,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn translation_items(&self) -> &RefCell, TransItemState>> { &self.translation_items } + + pub fn symbol_hasher(&self) -> &RefCell { + &self.symbol_hasher + } } impl<'tcx> LocalCrateContext<'tcx> { diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 8b1809e40233a..37bed9b440a92 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -88,7 +88,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, monomorphizing.insert(fn_id, depth + 1); } - let symbol = symbol_names::exported_name(ccx, &instance); + let symbol = symbol_names::exported_name(ccx.shared(), instance); debug!("monomorphize_fn mangled to {}", symbol); assert!(declare::get_defined_value(ccx, &symbol).is_none()); diff --git a/src/librustc_trans/symbol_names_test.rs b/src/librustc_trans/symbol_names_test.rs index 2e3355968dffa..4aa5ae74169e0 100644 --- a/src/librustc_trans/symbol_names_test.rs +++ b/src/librustc_trans/symbol_names_test.rs @@ -53,7 +53,7 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> { if attr.check_name(SYMBOL_NAME) { // for now, can only use on monomorphic names let instance = Instance::mono(tcx, def_id); - let name = symbol_names::exported_name(self.ccx, &instance); + let name = symbol_names::exported_name(self.ccx.shared(), instance); tcx.sess.span_err(attr.span, &format!("symbol-name({})", name)); } else if attr.check_name(ITEM_PATH) { let path = tcx.item_path_str(def_id); From 073f28962216a6ed6f8980cd4119900949349595 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 01:25:20 +0300 Subject: [PATCH 36/50] trans: force absolute item paths within symbols. --- src/librustc/ty/item_path.rs | 30 +++++++++++++++++++++++-- src/librustc_trans/back/symbol_names.rs | 5 ++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 5246c6739d960..9aaffd76d3984 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -14,12 +14,38 @@ use hir::def_id::{DefId, CRATE_DEF_INDEX}; use ty::{self, Ty, TyCtxt}; use syntax::ast; +use std::cell::Cell; + +thread_local! { + static FORCE_ABSOLUTE: Cell = Cell::new(false) +} + +/// Enforces that item_path_str always returns an absolute path. +/// This is useful when building symbols that contain types, +/// where we want the crate name to be part of the symbol. +pub fn with_forced_absolute_paths R, R>(f: F) -> R { + FORCE_ABSOLUTE.with(|force| { + let old = force.get(); + force.set(true); + let result = f(); + force.set(old); + result + }) +} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns a string identifying this def-id. This string is /// suitable for user output. It is relative to the current crate - /// root. + /// root, unless with_forced_absolute_paths was used. pub fn item_path_str(self, def_id: DefId) -> String { - let mut buffer = LocalPathBuffer::new(RootMode::Local); + let mode = FORCE_ABSOLUTE.with(|force| { + if force.get() { + RootMode::Absolute + } else { + RootMode::Local + } + }); + let mut buffer = LocalPathBuffer::new(mode); self.push_item_path(&mut buffer, def_id); buffer.into_string() } diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index dffd0beafe51b..27b695b913785 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -265,7 +265,10 @@ pub fn exported_name<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let mut buffer = SymbolPathBuffer { names: Vec::with_capacity(def_path.data.len()) }; - ccx.tcx().push_item_path(&mut buffer, def_id); + + item_path::with_forced_absolute_paths(|| { + scx.tcx().push_item_path(&mut buffer, def_id); + }); mangle(buffer.names.into_iter(), Some(&hash[..])) } From 843b174e93b253824a62fba3ac4be2753e30c9c2 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 2 May 2016 14:52:48 +0200 Subject: [PATCH 37/50] typeck: if a private field exists, also check for a public method For example, `Vec::len` is both a field and a method, and usually encountering `vec.len` just means that the parens were forgotten. Fixes: #26472 --- src/librustc_typeck/check/method/mod.rs | 5 +++-- src/librustc_typeck/check/mod.rs | 12 +++++++++--- src/test/compile-fail/issue-26472.rs | 24 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/issue-26472.rs diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f27ae181f77e3..00eeefa0449ce 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -84,7 +84,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, method_name: ast::Name, self_ty: ty::Ty<'tcx>, - call_expr_id: ast::NodeId) + call_expr_id: ast::NodeId, + allow_private: bool) -> bool { let mode = probe::Mode::MethodCall; @@ -93,7 +94,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Err(NoMatch(..)) => false, Err(Ambiguity(..)) => true, Err(ClosureAmbiguity(..)) => true, - Err(PrivateMatch(..)) => true, + Err(PrivateMatch(..)) => allow_private, } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f428023da9b82..060075e6f0d90 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3045,12 +3045,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some((did, field_ty)) = private_candidate { let struct_path = self.tcx().item_path_str(did); - let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path); - self.tcx().sess.span_err(expr.span, &msg); self.write_ty(expr.id, field_ty); + let msg = format!("field `{}` of struct `{}` is private", field.node, struct_path); + let mut err = self.tcx().sess.struct_span_err(expr.span, &msg); + // Also check if an accessible method exists, which is often what is meant. + if self.method_exists(field.span, field.node, expr_t, expr.id, false) { + err.note(&format!("a method `{}` also exists, perhaps you wish to call it", + field.node)); + } + err.emit(); } else if field.node == keywords::Invalid.name() { self.write_error(expr.id); - } else if self.method_exists(field.span, field.node, expr_t, expr.id) { + } else if self.method_exists(field.span, field.node, expr_t, expr.id, true) { self.type_error_struct(field.span, |actual| { format!("attempted to take value of method `{}` on type \ `{}`", field.node, actual) diff --git a/src/test/compile-fail/issue-26472.rs b/src/test/compile-fail/issue-26472.rs new file mode 100644 index 0000000000000..0d59a897ef1af --- /dev/null +++ b/src/test/compile-fail/issue-26472.rs @@ -0,0 +1,24 @@ +// Copyright 2016 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. + +mod sub { + pub struct S { len: usize } + impl S { + pub fn new() -> S { S { len: 0 } } + pub fn len(&self) -> usize { self.len } + } +} + +fn main() { + let s = sub::S::new(); + let v = s.len; + //~^ ERROR field `len` of struct `sub::S` is private + //~| NOTE a method `len` also exists, perhaps you wish to call it +} From c3310327552163e2d19bea1f38287dab22d38028 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Mon, 9 May 2016 23:09:25 +0900 Subject: [PATCH 38/50] Better handling of tab in error --- src/libsyntax/errors/snippet/mod.rs | 10 ++++++++-- src/libsyntax/errors/snippet/test.rs | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/errors/snippet/mod.rs b/src/libsyntax/errors/snippet/mod.rs index 237e6823e0f87..0699c6f4ac2a9 100644 --- a/src/libsyntax/errors/snippet/mod.rs +++ b/src/libsyntax/errors/snippet/mod.rs @@ -312,9 +312,15 @@ impl StyledBuffer { self.text[line][col] = chr; self.styles[line][col] = style; } else { - while self.text[line].len() < col { - self.text[line].push(' '); + let mut i = self.text[line].len(); + while i < col { + let s = match self.text[0].get(i) { + Some(&'\t') => '\t', + _ => ' ' + }; + self.text[line].push(s); self.styles[line].push(Style::NoStyle); + i += 1; } self.text[line].push(chr); self.styles[line].push(style); diff --git a/src/libsyntax/errors/snippet/test.rs b/src/libsyntax/errors/snippet/test.rs index 5a888b488191b..62ce3fa9dd5e9 100644 --- a/src/libsyntax/errors/snippet/test.rs +++ b/src/libsyntax/errors/snippet/test.rs @@ -79,6 +79,30 @@ fn make_string(lines: &[RenderedLine]) -> String { .collect() } +#[test] +fn tab() { + let file_text = " +fn foo() { +\tbar; +} +"; + + let cm = Rc::new(CodeMap::new()); + let foo = cm.new_filemap_and_lines("foo.rs", file_text); + let span_bar = cm.span_substr(&foo, file_text, "bar", 0); + + let mut snippet = SnippetData::new(cm, Some(span_bar)); + snippet.push(span_bar, true, None); + + let lines = snippet.render_lines(); + let text = make_string(&lines); + assert_eq!(&text[..], &" + --> foo.rs:3:2 +3 |> \tbar; + |> \t^^^ +"[1..]); +} + #[test] fn one_line() { let file_text = r#" From df4fe5fbd44d8b4d698397dc8a05db56fbd9ab42 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 12 May 2016 10:40:10 -0400 Subject: [PATCH 39/50] update "reason" for fnbox feature gate It isn't "newly introduced" anymore. --- src/liballoc/boxed.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 7bdf9eaccc323..20645dc90a810 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -525,14 +525,14 @@ impl ExactSizeIterator for Box {} /// } /// ``` #[rustc_paren_sugar] -#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")] +#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] pub trait FnBox { type Output; fn call_box(self: Box, args: A) -> Self::Output; } -#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")] +#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl FnBox for F where F: FnOnce { type Output = F::Output; @@ -542,7 +542,7 @@ impl FnBox for F where F: FnOnce } } -#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")] +#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + 'a> { type Output = R; @@ -551,7 +551,7 @@ impl<'a, A, R> FnOnce for Box + 'a> { } } -#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")] +#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + Send + 'a> { type Output = R; From b9fce76f470ca95e6801c19a82ebac874d34e92f Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 12 May 2016 10:59:37 -0400 Subject: [PATCH 40/50] fix tidy --- src/liballoc/boxed.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 20645dc90a810..10e4ea1c3f055 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -525,14 +525,16 @@ impl ExactSizeIterator for Box {} /// } /// ``` #[rustc_paren_sugar] -#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] +#[unstable(feature = "fnbox", + reason = "will be deprecated if and when Box becomes usable", issue = "28796")] pub trait FnBox { type Output; fn call_box(self: Box, args: A) -> Self::Output; } -#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] +#[unstable(feature = "fnbox", + reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl FnBox for F where F: FnOnce { type Output = F::Output; @@ -542,7 +544,8 @@ impl FnBox for F where F: FnOnce } } -#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] +#[unstable(feature = "fnbox", + reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + 'a> { type Output = R; @@ -551,7 +554,8 @@ impl<'a, A, R> FnOnce for Box + 'a> { } } -#[unstable(feature = "fnbox", reason = "will be deprecated if and when Box becomes usable", issue = "28796")] +#[unstable(feature = "fnbox", + reason = "will be deprecated if and when Box becomes usable", issue = "28796")] impl<'a, A, R> FnOnce for Box + Send + 'a> { type Output = R; From 9393e52d4d2705698a6dfdd2834d41154ee23b64 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 8 May 2016 12:07:50 -0700 Subject: [PATCH 41/50] Don't use env::current_exe with libbacktrace If the path we give to libbacktrace doesn't actually correspond to the current process, libbacktrace will segfault *at best*. cc #21889 --- src/libstd/sys/common/gnu/libbacktrace.rs | 49 ++++++----------------- src/test/run-pass/backtrace-debuginfo.rs | 14 ++++--- src/test/run-pass/backtrace.rs | 2 +- 3 files changed, 22 insertions(+), 43 deletions(-) diff --git a/src/libstd/sys/common/gnu/libbacktrace.rs b/src/libstd/sys/common/gnu/libbacktrace.rs index db719ccce61e8..b5802afc10943 100644 --- a/src/libstd/sys/common/gnu/libbacktrace.rs +++ b/src/libstd/sys/common/gnu/libbacktrace.rs @@ -15,7 +15,6 @@ use sys_common::backtrace::{output, output_fileline}; pub fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, symaddr: *mut libc::c_void) -> io::Result<()> { - use env; use ffi::CStr; use ptr; @@ -110,46 +109,22 @@ pub fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, // that is calculated the first time this is requested. Remember that // backtracing all happens serially (one global lock). // - // An additionally oddity in this function is that we initialize the - // filename via self_exe_name() to pass to libbacktrace. It turns out - // that on Linux libbacktrace seamlessly gets the filename of the - // current executable, but this fails on freebsd. by always providing - // it, we make sure that libbacktrace never has a reason to not look up - // the symbols. The libbacktrace API also states that the filename must - // be in "permanent memory", so we copy it to a static and then use the - // static as the pointer. + // Things don't work so well on not-Linux since libbacktrace can't track + // down that executable this is. We at one point used env::current_exe but + // it turns out that there are some serious security issues with that + // approach. // - // FIXME: We also call self_exe_name() on DragonFly BSD. I haven't - // tested if this is required or not. + // Specifically, on certain platforms like BSDs, a malicious actor can cause + // an arbitrary file to be placed at the path returned by current_exe. + // libbacktrace does not behave defensively in the presence of ill-formed + // DWARF information, and has been demonstrated to segfault in at least one + // case. There is no evidence at the moment to suggest that a more carefully + // constructed file can't cause arbitrary code execution. As a result of all + // of this, we don't hint libbacktrace with the path to the current process. unsafe fn init_state() -> *mut backtrace_state { static mut STATE: *mut backtrace_state = ptr::null_mut(); - static mut LAST_FILENAME: [libc::c_char; 256] = [0; 256]; if !STATE.is_null() { return STATE } - let selfname = if cfg!(target_os = "freebsd") || - cfg!(target_os = "dragonfly") || - cfg!(target_os = "bitrig") || - cfg!(target_os = "openbsd") || - cfg!(target_os = "windows") { - env::current_exe().ok() - } else { - None - }; - let filename = match selfname.as_ref().and_then(|s| s.to_str()) { - Some(path) => { - let bytes = path.as_bytes(); - if bytes.len() < LAST_FILENAME.len() { - let i = bytes.iter(); - for (slot, val) in LAST_FILENAME.iter_mut().zip(i) { - *slot = *val as libc::c_char; - } - LAST_FILENAME.as_ptr() - } else { - ptr::null() - } - } - None => ptr::null(), - }; - STATE = backtrace_create_state(filename, 0, error_cb, + STATE = backtrace_create_state(ptr::null(), 0, error_cb, ptr::null_mut()); STATE } diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index 8b2b26948824f..f42a6ab162b70 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -32,11 +32,15 @@ macro_rules! dump_and_die { ($($pos:expr),*) => ({ // FIXME(#18285): we cannot include the current position because // the macro span takes over the last frame's file/line. - if cfg!(target_os = "macos") || - cfg!(target_os = "ios") || - cfg!(target_os = "android") || - cfg!(all(target_os = "linux", target_arch = "arm")) || - cfg!(all(windows, target_env = "gnu")) { + if cfg!(any(target_os = "macos", + target_os = "ios", + target_os = "android", + all(target_os = "linux", target_arch = "arm"), + target_os = "windows", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "bitrig", + target_os = "openbsd")) { // skip these platforms as this support isn't implemented yet. } else { dump_filelines(&[$($pos),*]); diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index 5b364358a59dd..ad38dc8f45252 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -115,7 +115,7 @@ fn runtest(me: &str) { } fn main() { - if cfg!(windows) && cfg!(target_arch = "x86") && cfg!(target_env = "gnu") { + if cfg!(windows) && cfg!(target_env = "gnu") { return } From f7362caad86219f5f674b97891d1cbaf50ea7fea Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 19:52:38 +0300 Subject: [PATCH 42/50] trans: move exported_symbol to Instance::symbol_name. --- src/librustc/middle/cstore.rs | 2 + src/librustc_metadata/csearch.rs | 5 + src/librustc_metadata/decoder.rs | 10 ++ src/librustc_metadata/encoder.rs | 2 + src/librustc_trans/back/symbol_names.rs | 148 +++++++++++--------- src/librustc_trans/base.rs | 28 ++-- src/librustc_trans/callee.rs | 47 +++---- src/librustc_trans/closure.rs | 2 +- src/librustc_trans/consts.rs | 20 ++- src/librustc_trans/monomorphize.rs | 3 +- src/librustc_trans/symbol_names_test.rs | 4 +- src/test/compile-fail/symbol-names/impl1.rs | 2 +- 12 files changed, 146 insertions(+), 127 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index c0af457ed236c..07f7052c0ed6d 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -210,6 +210,7 @@ pub trait CrateStore<'tcx> : Any { fn is_impl(&self, did: DefId) -> bool; fn is_default_impl(&self, impl_did: DefId) -> bool; fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool; + fn is_foreign_item(&self, did: DefId) -> bool; fn is_static_method(&self, did: DefId) -> bool; fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool; fn is_typedef(&self, did: DefId) -> bool; @@ -394,6 +395,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") } fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool { bug!("is_extern_item") } + fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") } fn is_static_method(&self, did: DefId) -> bool { bug!("is_static_method") } fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false } fn is_typedef(&self, did: DefId) -> bool { bug!("is_typedef") } diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 8d464099783a6..7e039867a7877 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -252,6 +252,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::is_extern_item(&cdata, did.index, tcx) } + fn is_foreign_item(&self, did: DefId) -> bool { + let cdata = self.get_crate_data(did.krate); + decoder::is_foreign_item(&cdata, did.index) + } + fn is_static_method(&self, def: DefId) -> bool { let cdata = self.get_crate_data(def.krate); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0d11998f21c58..834ea7c027bd1 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1603,6 +1603,16 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd, } } +pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool { + let item_doc = cdata.lookup_item(id); + let parent_item_id = match item_parent_item(cdata, item_doc) { + None => return false, + Some(item_id) => item_id, + }; + let parent_item_doc = cdata.lookup_item(parent_item_id.index); + item_family(parent_item_doc) == ForeignMod +} + pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool { let item_doc = cdata.lookup_item(id); match item_family(item_doc) { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 020f12d753e63..e43c9cdfe4abb 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1344,6 +1344,8 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, index.record(def_id, rbml_w); rbml_w.start_tag(tag_items_data_item); encode_def_id_and_key(ecx, rbml_w, def_id); + let parent_id = ecx.tcx.map.get_parent(nitem.id); + encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id)); encode_visibility(rbml_w, &nitem.vis); match nitem.node { hir::ForeignItemFn(ref fndecl, _) => { diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 27b695b913785..49c7225306b25 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -103,6 +103,7 @@ use util::sha2::{Digest, Sha256}; use rustc::middle::{cstore, weak_lang_items}; use rustc::hir::def_id::DefId; +use rustc::hir::map as hir_map; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; use rustc::hir::map::definitions::{DefPath, DefPathData}; @@ -188,89 +189,100 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, } } -pub fn exported_name<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, - instance: Instance<'tcx>) - -> String { - let Instance { def: def_id, ref substs } = instance; +impl<'a, 'tcx> Instance<'tcx> { + pub fn symbol_name(self, scx: &SharedCrateContext<'a, 'tcx>) -> String { + let Instance { def: def_id, ref substs } = self; - debug!("exported_name(def_id={:?}, substs={:?})", - def_id, substs); + debug!("symbol_name(def_id={:?}, substs={:?})", + def_id, substs); - let node_id = scx.tcx().map.as_local_node_id(instance.def); + let node_id = scx.tcx().map.as_local_node_id(def_id); - if let Some(id) = node_id { - if scx.sess().plugin_registrar_fn.get() == Some(id) { - let svh = &scx.link_meta().crate_hash; - let idx = instance.def.index; - return scx.sess().generate_plugin_registrar_symbol(svh, idx); + if let Some(id) = node_id { + if scx.sess().plugin_registrar_fn.get() == Some(id) { + let svh = &scx.link_meta().crate_hash; + let idx = def_id.index; + return scx.sess().generate_plugin_registrar_symbol(svh, idx); + } } - } - - // FIXME(eddyb) Precompute a custom symbol name based on attributes. - let attrs; - let attrs = if let Some(id) = node_id { - scx.tcx().map.attrs(id) - } else { - attrs = scx.sess().cstore.item_attrs(def_id); - &attrs[..] - }; - if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), attrs) { - // Use provided name - return name.to_string(); - } + // FIXME(eddyb) Precompute a custom symbol name based on attributes. + let attrs = scx.tcx().get_attrs(def_id); + let is_foreign = if let Some(id) = node_id { + match scx.tcx().map.get(id) { + hir_map::NodeForeignItem(_) => true, + _ => false + } + } else { + scx.sess().cstore.is_foreign_item(def_id) + }; - if attr::contains_name(attrs, "no_mangle") { - // Don't mangle - return scx.tcx().item_name(instance.def).as_str().to_string() - } - if let Some(name) = weak_lang_items::link_name(attrs) { - return name.to_string(); - } + if let Some(name) = weak_lang_items::link_name(&attrs) { + return name.to_string(); + } - let def_path = scx.tcx().def_path(def_id); - - // We want to compute the "type" of this item. Unfortunately, some - // kinds of items (e.g., closures) don't have an entry in the - // item-type array. So walk back up the find the closest parent - // that DOES have an entry. - let mut ty_def_id = def_id; - let instance_ty; - loop { - let key = scx.tcx().def_key(ty_def_id); - match key.disambiguated_data.data { - DefPathData::TypeNs(_) | - DefPathData::ValueNs(_) => { - instance_ty = scx.tcx().lookup_item_type(ty_def_id); - break; + if is_foreign { + if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") { + return name.to_string(); } - _ => { - // if we're making a symbol for something, there ought - // to be a value or type-def or something in there - // *somewhere* - ty_def_id.index = key.parent.unwrap_or_else(|| { - bug!("finding type for {:?}, encountered def-id {:?} with no \ - parent", def_id, ty_def_id); - }); + // Don't mangle foreign items. + return scx.tcx().item_name(def_id).as_str().to_string(); + } + + if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), &attrs) { + // Use provided name + return name.to_string(); + } + + if attr::contains_name(&attrs, "no_mangle") { + // Don't mangle + return scx.tcx().item_name(def_id).as_str().to_string(); + } + + let def_path = scx.tcx().def_path(def_id); + + // We want to compute the "type" of this item. Unfortunately, some + // kinds of items (e.g., closures) don't have an entry in the + // item-type array. So walk back up the find the closest parent + // that DOES have an entry. + let mut ty_def_id = def_id; + let instance_ty; + loop { + let key = scx.tcx().def_key(ty_def_id); + match key.disambiguated_data.data { + DefPathData::TypeNs(_) | + DefPathData::ValueNs(_) => { + instance_ty = scx.tcx().lookup_item_type(ty_def_id); + break; + } + _ => { + // if we're making a symbol for something, there ought + // to be a value or type-def or something in there + // *somewhere* + ty_def_id.index = key.parent.unwrap_or_else(|| { + bug!("finding type for {:?}, encountered def-id {:?} with no \ + parent", def_id, ty_def_id); + }); + } } } - } - // Erase regions because they may not be deterministic when hashed - // and should not matter anyhow. - let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); + // Erase regions because they may not be deterministic when hashed + // and should not matter anyhow. + let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); - let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice()); + let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice()); - let mut buffer = SymbolPathBuffer { - names: Vec::with_capacity(def_path.data.len()) - }; + let mut buffer = SymbolPathBuffer { + names: Vec::with_capacity(def_path.data.len()) + }; - item_path::with_forced_absolute_paths(|| { - scx.tcx().push_item_path(&mut buffer, def_id); - }); + item_path::with_forced_absolute_paths(|| { + scx.tcx().push_item_path(&mut buffer, def_id); + }); - mangle(buffer.names.into_iter(), Some(&hash[..])) + mangle(buffer.names.into_iter(), Some(&hash[..])) + } } struct SymbolPathBuffer { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 5fe2aaa35e31d..3e3160496f3d3 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -30,7 +30,7 @@ pub use self::ValueOrigin::*; use super::CrateTranslation; use super::ModuleTranslation; -use back::{link, symbol_names}; +use back::link; use lint; use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param}; use llvm; @@ -2629,10 +2629,7 @@ fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter { /// This list is later used by linkers to determine the set of symbols needed to /// be exposed from a dynamic library and it's also encoded into the metadata. pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet { - scx.reachable().iter().map(|x| *x).filter(|id| { - // First, only worry about nodes which have a symbol name - scx.item_symbols().borrow().contains_key(id) - }).filter(|&id| { + scx.reachable().iter().map(|x| *x).filter(|&id| { // Next, we want to ignore some FFI functions that are not exposed from // this crate. Reachable FFI functions can be lumped into two // categories: @@ -2650,7 +2647,18 @@ pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet { hir_map::NodeForeignItem(..) => { scx.sess().cstore.is_statically_included_foreign_item(id) } - _ => true, + + // Only consider nodes that actually have exported symbols. + hir_map::NodeItem(&hir::Item { + node: hir::ItemStatic(..), .. }) | + hir_map::NodeItem(&hir::Item { + node: hir::ItemFn(..), .. }) | + hir_map::NodeTraitItem(&hir::TraitItem { + node: hir::MethodTraitItem(_, Some(_)), .. }) | + hir_map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method(..), .. }) => true, + + _ => false } }).collect() } @@ -2769,8 +2777,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .collect(); let sess = shared_ccx.sess(); - let mut reachable_symbols = reachable_symbol_ids.iter().map(|id| { - shared_ccx.item_symbols().borrow()[id].to_string() + let mut reachable_symbols = reachable_symbol_ids.iter().map(|&id| { + let def_id = shared_ccx.tcx().map.local_def_id(id); + Instance::mono(shared_ccx.tcx(), def_id).symbol_name(&shared_ccx) }).collect::>(); if sess.entry_fn.borrow().is_some() { reachable_symbols.push("main".to_string()); @@ -2785,8 +2794,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reachable_symbols.extend(syms.into_iter().filter(|did| { sess.cstore.is_extern_item(shared_ccx.tcx(), *did) }).map(|did| { - let instance = Instance::mono(shared_ccx.tcx(), did); - symbol_names::exported_name(&shared_ccx, instance) + Instance::mono(shared_ccx.tcx(), did).symbol_name(&shared_ccx) })); } } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 9694a8b59769f..e97b1dfa13416 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -499,44 +499,20 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, return immediate_rvalue(llfn, fn_ptr_ty); } - let attrs; let local_id = ccx.tcx().map.as_local_node_id(def_id); - let maybe_node = local_id.and_then(|id| tcx.map.find(id)); - let (sym, attrs, local_item) = match maybe_node { + let local_item = match local_id.and_then(|id| tcx.map.find(id)) { Some(hir_map::NodeItem(&hir::Item { - ref attrs, id, span, node: hir::ItemFn(..), .. + span, node: hir::ItemFn(..), .. })) | Some(hir_map::NodeTraitItem(&hir::TraitItem { - ref attrs, id, span, node: hir::MethodTraitItem(_, Some(_)), .. + span, node: hir::MethodTraitItem(_, Some(_)), .. })) | Some(hir_map::NodeImplItem(&hir::ImplItem { - ref attrs, id, span, node: hir::ImplItemKind::Method(..), .. + span, node: hir::ImplItemKind::Method(..), .. })) => { - let sym = symbol_names::exported_name(ccx.shared(), instance); - - if declare::get_defined_value(ccx, &sym).is_some() { - ccx.sess().span_fatal(span, - &format!("symbol `{}` is already defined", sym)); - } - - (sym, &attrs[..], Some(id)) - } - - Some(hir_map::NodeForeignItem(&hir::ForeignItem { - ref attrs, name, node: hir::ForeignItemFn(..), .. - })) => { - (imported_name(name, attrs).to_string(), &attrs[..], None) - } - - None => { - attrs = ccx.sess().cstore.item_attrs(def_id); - let sym = symbol_names::exported_name(ccx.shared(), instance); - (sym, &attrs[..], None) - } - - ref variant => { - bug!("get_fn: unexpected variant: {:?}", variant) + Some(span) } + _ => None }; // This is subtle and surprising, but sometimes we have to bitcast @@ -563,8 +539,16 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // reference. It also occurs when testing libcore and in some // other weird situations. Annoying. + let sym = instance.symbol_name(ccx.shared()); let llptrty = type_of::type_of(ccx, fn_ptr_ty); let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) { + if let Some(span) = local_item { + if declare::get_defined_value(ccx, &sym).is_some() { + ccx.sess().span_fatal(span, + &format!("symbol `{}` is already defined", sym)); + } + } + if common::val_ty(llfn) != llptrty { if local_item.is_some() { bug!("symbol `{}` previously declared as {:?}, now wanted as {:?}", @@ -581,7 +565,8 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, assert_eq!(common::val_ty(llfn), llptrty); debug!("get_fn: not casting pointer!"); - attributes::from_fn_attrs(ccx, attrs, llfn); + let attrs = ccx.tcx().get_attrs(def_id); + attributes::from_fn_attrs(ccx, &attrs, llfn); if local_item.is_some() { // FIXME(eddyb) Doubt all extern fn should allow unwinding. attributes::unwind(llfn, true); diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 8d273dfe1953c..5e0d34c2a674d 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -150,7 +150,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, return llfn; } - let symbol = symbol_names::exported_name(ccx.shared(), instance); + let symbol = instance.symbol_name(ccx.shared()); // Compute the rust-call form of the closure call method. let sig = &tcx.closure_type(closure_id, substs).sig; diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index f26af29b89e24..7b6ecdf30109d 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -19,8 +19,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use {abi, adt, closure, debuginfo, expr, machine}; -use base::{self, imported_name, push_ctxt}; -use back::symbol_names; +use base::{self, push_ctxt}; use callee::Callee; use collector::{self, TransItem}; use common::{type_is_sized, C_nil, const_get_elt}; @@ -1017,6 +1016,8 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) return Datum::new(g, ty, Lvalue::new("static")); } + let sym = instance.symbol_name(ccx.shared()); + let g = if let Some(id) = ccx.tcx().map.as_local_node_id(def_id) { let llty = type_of::type_of(ccx, ty); match ccx.tcx().map.get(id) { @@ -1027,7 +1028,6 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) // we need to get the symbol from metadata instead of // using the current crate's name/version // information in the hash of the symbol - let sym = symbol_names::exported_name(ccx.shared(), instance); debug!("making {}", sym); // Create the global before evaluating the initializer; @@ -1042,9 +1042,8 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) } hir_map::NodeForeignItem(&hir::ForeignItem { - ref attrs, name, span, node: hir::ForeignItemStatic(..), .. + ref attrs, span, node: hir::ForeignItemStatic(..), .. }) => { - let ident = imported_name(name, attrs); let g = if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "linkage") { // If this is a static with a linkage specified, then we need to handle @@ -1066,7 +1065,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) }; unsafe { // Declare a symbol `foo` with the desired linkage. - let g1 = declare::declare_global(ccx, &ident, llty2); + let g1 = declare::declare_global(ccx, &sym, llty2); llvm::SetLinkage(g1, linkage); // Declare an internal global `extern_with_linkage_foo` which @@ -1076,10 +1075,10 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) // `extern_with_linkage_foo` will instead be initialized to // zero. let mut real_name = "_rust_extern_with_linkage_".to_string(); - real_name.push_str(&ident); + real_name.push_str(&sym); let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{ ccx.sess().span_fatal(span, - &format!("symbol `{}` is already defined", ident)) + &format!("symbol `{}` is already defined", sym)) }); llvm::SetLinkage(g2, llvm::InternalLinkage); llvm::LLVMSetInitializer(g2, g1); @@ -1087,7 +1086,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) } } else { // Generate an external declaration. - declare::declare_global(ccx, &ident, llty) + declare::declare_global(ccx, &sym, llty) }; for attr in attrs { @@ -1104,8 +1103,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) } else { // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? // FIXME(nagisa): investigate whether it can be changed into define_global - let name = symbol_names::exported_name(ccx.shared(), instance); - let g = declare::declare_global(ccx, &name, type_of::type_of(ccx, ty)); + let g = declare::declare_global(ccx, &sym, type_of::type_of(ccx, ty)); // Thread-local statics in some other crate need to *always* be linked // against in a thread-local fashion, so we need to be sure to apply the // thread-local attribute locally if it was present remotely. If we diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 37bed9b440a92..6dc93c787330f 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use back::symbol_names; use llvm::ValueRef; use llvm; use rustc::hir::def_id::DefId; @@ -88,7 +87,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, monomorphizing.insert(fn_id, depth + 1); } - let symbol = symbol_names::exported_name(ccx.shared(), instance); + let symbol = instance.symbol_name(ccx.shared()); debug!("monomorphize_fn mangled to {}", symbol); assert!(declare::get_defined_value(ccx, &symbol).is_none()); diff --git a/src/librustc_trans/symbol_names_test.rs b/src/librustc_trans/symbol_names_test.rs index 4aa5ae74169e0..b84394e474ec3 100644 --- a/src/librustc_trans/symbol_names_test.rs +++ b/src/librustc_trans/symbol_names_test.rs @@ -14,7 +14,6 @@ //! item-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. -use back::symbol_names; use rustc::hir; use rustc::hir::intravisit::{self, Visitor}; use syntax::ast; @@ -52,8 +51,7 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> { for attr in tcx.get_attrs(def_id).iter() { if attr.check_name(SYMBOL_NAME) { // for now, can only use on monomorphic names - let instance = Instance::mono(tcx, def_id); - let name = symbol_names::exported_name(self.ccx.shared(), instance); + let name = Instance::mono(tcx, def_id).symbol_name(self.ccx.shared()); tcx.sess.span_err(attr.span, &format!("symbol-name({})", name)); } else if attr.check_name(ITEM_PATH) { let path = tcx.item_path_str(def_id); diff --git a/src/test/compile-fail/symbol-names/impl1.rs b/src/test/compile-fail/symbol-names/impl1.rs index 39bee26da20b8..93fa48b880fdf 100644 --- a/src/test/compile-fail/symbol-names/impl1.rs +++ b/src/test/compile-fail/symbol-names/impl1.rs @@ -25,7 +25,7 @@ mod bar { use foo::Foo; impl Foo { - #[rustc_symbol_name] //~ ERROR _ZN5impl13bar26_$LT$impl$u20$foo..Foo$GT$3baz + #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz #[rustc_item_path] //~ ERROR item-path(bar::::baz) fn baz() { } } From ff3a1ce9fce3e8c83bab9b5ecb5917556d5a6dbb Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 19:57:23 +0300 Subject: [PATCH 43/50] trans: move the MSVC linker to compute symbols on-demand. --- src/librustc_trans/back/link.rs | 13 +--- src/librustc_trans/back/linker.rs | 121 ++++++++++++++++++++---------- src/librustc_trans/base.rs | 3 + src/librustc_trans/lib.rs | 1 + 4 files changed, 91 insertions(+), 47 deletions(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 00d9658cb5943..c54432c6e5838 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -9,7 +9,7 @@ // except according to those terms. use super::archive::{ArchiveBuilder, ArchiveConfig}; -use super::linker::{Linker, GnuLinker, MsvcLinker}; +use super::linker::Linker; use super::rpath::RPathConfig; use super::rpath; use super::msvc; @@ -634,13 +634,9 @@ fn link_natively(sess: &Session, dylib: bool, } { - let mut linker = if sess.target.target.options.is_like_msvc { - Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box - } else { - Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box - }; + let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, dylib, tmpdir, - objects, out_filename, trans, outputs); + objects, out_filename, outputs); if !sess.target.target.options.no_compiler_rt { linker.link_staticlib("compiler-rt"); } @@ -709,7 +705,6 @@ fn link_args(cmd: &mut Linker, tmpdir: &Path, objects: &[PathBuf], out_filename: &Path, - trans: &CrateTranslation, outputs: &OutputFilenames) { // The default library location, we need this to find the runtime. @@ -728,7 +723,7 @@ fn link_args(cmd: &mut Linker, // If we're building a dynamic library then some platforms need to make sure // that all symbols are exported correctly from the dynamic library. if dylib { - cmd.export_symbols(sess, trans, tmpdir); + cmd.export_symbols(tmpdir); } // When linking a dynamic library, we put the metadata into a section of the diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 8055e97034e3f..858fe65c0fc7f 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -9,19 +9,91 @@ // except according to those terms. use std::ffi::OsString; +use std::fmt::Write as FmtWrite; use std::fs::{self, File}; use std::io::{self, BufWriter}; use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; +use context::SharedCrateContext; +use monomorphize::Instance; + use back::archive; use middle::dependency_format::Linkage; use session::Session; use session::config::CrateTypeDylib; use session::config; use syntax::ast; -use CrateTranslation; + +/// For all the linkers we support, and information they might +/// need out of the shared crate context before we get rid of it. +pub enum LinkerInfo { + Gnu, + Msvc { + dylib_exports: String + } +} + +impl<'a, 'tcx> LinkerInfo { + pub fn new(scx: &SharedCrateContext<'a, 'tcx>, + reachable: &[String]) -> LinkerInfo { + if scx.sess().target.target.options.is_like_msvc { + let mut exports = String::new(); + if scx.sess().crate_types.borrow().contains(&CrateTypeDylib) { + for sym in reachable { + writeln!(exports, " {}", sym).unwrap(); + } + + // Take a look at how all upstream crates are linked into this + // dynamic library. For all statically linked libraries we take all + // their reachable symbols and emit them as well. + let cstore = &scx.sess().cstore; + let formats = scx.sess().dependency_formats.borrow(); + let symbols = formats[&CrateTypeDylib].iter(); + let symbols = symbols.enumerate().filter_map(|(i, f)| { + if *f == Linkage::Static { + Some((i + 1) as ast::CrateNum) + } else { + None + } + }).flat_map(|cnum| { + cstore.reachable_ids(cnum) + }).map(|did| -> String { + Instance::mono(scx.tcx(), did).symbol_name(scx) + }); + for symbol in symbols { + writeln!(exports, " {}", symbol).unwrap(); + } + } + LinkerInfo::Msvc { + dylib_exports: exports + } + } else { + LinkerInfo::Gnu + } + } + + pub fn to_linker(&'a self, + cmd: &'a mut Command, + sess: &'a Session) -> Box { + match *self { + LinkerInfo::Gnu => { + Box::new(GnuLinker { + cmd: cmd, + sess: sess + }) as Box + } + LinkerInfo::Msvc { ref dylib_exports } => { + Box::new(MsvcLinker { + cmd: cmd, + sess: sess, + dylib_exports: dylib_exports + }) as Box + } + } + } +} /// Linker abstraction used by back::link to build up the command to invoke a /// linker. @@ -53,13 +125,12 @@ pub trait Linker { fn hint_dynamic(&mut self); fn whole_archives(&mut self); fn no_whole_archives(&mut self); - fn export_symbols(&mut self, sess: &Session, trans: &CrateTranslation, - tmpdir: &Path); + fn export_symbols(&mut self, tmpdir: &Path); } pub struct GnuLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, } impl<'a> GnuLinker<'a> { @@ -198,14 +269,15 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg("-Wl,-Bdynamic"); } - fn export_symbols(&mut self, _: &Session, _: &CrateTranslation, _: &Path) { + fn export_symbols(&mut self, _: &Path) { // noop, visibility in object files takes care of this } } pub struct MsvcLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, + dylib_exports: &'a str } impl<'a> Linker for MsvcLinker<'a> { @@ -322,8 +394,7 @@ impl<'a> Linker for MsvcLinker<'a> { // crates. Upstream rlibs may be linked statically to this dynamic library, // in which case they may continue to transitively be used and hence need // their symbols exported. - fn export_symbols(&mut self, sess: &Session, trans: &CrateTranslation, - tmpdir: &Path) { + fn export_symbols(&mut self, tmpdir: &Path) { let path = tmpdir.join("lib.def"); let res = (|| -> io::Result<()> { let mut f = BufWriter::new(File::create(&path)?); @@ -332,37 +403,11 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - - // Write out all our local symbols - for sym in trans.reachable.iter() { - writeln!(f, " {}", sym)?; - } - - // Take a look at how all upstream crates are linked into this - // dynamic library. For all statically linked libraries we take all - // their reachable symbols and emit them as well. - let cstore = &sess.cstore; - let formats = sess.dependency_formats.borrow(); - let symbols = formats[&CrateTypeDylib].iter(); - let symbols = symbols.enumerate().filter_map(|(i, f)| { - if *f == Linkage::Static { - Some((i + 1) as ast::CrateNum) - } else { - None - } - }).flat_map(|cnum| { - cstore.reachable_ids(cnum) - }).map(|did| { - cstore.item_symbol(did) - }); - for symbol in symbols { - writeln!(f, " {}", symbol)?; - } - + f.write(self.dylib_exports.as_bytes())?; Ok(()) })(); if let Err(e) = res { - sess.fatal(&format!("failed to write lib.def file: {}", e)); + self.sess.fatal(&format!("failed to write lib.def file: {}", e)); } let mut arg = OsString::from("/DEF:"); arg.push(path); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 3e3160496f3d3..6849134661336 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -31,6 +31,7 @@ use super::CrateTranslation; use super::ModuleTranslation; use back::link; +use back::linker::LinkerInfo; use lint; use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param}; use llvm; @@ -2815,6 +2816,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); + let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); CrateTranslation { modules: modules, metadata_module: metadata_module, @@ -2822,6 +2824,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: reachable_symbols, no_builtins: no_builtins, + linker_info: linker_info } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index f48409ec75573..78318aa023c3f 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -144,6 +144,7 @@ pub struct CrateTranslation { pub metadata: Vec, pub reachable: Vec, pub no_builtins: bool, + pub linker_info: back::linker::LinkerInfo } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } From 749494e2ca36ef23956a8824751b3531c2ae51d8 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 19:58:11 +0300 Subject: [PATCH 44/50] trans: remove item_symbols from metadata and CrateContext. --- src/librustc/middle/cstore.rs | 7 +------ src/librustc_metadata/common.rs | 2 +- src/librustc_metadata/csearch.rs | 10 +--------- src/librustc_metadata/decoder.rs | 8 -------- src/librustc_metadata/encoder.rs | 32 +------------------------------- src/librustc_trans/base.rs | 21 --------------------- src/librustc_trans/callee.rs | 5 ----- src/librustc_trans/consts.rs | 7 ++----- src/librustc_trans/context.rs | 10 ---------- 9 files changed, 6 insertions(+), 96 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 07f7052c0ed6d..17b5778994789 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -33,9 +33,8 @@ use mir::mir_map::MirMap; use session::Session; use session::config::PanicStrategy; use session::search_paths::PathKind; -use util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap}; +use util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; use std::any::Any; -use std::cell::RefCell; use std::rc::Rc; use std::path::PathBuf; use syntax::ast; @@ -174,7 +173,6 @@ pub trait CrateStore<'tcx> : Any { fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx>; fn item_attrs(&self, def_id: DefId) -> Vec; - fn item_symbol(&self, def: DefId) -> String; fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>; fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>; fn method_arg_names(&self, did: DefId) -> Vec; @@ -276,7 +274,6 @@ pub trait CrateStore<'tcx> : Any { fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, @@ -354,7 +351,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") } fn item_attrs(&self, def_id: DefId) -> Vec { bug!("item_attrs") } - fn item_symbol(&self, def: DefId) -> String { bug!("item_symbol") } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx> { bug!("trait_def") } fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> @@ -478,7 +474,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 2b972af07ff91..74f97de265898 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -33,7 +33,7 @@ pub const tag_items_data_item_family: usize = 0x24; pub const tag_items_data_item_type: usize = 0x25; -pub const tag_items_data_item_symbol: usize = 0x26; +// GAP 0x26 pub const tag_items_data_item_variant: usize = 0x27; diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 7e039867a7877..6461869344d65 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -23,7 +23,7 @@ use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::map as hir_map; use rustc::mir::repr::Mir; use rustc::mir::mir_map::MirMap; -use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap}; +use rustc::util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; use rustc::session::config::PanicStrategy; use std::cell::RefCell; @@ -105,12 +105,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_item_attrs(&cdata, def_id.index) } - fn item_symbol(&self, def: DefId) -> String - { - let cdata = self.get_crate_data(def.krate); - decoder::get_symbol(&cdata, def.index) - } - fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef<'tcx> { let cdata = self.get_crate_data(def.krate); @@ -517,7 +511,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, @@ -527,7 +520,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { diag: tcx.sess.diagnostic(), tcx: tcx, reexports: reexports, - item_symbols: item_symbols, link_meta: link_meta, cstore: self, reachable: reachable, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 834ea7c027bd1..2c1114e3ee713 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -186,10 +186,6 @@ fn item_sort(item: rbml::Doc) -> Option { }) } -fn item_symbol(item: rbml::Doc) -> String { - reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string() -} - fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId { let id = reader::doc_as_u64(d); let index = DefIndex::new((id & 0xFFFF_FFFF) as usize); @@ -609,10 +605,6 @@ pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, } } -pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String { - return item_symbol(cdata.lookup_item(id)); -} - /// Iterates over the language items in the given crate. pub fn each_lang_item(cdata: Cmd, mut f: F) -> bool where F: FnMut(DefIndex, usize) -> bool, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e43c9cdfe4abb..80c139b1be124 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -33,7 +33,7 @@ use rustc::ty::util::IntTypeExt; use rustc::hir::svh::Svh; use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, PanicStrategy}; -use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet}; +use rustc::util::nodemap::{FnvHashMap, NodeSet}; use rustc_serialize::Encodable; use std::cell::RefCell; @@ -58,7 +58,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> { pub diag: &'a Handler, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub reexports: &'a def::ExportMap, - pub item_symbols: &'a RefCell>, pub link_meta: &'a LinkMeta, pub cstore: &'a cstore::CStore, pub type_abbrevs: tyencode::abbrev_map<'tcx>, @@ -204,20 +203,6 @@ fn encode_region(ecx: &EncodeContext, rbml_w.end_tag(); } -fn encode_symbol(ecx: &EncodeContext, - rbml_w: &mut Encoder, - id: NodeId) { - match ecx.item_symbols.borrow().get(&id) { - Some(x) => { - debug!("encode_symbol(id={}, str={})", id, *x); - rbml_w.wr_tagged_str(tag_items_data_item_symbol, x); - } - None => { - bug!("encode_symbol: id not found {}", id); - } - } -} - fn encode_disr_val(_: &EncodeContext, rbml_w: &mut Encoder, disr_val: ty::Disr) { @@ -512,10 +497,6 @@ fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_name(rbml_w, name); encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(struct_id)); - if ecx.item_symbols.borrow().contains_key(&ctor_id) { - encode_symbol(ecx, rbml_w, ctor_id); - } - let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(ctor_id)); let depr= ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(ctor_id)); encode_stability(rbml_w, stab); @@ -704,10 +685,6 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, } encode_constness(rbml_w, sig.constness); encode_defaultness(rbml_w, impl_item.defaultness); - if !any_types { - let m_id = ecx.local_id(m.def_id); - encode_symbol(ecx, rbml_w, m_id); - } encode_method_argument_names(rbml_w, &sig.decl); } } @@ -885,7 +862,6 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_family(rbml_w, 'c'); } encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id); - encode_symbol(ecx, rbml_w, item.id); encode_name(rbml_w, item.name); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); @@ -922,9 +898,6 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item)); encode_mir(ecx, rbml_w, item.id); } - if tps_len == 0 { - encode_symbol(ecx, rbml_w, item.id); - } encode_constness(rbml_w, constness); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); @@ -1355,8 +1328,6 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem)); encode_mir(ecx, rbml_w, nitem.id); - } else { - encode_symbol(ecx, rbml_w, nitem.id); } encode_attributes(rbml_w, &nitem.attrs); let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id)); @@ -1377,7 +1348,6 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id)); encode_stability(rbml_w, stab); encode_deprecation(rbml_w, depr); - encode_symbol(ecx, rbml_w, nitem.id); encode_name(rbml_w, nitem.name); } } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 6849134661336..932d5a83a602f 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -38,7 +38,6 @@ use llvm; use rustc::cfg; use rustc::hir::def_id::DefId; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; -use middle::weak_lang_items; use rustc::hir::pat_util::simple_name; use rustc::ty::subst::{self, Substs}; use rustc::traits; @@ -2337,15 +2336,6 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) { set_global_section(ccx, g, item); update_linkage(ccx, g, Some(item.id), OriginalTranslation); } - hir::ItemForeignMod(ref m) => { - if m.abi == Abi::RustIntrinsic || m.abi == Abi::PlatformIntrinsic { - return; - } - for fi in &m.items { - let lname = imported_name(fi.name, &fi.attrs).to_string(); - ccx.item_symbols().borrow_mut().insert(fi.id, lname); - } - } _ => {} } } @@ -2430,16 +2420,6 @@ pub fn create_entry_wrapper(ccx: &CrateContext, sp: Span, main_llfn: ValueRef) { } } -pub fn imported_name(name: ast::Name, attrs: &[ast::Attribute]) -> InternedString { - match attr::first_attr_value_str_by_name(attrs, "link_name") { - Some(ln) => ln.clone(), - None => match weak_lang_items::link_name(attrs) { - Some(name) => name, - None => name.as_str(), - } - } -} - fn contains_null(s: &str) -> bool { s.bytes().any(|b| b == 0) } @@ -2463,7 +2443,6 @@ pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, let cstore = &cx.tcx().sess.cstore; let metadata = cstore.encode_metadata(cx.tcx(), cx.export_map(), - cx.item_symbols(), cx.link_meta(), reachable, mir_map, diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index e97b1dfa13416..77cea248deecb 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -575,11 +575,6 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfn }; - // Always insert into item_symbols, in case this item is exported. - if let Some(id) = local_item { - ccx.item_symbols().borrow_mut().insert(id, sym); - } - ccx.instances().borrow_mut().insert(instance, llfn); immediate_rvalue(llfn, fn_ptr_ty) diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 7b6ecdf30109d..f93edeb511a99 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -1032,13 +1032,10 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) // Create the global before evaluating the initializer; // this is necessary to allow recursive statics. - let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| { + declare::define_global(ccx, &sym, llty).unwrap_or_else(|| { ccx.sess().span_fatal(span, &format!("symbol `{}` is already defined", sym)) - }); - - ccx.item_symbols().borrow_mut().insert(id, sym); - g + }) } hir_map::NodeForeignItem(&hir::ForeignItem { diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 8e8c690efb99b..9bdc59ff055cb 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -70,7 +70,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { export_map: ExportMap, reachable: NodeSet, - item_symbols: RefCell>, link_meta: LinkMeta, symbol_hasher: RefCell, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -394,7 +393,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { metadata_llcx: metadata_llcx, export_map: export_map, reachable: reachable, - item_symbols: RefCell::new(NodeMap()), link_meta: link_meta, symbol_hasher: RefCell::new(symbol_hasher), tcx: tcx, @@ -438,10 +436,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { &self.reachable } - pub fn item_symbols<'a>(&'a self) -> &'a RefCell> { - &self.item_symbols - } - pub fn trait_cache(&self) -> &RefCell>> { &self.trait_cache } @@ -698,10 +692,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.shared.reachable } - pub fn item_symbols<'a>(&'a self) -> &'a RefCell> { - &self.shared.item_symbols - } - pub fn link_meta<'a>(&'a self) -> &'a LinkMeta { &self.shared.link_meta } From aa00e3a552d453f8af0d033d6207a0e09d159d2e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 12 May 2016 14:19:26 -0400 Subject: [PATCH 45/50] re-introduce a cache for ast-ty-to-ty It turns out that `ast_ty_to_ty` is supposed to be updating the `def` after it finishes, but at some point in the past it stopped doing so. This was never noticed because of the `ast_ty_to_ty_cache`, but that cache was recently removed. This PR fixes the code to update the def properly, but apparently that is not quite enough to make the operation idempotent, so for now we reintroduce the cache too. Fixes #33425. --- src/librustc_resolve/lib.rs | 2 + src/librustc_typeck/astconv.rs | 58 +++++++++++++------ src/librustc_typeck/check/mod.rs | 21 ++++--- src/librustc_typeck/collect.rs | 12 +++- src/librustc_typeck/lib.rs | 6 +- .../associated-types-in-bound-type-arg.rs | 26 +++++++++ 6 files changed, 98 insertions(+), 27 deletions(-) create mode 100644 src/test/run-pass/associated-types-in-bound-type-arg.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index fc048c86dc9dd..9cec3a5179496 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2544,6 +2544,8 @@ impl<'a> Resolver<'a> { /// returned value. See `hir::def::PathResolution` for more info. fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace) -> Result { + debug!("resolve_path(id={:?} path={:?}, path_depth={:?})", id, path, path_depth); + let span = path.span; let segments = &path.segments[..path.segments.len() - path_depth]; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 725d40889ceec..c8e247fb9181c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -64,10 +64,10 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope, ElisionFailureInfo, ElidedLifetime}; use util::common::{ErrorReported, FN_OUTPUT_NAME}; -use util::nodemap::FnvHashSet; +use util::nodemap::{NodeMap, FnvHashSet}; use rustc_const_math::ConstInt; - +use std::cell::RefCell; use syntax::{abi, ast}; use syntax::codemap::{Span, Pos}; use syntax::errors::DiagnosticBuilder; @@ -81,6 +81,9 @@ use rustc_back::slice; pub trait AstConv<'gcx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; + /// A cache used for the result of `ast_ty_to_ty_cache` + fn ast_ty_to_ty_cache(&self) -> &RefCell>>; + /// Identify the type scheme for an item with a type, like a type /// alias, fn, or struct. This allows you to figure out the set of /// type parameters defined on the item. @@ -1416,13 +1419,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { rscope: &RegionScope, span: Span, param_mode: PathParamMode, - def: &Def, + def: Def, opt_self_ty: Option>, base_segments: &[hir::PathSegment]) -> Ty<'tcx> { let tcx = self.tcx(); - match *def { + debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, base_segments={:?})", + def, opt_self_ty, base_segments); + + match def { Def::Trait(trait_def_id) => { // N.B. this case overlaps somewhat with // TyObjectSum, see that fn for details @@ -1515,20 +1521,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { rscope: &RegionScope, span: Span, param_mode: PathParamMode, - def: &Def, + mut def: Def, opt_self_ty: Option>, base_segments: &[hir::PathSegment], assoc_segments: &[hir::PathSegment]) - -> Ty<'tcx> { + -> (Ty<'tcx>, Def) { + debug!("finish_resolving_def_to_ty(def={:?}, \ + base_segments={:?}, \ + assoc_segments={:?})", + def, + base_segments, + assoc_segments); let mut ty = self.base_def_to_ty(rscope, span, param_mode, def, opt_self_ty, base_segments); - let mut def = *def; + debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", ty); // If any associated type segments remain, attempt to resolve them. for segment in assoc_segments { + debug!("finish_resolving_def_to_ty: segment={:?}", segment); if ty.sty == ty::TyError { break; } @@ -1540,7 +1553,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty = a_ty; def = a_def; } - ty + (ty, def) } /// Parses the programmer's textual representation of a type into our @@ -1551,7 +1564,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let tcx = self.tcx(); - match ast_ty.node { + let cache = self.ast_ty_to_ty_cache(); + match cache.borrow().get(&ast_ty.id) { + Some(ty) => { return ty; } + None => { } + } + + let result_ty = match ast_ty.node { hir::TyVec(ref ty) => { tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty)) } @@ -1599,6 +1618,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds) } hir::TyPath(ref maybe_qself, ref path) => { + debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { d } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself { @@ -1615,13 +1635,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let opt_self_ty = maybe_qself.as_ref().map(|qself| { self.ast_ty_to_ty(rscope, &qself.ty) }); - let ty = self.finish_resolving_def_to_ty(rscope, - ast_ty.span, - PathParamMode::Explicit, - &def, - opt_self_ty, - &path.segments[..base_ty_end], - &path.segments[base_ty_end..]); + let (ty, _def) = self.finish_resolving_def_to_ty(rscope, + ast_ty.span, + PathParamMode::Explicit, + def, + opt_self_ty, + &path.segments[..base_ty_end], + &path.segments[base_ty_end..]); if path_res.depth != 0 && ty.sty != ty::TyError { // Write back the new resolution. @@ -1675,7 +1695,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // handled specially and will not descend into this routine. self.ty_infer(None, None, None, ast_ty.span) } - } + }; + + cache.borrow_mut().insert(ast_ty.id, result_ty); + + result_ty } pub fn ty_of_arg(&self, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f428023da9b82..6dfad749982b6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -346,6 +346,8 @@ impl UnsafetyState { #[derive(Clone)] pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + ast_ty_to_ty_cache: RefCell>>, + body_id: ast::NodeId, // This flag is set to true if, during the writeback phase, we encounter @@ -1262,6 +1264,10 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } + fn ast_ty_to_ty_cache(&self) -> &RefCell>> { + &self.ast_ty_to_ty_cache + } + fn get_item_type_scheme(&self, _: Span, id: DefId) -> Result, ErrorReported> { @@ -1434,6 +1440,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { body_id: ast::NodeId) -> FnCtxt<'a, 'gcx, 'tcx> { FnCtxt { + ast_ty_to_ty_cache: RefCell::new(NodeMap()), body_id: body_id, writeback_errors: Cell::new(false), err_count_on_creation: inh.tcx.sess.err_count(), @@ -3845,15 +3852,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if path_res.depth == 0 { Some((opt_self_ty, &path.segments, path_res.base_def)) } else { - let mut def = path_res.base_def; + let def = path_res.base_def; let ty_segments = path.segments.split_last().unwrap().1; let base_ty_end = path.segments.len() - path_res.depth; - let ty = AstConv::finish_resolving_def_to_ty(self, self, span, - PathParamMode::Optional, - &mut def, - opt_self_ty, - &ty_segments[..base_ty_end], - &ty_segments[base_ty_end..]); + let (ty, _def) = AstConv::finish_resolving_def_to_ty(self, self, span, + PathParamMode::Optional, + def, + opt_self_ty, + &ty_segments[..base_ty_end], + &ty_segments[base_ty_end..]); let item_segment = path.segments.last().unwrap(); let item_name = item_segment.identifier.name; let def = match self.resolve_ufcs(span, item_name, ty, node_id) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 797a1509ebee5..f9a22e2a577b4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -78,11 +78,12 @@ use rscope::*; use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; use util::common::{ErrorReported, MemoizationMap}; -use util::nodemap::FnvHashMap; +use util::nodemap::{NodeMap, FnvHashMap}; use {CrateCtxt, write_ty_to_tcx}; use rustc_const_math::ConstInt; +use std::cell::RefCell; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::rc::Rc; @@ -146,7 +147,10 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> impl<'a,'tcx> CrateCtxt<'a,'tcx> { fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> { - ItemCtxt { ccx: self, param_bounds: param_bounds } + ItemCtxt { + ccx: self, + param_bounds: param_bounds, + } } fn cycle_check(&self, @@ -298,6 +302,10 @@ impl<'a,'tcx> ItemCtxt<'a,'tcx> { impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.ccx.tcx } + fn ast_ty_to_ty_cache(&self) -> &RefCell>> { + &self.ccx.ast_ty_to_ty_cache + } + fn get_item_type_scheme(&self, span: Span, id: DefId) -> Result, ErrorReported> { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index b88b3c9802d30..f41da95c13537 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -116,6 +116,7 @@ use syntax::ast; use syntax::abi::Abi; use std::cell::RefCell; +use util::nodemap::NodeMap; // NB: This module needs to be declared first so diagnostics are // registered before they are used. @@ -136,7 +137,9 @@ pub struct TypeAndSubsts<'tcx> { } pub struct CrateCtxt<'a, 'tcx: 'a> { - // A mapping from method call sites to traits that have that method. + ast_ty_to_ty_cache: RefCell>>, + + /// A mapping from method call sites to traits that have that method. pub trait_map: hir::TraitMap, /// A vector of every trait accessible in the whole crate @@ -334,6 +337,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> CompileResult { let time_passes = tcx.sess.time_passes(); let ccx = CrateCtxt { + ast_ty_to_ty_cache: RefCell::new(NodeMap()), trait_map: trait_map, all_traits: RefCell::new(None), stack: RefCell::new(Vec::new()), diff --git a/src/test/run-pass/associated-types-in-bound-type-arg.rs b/src/test/run-pass/associated-types-in-bound-type-arg.rs new file mode 100644 index 0000000000000..18803d15719e8 --- /dev/null +++ b/src/test/run-pass/associated-types-in-bound-type-arg.rs @@ -0,0 +1,26 @@ +// 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. + +// Test the case where we resolve `C::Result` and the trait bound +// itself includes a `Self::Item` shorthand. +// +// Regression test for issue #33425. + +trait ParallelIterator { + type Item; + fn drive_unindexed(self, consumer: C) -> C::Result + where C: Consumer; +} + +pub trait Consumer { + type Result; +} + +fn main() { } From 0eeb14eaba04025aa8a4612e1935f04f2ca3fb6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Thu, 12 May 2016 17:54:05 +0200 Subject: [PATCH 46/50] Improve derived implementations for enums with lots of fieldless variants A number of trait methods like PartialEq::eq or Hash::hash don't actually need a distinct arm for each variant, because the code within the arm only depends on the number and types of the fields in the variants. We can easily exploit this fact to create less and better code for enums with multiple variants that have no fields at all, the extreme case being C-like enums. For nickel.rs and its by now infamous 800 variant enum, this reduces optimized compile times by 25% and non-optimized compile times by 40%. Also peak memory usage is down by almost 40% (310MB down to 190MB). To be fair, most other crates don't benefit nearly as much, because they don't have as huge enums. The crates in the Rust distribution that I measured saw basically no change in compile times (I only tried optimized builds) and only 1-2% reduction in peak memory usage. --- src/libsyntax_ext/deriving/clone.rs | 4 +++ src/libsyntax_ext/deriving/cmp/eq.rs | 1 + src/libsyntax_ext/deriving/cmp/ord.rs | 1 + src/libsyntax_ext/deriving/cmp/partial_eq.rs | 1 + src/libsyntax_ext/deriving/cmp/partial_ord.rs | 2 ++ src/libsyntax_ext/deriving/debug.rs | 1 + src/libsyntax_ext/deriving/decodable.rs | 1 + src/libsyntax_ext/deriving/default.rs | 1 + src/libsyntax_ext/deriving/encodable.rs | 1 + src/libsyntax_ext/deriving/generic/mod.rs | 35 +++++++++++++++---- src/libsyntax_ext/deriving/hash.rs | 1 + .../auxiliary/custom_derive_plugin.rs | 1 + .../auxiliary/custom_derive_plugin_attr.rs | 1 + 13 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 2c21fd2cd5ed2..30fe0f2db8a1c 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -39,6 +39,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, // Clone + Copy, and then there'd be no Clone impl at all if the user fills in something // that is Clone but not Copy. and until specialization we can't write both impls. let bounds; + let unify_fieldless_variants; let substructure; match *item { Annotatable::Item(ref annitem) => { @@ -49,6 +50,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, && attr::contains_name(&annitem.attrs, "derive_Copy") => { bounds = vec![Literal(path_std!(cx, core::marker::Copy))]; + unify_fieldless_variants = true; substructure = combine_substructure(Box::new(|c, s, sub| { cs_clone("Clone", c, s, sub, Mode::Shallow) })); @@ -56,6 +58,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, _ => { bounds = vec![]; + unify_fieldless_variants = false; substructure = combine_substructure(Box::new(|c, s, sub| { cs_clone("Clone", c, s, sub, Mode::Deep) })); @@ -84,6 +87,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, ret_ty: Self_, attributes: attrs, is_unsafe: false, + unify_fieldless_variants: unify_fieldless_variants, combine_substructure: substructure, } ), diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index 1b855c56a48bf..8bd12c393370d 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -62,6 +62,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, ret_ty: nil_ty(), attributes: attrs, is_unsafe: false, + unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { cs_total_eq_assert(a, b, c) })) diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 74706c470872a..6133adb8fc5d1 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -42,6 +42,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, ret_ty: Literal(path_std!(cx, core::cmp::Ordering)), attributes: attrs, is_unsafe: false, + unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { cs_cmp(a, b, c) })), diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index 6406ee59a5eb5..e5890d7213bed 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -73,6 +73,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, ret_ty: Literal(path_local!(bool)), attributes: attrs, is_unsafe: false, + unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { $f(a, b, c) })) diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index e49c77285ab02..cfc6dbe5cd030 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -38,6 +38,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, ret_ty: Literal(path_local!(bool)), attributes: attrs, is_unsafe: false, + unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|cx, span, substr| { cs_op($op, $equal, cx, span, substr) })) @@ -62,6 +63,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, ret_ty: ret_ty, attributes: attrs, is_unsafe: false, + unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|cx, span, substr| { cs_partial_cmp(cx, span, substr) })) diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 323c6c388fb64..d86eae820a884 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -45,6 +45,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt, ret_ty: Literal(path_std!(cx, core::fmt::Result)), attributes: Vec::new(), is_unsafe: false, + unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { show_substructure(a, b, c) })) diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 9387cf05ac7d1..04888d046ad2d 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -85,6 +85,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, )), attributes: Vec::new(), is_unsafe: false, + unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { decodable_substructure(a, b, c, krate) })), diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index bee63a98c252f..a6a4830fab7f8 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -42,6 +42,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, ret_ty: Self_, attributes: attrs, is_unsafe: false, + unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { default_substructure(a, b, c) })) diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 5b47d8da8b642..66672305829b9 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -161,6 +161,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, )), attributes: Vec::new(), is_unsafe: false, + unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { encodable_substructure(a, b, c, krate) })), diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1d5fc13c72008..45029c8eb943b 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -257,6 +257,9 @@ pub struct MethodDef<'a> { // Is it an `unsafe fn`? pub is_unsafe: bool, + /// Can we combine fieldless variants for enums into a single match arm? + pub unify_fieldless_variants: bool, + pub combine_substructure: RefCell>, } @@ -1131,12 +1134,15 @@ impl<'a> MethodDef<'a> { let catch_all_substructure = EnumNonMatchingCollapsed( self_arg_idents, &variants[..], &vi_idents[..]); + let first_fieldless = variants.iter().find(|v| v.node.data.fields().is_empty()); + // These arms are of the form: // (Variant1, Variant1, ...) => Body1 // (Variant2, Variant2, ...) => Body2 // ... // where each tuple has length = self_args.len() let mut match_arms: Vec = variants.iter().enumerate() + .filter(|&(_, v)| !(self.unify_fieldless_variants && v.node.data.fields().is_empty())) .map(|(index, variant)| { let mk_self_pat = |cx: &mut ExtCtxt, self_arg_name: &str| { let (p, idents) = trait_.create_enum_variant_pattern( @@ -1219,6 +1225,28 @@ impl<'a> MethodDef<'a> { cx.arm(sp, vec![single_pat], arm_expr) }).collect(); + + let default = match first_fieldless { + Some(v) if self.unify_fieldless_variants => { + // We need a default case that handles the fieldless variants. + // The index and actual variant aren't meaningful in this case, + // so just use whatever + Some(self.call_substructure_method( + cx, trait_, type_ident, &self_args[..], nonself_args, + &EnumMatching(0, v, Vec::new()))) + } + _ if variants.len() > 1 && self_args.len() > 1 => { + // Since we know that all the arguments will match if we reach + // the match expression we add the unreachable intrinsics as the + // result of the catch all which should help llvm in optimizing it + Some(deriving::call_intrinsic(cx, sp, "unreachable", vec![])) + } + _ => None + }; + if let Some(arm) = default { + match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], arm)); + } + // We will usually need the catch-all after matching the // tuples `(VariantK, VariantK, ...)` for each VariantK of the // enum. But: @@ -1292,13 +1320,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, &self_args[..], nonself_args, &catch_all_substructure); - //Since we know that all the arguments will match if we reach the match expression we - //add the unreachable intrinsics as the result of the catch all which should help llvm - //in optimizing it - match_arms.push(cx.arm(sp, - vec![cx.pat_wild(sp)], - deriving::call_intrinsic(cx, sp, "unreachable", vec![]))); - // Final wrinkle: the self_args are expressions that deref // down to desired l-values, but we cannot actually deref // them when they are fed as r-values into a tuple diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index c37ae116d379b..fd449372cb376 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -51,6 +51,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, ret_ty: nil_ty(), attributes: vec![], is_unsafe: false, + unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { hash_substructure(a, b, c) })) diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs index 5f0ef4de491e0..0132014de0ab5 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs @@ -58,6 +58,7 @@ fn expand(cx: &mut ExtCtxt, ret_ty: Literal(Path::new_local("isize")), attributes: vec![], is_unsafe: false, + unify_fieldless_variants: true, combine_substructure: combine_substructure(box |cx, span, substr| { let zero = cx.expr_isize(span, 0); cs_fold(false, diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs index 2878674f0ea61..6fa78913839b7 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs @@ -60,6 +60,7 @@ fn expand(cx: &mut ExtCtxt, ret_ty: Literal(Path::new_local("isize")), attributes: vec![], is_unsafe: false, + unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(totalsum_substructure)), }, ], From 538de73f5b90eb831b7cc64e78f3aaac57d1378f Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Thu, 12 May 2016 18:23:11 +0100 Subject: [PATCH 47/50] rustdoc: Fix missing type parameters on impls --- src/librustdoc/clean/mod.rs | 7 ------- src/librustdoc/html/format.rs | 8 +++++++- src/test/rustdoc/issue-33592.rs | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 src/test/rustdoc/issue-33592.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a89609fad6b6e..7305b0f1fb8bc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1534,13 +1534,6 @@ impl Type { } } - pub fn trait_name(&self) -> Option { - match *self { - ResolvedPath { ref path, .. } => Some(path.last_name()), - _ => None, - } - } - pub fn is_generic(&self) -> bool { match *self { ResolvedPath { is_generic, .. } => is_generic, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 7af5322e7bdf1..4514106cece25 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -587,7 +587,13 @@ fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::R if link_trait { write!(f, "{}", *ty)?; } else { - write!(f, "{}", ty.trait_name().unwrap())?; + match *ty { + clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => { + let last = path.segments.last().unwrap(); + write!(f, "{}{}", last.name, last.params)?; + } + _ => unreachable!(), + } } write!(f, " for ")?; } diff --git a/src/test/rustdoc/issue-33592.rs b/src/test/rustdoc/issue-33592.rs new file mode 100644 index 0000000000000..c0de4cc38e41e --- /dev/null +++ b/src/test/rustdoc/issue-33592.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +#![crate_name = "foo"] + +pub trait Foo {} + +pub struct Bar; + +pub struct Baz; + +// @has foo/trait.Foo.html '//code' 'impl Foo for Bar' +impl Foo for Bar {} + +// @has foo/trait.Foo.html '//code' 'impl Foo for Baz' +impl Foo for Baz {} From d4bff0cddaeedcac954c10930b71f5f2ceba286c Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Thu, 12 May 2016 21:49:14 +0200 Subject: [PATCH 48/50] doc: Fix comment in std::string::String example code --- src/libcollections/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 306fad2328b62..eedf4c2c11f34 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -184,7 +184,7 @@ use boxed::Box; /// let len = story.len(); /// let capacity = story.capacity(); /// -/// // story has thirteen bytes +/// // story has nineteen bytes /// assert_eq!(19, len); /// /// // Now that we have our parts, we throw the story away. From adee551ce32f0e7214e83096bdac0f3b5247aa7f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 12 May 2016 23:37:41 +0300 Subject: [PATCH 49/50] trans: save metadata even with -Z no-trans. --- src/librustc/session/config.rs | 2 +- src/librustc_driver/lib.rs | 4 --- src/librustc_trans/base.rs | 54 ++++++++++++++++++++-------------- src/librustc_trans/context.rs | 4 +++ 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 7d1d5dba39839..08e422e47877b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1103,7 +1103,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let no_analysis = debugging_opts.no_analysis; let mut output_types = HashMap::new(); - if !debugging_opts.parse_only && !no_trans { + if !debugging_opts.parse_only { for list in matches.opt_strs("emit") { for output_type in list.split(',') { let mut parts = output_type.splitn(2, '='); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 4da36be94e009..c863ff21b2c7a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -504,10 +504,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_write_deps.stop = Compilation::Stop; } - if sess.opts.no_trans { - control.after_analysis.stop = Compilation::Stop; - } - if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) { control.after_llvm.stop = Compilation::Stop; } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 932d5a83a602f..2185ec9a7252c 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2424,11 +2424,7 @@ fn contains_null(s: &str) -> bool { s.bytes().any(|b| b == 0) } -pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, - krate: &hir::Crate, - reachable: &NodeSet, - mir_map: &MirMap<'tcx>) - -> Vec { +pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>) -> Vec { use flate; let any_library = cx.sess() @@ -2444,9 +2440,9 @@ pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, let metadata = cstore.encode_metadata(cx.tcx(), cx.export_map(), cx.link_meta(), - reachable, - mir_map, - krate); + cx.reachable(), + cx.mir_map(), + cx.tcx().map.krate()); let mut compressed = cstore.metadata_encoding_version().to_vec(); compressed.extend_from_slice(&flate::deflate_bytes(&metadata)); @@ -2679,6 +2675,16 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reachable, check_overflow, check_dropflag); + // Translate the metadata. + let metadata = time(tcx.sess.time_passes(), "write metadata", || { + write_metadata(&shared_ccx) + }); + + let metadata_module = ModuleTranslation { + llcx: shared_ccx.metadata_llcx(), + llmod: shared_ccx.metadata_llmod(), + }; + let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); let codegen_units = collect_and_partition_translation_items(&shared_ccx); let codegen_unit_count = codegen_units.len(); @@ -2687,6 +2693,24 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units); + let modules = crate_context_list.iter() + .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() }) + .collect(); + + // Skip crate items and just output metadata in -Z no-trans mode. + if tcx.sess.opts.no_trans { + let linker_info = LinkerInfo::new(&shared_ccx, &[]); + return CrateTranslation { + modules: modules, + metadata_module: metadata_module, + link: link_meta, + metadata: metadata, + reachable: vec![], + no_builtins: no_builtins, + linker_info: linker_info + }; + } + { let ccx = crate_context_list.get_ccx(0); @@ -2718,10 +2742,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let reachable_symbol_ids = filter_reachable_ids(&shared_ccx); - // Translate the metadata. - let metadata = time(tcx.sess.time_passes(), "write metadata", || { - write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map) - }); if shared_ccx.sess().trans_stats() { let stats = shared_ccx.stats(); @@ -2752,10 +2772,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let modules = crate_context_list.iter() - .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() }) - .collect(); - let sess = shared_ccx.sess(); let mut reachable_symbols = reachable_symbol_ids.iter().map(|&id| { let def_id = shared_ccx.tcx().map.local_def_id(id); @@ -2789,12 +2805,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, create_imps(&crate_context_list); } - let metadata_module = ModuleTranslation { - llcx: shared_ccx.metadata_llcx(), - llmod: shared_ccx.metadata_llmod(), - }; - let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); - let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); CrateTranslation { modules: modules, diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 9bdc59ff055cb..40018840a8b83 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -485,6 +485,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn symbol_hasher(&self) -> &RefCell { &self.symbol_hasher } + + pub fn mir_map(&self) -> &MirMap<'tcx> { + &self.mir_map + } } impl<'tcx> LocalCrateContext<'tcx> { From 8ad6d27f87ad497f4f97fbaffd72a404303dd6b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sat, 14 Nov 2015 23:52:17 +0100 Subject: [PATCH 50/50] [MIR] Enhance the SimplifyCfg pass to merge consecutive blocks --- src/librustc_mir/transform/simplify_cfg.rs | 183 ++++++++++++++------- 1 file changed, 124 insertions(+), 59 deletions(-) diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index fa897384a542a..526157a49c734 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -8,73 +8,155 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc_data_structures::bitvec::BitVector; use rustc::middle::const_val::ConstVal; use rustc::ty::TyCtxt; use rustc::mir::repr::*; use rustc::mir::transform::{MirPass, MirSource, Pass}; use pretty; +use std::mem; use super::remove_dead_blocks::RemoveDeadBlocks; +use traversal; + pub struct SimplifyCfg; impl SimplifyCfg { pub fn new() -> SimplifyCfg { SimplifyCfg } +} + +impl<'tcx> MirPass<'tcx> for SimplifyCfg { + fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { + simplify_branches(mir); + RemoveDeadBlocks.run_pass(tcx, src, mir); + merge_consecutive_blocks(mir); + RemoveDeadBlocks.run_pass(tcx, src, mir); + pretty::dump_mir(tcx, "simplify_cfg", &0, src, mir, None); + + // FIXME: Should probably be moved into some kind of pass manager + mir.basic_blocks.shrink_to_fit(); + } +} + +impl Pass for SimplifyCfg {} + +fn merge_consecutive_blocks(mir: &mut Mir) { + // Build the precedecessor map for the MIR + let mut pred_count = vec![0u32; mir.basic_blocks.len()]; + for (_, data) in traversal::preorder(mir) { + if let Some(ref term) = data.terminator { + for &tgt in term.successors().iter() { + pred_count[tgt.index()] += 1; + } + } + } + + loop { + let mut changed = false; + let mut seen = BitVector::new(mir.basic_blocks.len()); + let mut worklist = vec![START_BLOCK]; + while let Some(bb) = worklist.pop() { + // Temporarily take ownership of the terminator we're modifying to keep borrowck happy + let mut terminator = mir.basic_block_data_mut(bb).terminator.take() + .expect("invalid terminator state"); + + // See if we can merge the target block into this one + loop { + let mut inner_change = false; - fn remove_goto_chains(&self, mir: &mut Mir) -> bool { - // Find the target at the end of the jump chain, return None if there is a loop - fn final_target(mir: &Mir, mut target: BasicBlock) -> Option { - // Keep track of already seen blocks to detect loops - let mut seen: Vec = Vec::with_capacity(8); - - while mir.basic_block_data(target).statements.is_empty() { - // NB -- terminator may have been swapped with `None` - // below, in which case we have a cycle and just want - // to stop - if let Some(ref terminator) = mir.basic_block_data(target).terminator { - match terminator.kind { - TerminatorKind::Goto { target: next } => { - if seen.contains(&next) { - return None; + if let TerminatorKind::Goto { target } = terminator.kind { + // Don't bother trying to merge a block into itself + if target == bb { + break; + } + + let num_insts = mir.basic_block_data(target).statements.len(); + match mir.basic_block_data(target).terminator().kind { + TerminatorKind::Goto { target: new_target } if num_insts == 0 => { + inner_change = true; + terminator.kind = TerminatorKind::Goto { target: new_target }; + pred_count[target.index()] -= 1; + pred_count[new_target.index()] += 1; + } + _ if pred_count[target.index()] == 1 => { + inner_change = true; + let mut stmts = Vec::new(); + { + let target_data = mir.basic_block_data_mut(target); + mem::swap(&mut stmts, &mut target_data.statements); + mem::swap(&mut terminator, target_data.terminator_mut()); } - seen.push(next); - target = next; + + mir.basic_block_data_mut(bb).statements.append(&mut stmts); } - _ => break + _ => {} + }; + } + + for target in terminator.successors_mut() { + let new_target = match final_target(mir, *target) { + Some(new_target) => new_target, + None if mir.basic_block_data(bb).statements.is_empty() => bb, + None => continue + }; + if *target != new_target { + inner_change = true; + pred_count[target.index()] -= 1; + pred_count[new_target.index()] += 1; + *target = new_target; } - } else { - break + } + + changed |= inner_change; + if !inner_change { + break; } } - Some(target) + mir.basic_block_data_mut(bb).terminator = Some(terminator); + + for succ in mir.basic_block_data(bb).terminator().successors().iter() { + if seen.insert(succ.index()) { + worklist.push(*succ); + } + } } - let mut changed = false; - for bb in mir.all_basic_blocks() { - // Temporarily take ownership of the terminator we're modifying to keep borrowck happy - let mut terminator = mir.basic_block_data_mut(bb).terminator.take() - .expect("invalid terminator state"); - - debug!("remove_goto_chains: bb={:?} terminator={:?}", bb, terminator); - - for target in terminator.successors_mut() { - let new_target = match final_target(mir, *target) { - Some(new_target) => new_target, - None if mir.basic_block_data(bb).statements.is_empty() => bb, - None => continue - }; - changed |= *target != new_target; - *target = new_target; + if !changed { + break; + } + } +} + +// Find the target at the end of the jump chain, return None if there is a loop +fn final_target(mir: &Mir, mut target: BasicBlock) -> Option { + // Keep track of already seen blocks to detect loops + let mut seen: Vec = Vec::with_capacity(8); + + while mir.basic_block_data(target).statements.is_empty() { + // NB -- terminator may have been swapped with `None` in + // merge_consecutive_blocks, in which case we have a cycle and just want + // to stop + match mir.basic_block_data(target).terminator { + Some(Terminator { kind: TerminatorKind::Goto { target: next }, .. }) => { + if seen.contains(&next) { + return None; + } + seen.push(next); + target = next; } - mir.basic_block_data_mut(bb).terminator = Some(terminator); + _ => break } - changed } - fn simplify_branches(&self, mir: &mut Mir) -> bool { + Some(target) +} + +fn simplify_branches(mir: &mut Mir) { + loop { let mut changed = false; for bb in mir.all_basic_blocks() { @@ -106,25 +188,8 @@ impl SimplifyCfg { } } - changed - } -} - -impl<'tcx> MirPass<'tcx> for SimplifyCfg { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, mir: &mut Mir<'tcx>) { - let mut counter = 0; - let mut changed = true; - while changed { - pretty::dump_mir(tcx, "simplify_cfg", &counter, src, mir, None); - counter += 1; - changed = self.simplify_branches(mir); - changed |= self.remove_goto_chains(mir); - RemoveDeadBlocks.run_pass(tcx, src, mir); + if !changed { + break; } - // FIXME: Should probably be moved into some kind of pass manager - mir.basic_blocks.shrink_to_fit(); } } - -impl Pass for SimplifyCfg {}