From ab9a42ce20dc183f3ac7825571e69d79b77228ea Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 8 Apr 2016 14:04:39 -0400 Subject: [PATCH 1/3] make field of `Binder` private It should never have been public. Call `skip_binder` instead and make your intentions explicit. Where possible, I adopted `map_bound_ref` and `map_bound` instead. --- src/librustc/infer/bivariate.rs | 2 +- src/librustc/infer/higher_ranked/mod.rs | 6 +- src/librustc/middle/free_region.rs | 5 +- src/librustc/middle/intrinsicck.rs | 10 ++- src/librustc/traits/error_reporting.rs | 4 +- src/librustc/traits/mod.rs | 2 +- src/librustc/traits/object_safety.rs | 21 +++-- src/librustc/traits/project.rs | 32 +++---- src/librustc/traits/select.rs | 99 ++++++++++++--------- src/librustc/traits/util.rs | 22 ++--- src/librustc/ty/_match.rs | 2 +- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 9 +- src/librustc/ty/fold.rs | 8 +- src/librustc/ty/mod.rs | 59 ++++++------ src/librustc/ty/structural_impls.rs | 6 +- src/librustc/ty/sty.rs | 76 ++++++++++------ src/librustc/ty/util.rs | 15 +++- src/librustc/ty/walk.rs | 6 +- src/librustc/ty/wf.rs | 14 +-- src/librustc/util/ppaux.rs | 16 ++-- src/librustc_const_eval/eval.rs | 2 +- src/librustc_driver/test.rs | 2 +- src/librustc_lint/builtin.rs | 7 +- src/librustc_metadata/astencode.rs | 2 +- src/librustc_metadata/decoder.rs | 5 +- src/librustc_metadata/tydecode.rs | 26 +++--- src/librustc_metadata/tyencode.rs | 25 +++--- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_privacy/lib.rs | 11 ++- src/librustc_trans/base.rs | 14 +-- src/librustc_trans/callee.rs | 6 +- src/librustc_trans/closure.rs | 8 +- src/librustc_trans/collector.rs | 2 +- src/librustc_trans/common.rs | 10 +-- src/librustc_trans/glue.rs | 2 +- src/librustc_trans/intrinsic.rs | 4 +- src/librustc_trans/mir/block.rs | 2 +- src/librustc_typeck/astconv.rs | 73 ++++++++------- src/librustc_typeck/check/callee.rs | 2 +- src/librustc_typeck/check/closure.rs | 5 +- src/librustc_typeck/check/compare_method.rs | 14 +-- src/librustc_typeck/check/intrinsic.rs | 4 +- src/librustc_typeck/check/method/confirm.rs | 4 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 7 +- src/librustc_typeck/check/mod.rs | 48 +++++----- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/collect.rs | 16 ++-- src/librustc_typeck/lib.rs | 4 +- src/librustc_typeck/variance/constraints.rs | 12 ++- src/librustdoc/clean/mod.rs | 21 ++--- 52 files changed, 429 insertions(+), 331 deletions(-) diff --git a/src/librustc/infer/bivariate.rs b/src/librustc/infer/bivariate.rs index a9ea395e6b3cd..917391b0b9a32 100644 --- a/src/librustc/infer/bivariate.rs +++ b/src/librustc/infer/bivariate.rs @@ -112,6 +112,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { let a1 = self.tcx().erase_late_bound_regions(a); let b1 = self.tcx().erase_late_bound_regions(b); let c = self.relate(&a1, &b1)?; - Ok(ty::Binder(c)) + Ok(ty::Binder::new(c)) } } diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index d89ef8ef6c31d..a2bd5fba1aba7 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -97,7 +97,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { debug!("higher_ranked_sub: OK result={:?}", result); - Ok(ty::Binder(result)) + Ok(ty::Binder::new(result)) }); } @@ -138,7 +138,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { b, result1); - Ok(ty::Binder(result1)) + Ok(ty::Binder::new(result1)) }); fn generalize_region(infcx: &InferCtxt, @@ -233,7 +233,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { b, result1); - Ok(ty::Binder(result1)) + Ok(ty::Binder::new(result1)) }); fn generalize_region(infcx: &InferCtxt, diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index ae0540696c572..3fea881f6bd35 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -62,7 +62,10 @@ impl FreeRegionMap { ty::Predicate::TypeOutlives(..) => { // No region bounds here } - ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => { + ty::Predicate::RegionOutlives(ref data) => { + let &ty::OutlivesPredicate(r_a, r_b) = data.skip_binder(); // (*) + // (*) OK to skip binder because the code below + // ignores bound regions. match (r_a, r_b) { (ty::ReStatic, ty::ReFree(_)) => {}, (ty::ReFree(fr_a), ty::ReStatic) => self.relate_to_static(fr_a), diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 767c5adc81e25..cf063be29465e 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -239,8 +239,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> { let typ = self.tcx.node_id_to_type(expr.id); match typ.sty { ty::TyFnDef(_, _, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { - if let ty::FnConverging(to) = bare_fn_ty.sig.0.output { - let from = bare_fn_ty.sig.0.inputs[0]; + let output = + self.tcx.erase_late_bound_regions( + &bare_fn_ty.sig.output()); + + if let ty::FnConverging(to) = output { + let from = + self.tcx.erase_late_bound_regions( + &bare_fn_ty.sig.input(0)); self.check_transmute(expr.span, from, to, expr.id); } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 286733c7c26a3..28293589a15f6 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -843,7 +843,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, err.fileline_note( cause_span, &format!("required because it appears within the type `{}`", - parent_trait_ref.0.self_ty())); + parent_trait_ref.skip_binder().self_ty())); let parent_predicate = parent_trait_ref.to_predicate(); note_obligation_cause_code(infcx, err, @@ -857,7 +857,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, cause_span, &format!("required because of the requirements on the impl of `{}` for `{}`", parent_trait_ref, - parent_trait_ref.0.self_ty())); + parent_trait_ref.skip_binder().self_ty())); let parent_predicate = parent_trait_ref.to_predicate(); note_obligation_cause_code(infcx, err, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a160465e2e815..7a5cb7c311d31 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -618,6 +618,6 @@ impl<'tcx> FulfillmentError<'tcx> { impl<'tcx> TraitObligation<'tcx> { fn self_ty(&self) -> ty::Binder> { - ty::Binder(self.predicate.skip_binder().self_ty()) + self.predicate.map_bound_ref(|p| p.self_ty()) } } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 9af2cfbd04da0..5b1eb01d108bc 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -155,10 +155,11 @@ pub fn supertraits_reference_self<'tcx>(tcx: &TyCtxt<'tcx>, match predicate { ty::Predicate::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. - data.0.trait_ref.substs.types.get_slice(TypeSpace) - .iter() - .cloned() - .any(|t| t.has_self_ty()) + data.skip_binder() // ok to skip binder, bound regions not relevant + .trait_ref.substs.types.get_slice(TypeSpace) + .iter() + .cloned() + .any(|t| t.has_self_ty()) } ty::Predicate::Projection(..) | ty::Predicate::WellFormed(..) | @@ -199,7 +200,8 @@ fn generics_require_sized_self<'tcx>(tcx: &TyCtxt<'tcx>, .any(|predicate| { match predicate { ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { - trait_pred.0.self_ty().is_self() + trait_pred.skip_binder().self_ty().is_self() + // ok to skip_binder, bound regions not relevant } ty::Predicate::Projection(..) | ty::Predicate::Trait(..) | @@ -267,16 +269,17 @@ fn virtual_call_violation_for_method<'tcx>(tcx: &TyCtxt<'tcx>, // The `Self` type is erased, so it should not appear in list of // arguments or return type apart from the receiver. let ref sig = method.fty.sig; - for &input_ty in &sig.0.inputs[1..] { + for &input_ty in &sig.skip_binder().inputs[1..] { // (*) if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) { return Some(MethodViolationCode::ReferencesSelf); } } - if let ty::FnConverging(result_type) = sig.0.output { + if let ty::FnConverging(result_type) = sig.skip_binder().output { // (*) if contains_illegal_self_type_reference(tcx, trait_def_id, result_type) { return Some(MethodViolationCode::ReferencesSelf); } } + // (*) ok to skip binders, bound regions not relevant here // We can't monomorphize things like `fn foo(...)`. if !method.generics.types.is_empty_in(subst::FnSpace) { @@ -348,7 +351,7 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &TyCtxt<'tcx>, // Compute supertraits of current trait lazily. if supertraits.is_none() { let trait_def = tcx.lookup_trait_def(trait_def_id); - let trait_ref = ty::Binder(trait_def.trait_ref.clone()); + let trait_ref = ty::Binder::new(trait_def.trait_ref.clone()); supertraits = Some(traits::supertraits(tcx, trait_ref).collect()); } @@ -360,7 +363,7 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &TyCtxt<'tcx>, // direct equality here because all of these types // are part of the formal parameter listing, and // hence there should be no inference variables. - let projection_trait_ref = ty::Binder(data.trait_ref.clone()); + let projection_trait_ref = ty::Binder::new(data.trait_ref.clone()); let is_supertrait_of_current_trait = supertraits.as_ref().unwrap().contains(&projection_trait_ref); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index a0d6f5f912b2c..e4a19e60d47fa 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -261,12 +261,14 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext ty::TyClosure(closure_def_id, ref substs) => { let closure_typer = selcx.closure_typer(); let closure_type = closure_typer.closure_type(closure_def_id, substs); - let ty::Binder((_, ret_type)) = + let ret_type = util::closure_trait_ref_and_return_type(infcx.tcx, def_id, self_ty, &closure_type.sig, - util::TupleArgumentsFlag::No); + util::TupleArgumentsFlag::No) + .map_bound(|(_, t)| t); + // 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 @@ -275,7 +277,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext infcx.replace_late_bound_regions_with_fresh_var( obligation.cause.span, infer::AssocTypeProjection(obligation.predicate.projection_ty.item_name), - &ty::Binder(ret_type)); + &ret_type); debug!("consider_unification_despite_ambiguity: ret_type={:?}", ret_type); @@ -438,7 +440,7 @@ pub fn normalize_projection_type<'a,'b,'tcx>( // information is available. let ty_var = selcx.infcx().next_ty_var(); - let projection = ty::Binder(ty::ProjectionPredicate { + let projection = ty::Binder::new(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty_var }); @@ -1051,21 +1053,21 @@ fn confirm_callable_candidate<'cx,'tcx>( // the `Output` associated type is declared on `FnOnce` let fn_once_def_id = tcx.lang_items.fn_once_trait().unwrap(); - // Note: we unwrap the binder here but re-create it below (1) - let ty::Binder((trait_ref, ret_type)) = + let predicate = util::closure_trait_ref_and_return_type(tcx, fn_once_def_id, obligation.predicate.trait_ref.self_ty(), fn_sig, - flag); - - let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here - projection_ty: ty::ProjectionTy { - trait_ref: trait_ref, - item_name: token::intern(FN_OUTPUT_NAME), - }, - ty: ret_type - }); + flag) + .map_bound(|(trait_ref, ret_type)| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref, + item_name: token::intern(FN_OUTPUT_NAME), + }, + ty: ret_type + } + }); confirm_param_env_candidate(selcx, obligation, predicate) } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 8d7df6e44aeb7..6b5a1868913e0 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -93,7 +93,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> { #[derive(Clone)] pub struct SelectionCache<'tcx> { - hashmap: RefCell, + hashmap: RefCell, SelectionResult<'tcx, SelectionCandidate<'tcx>>>>, } @@ -358,7 +358,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// argment types won't really change. fn consider_unification_despite_ambiguity(&mut self, obligation: &TraitObligation<'tcx>) { // Is this a `C : FnFoo(...)` trait reference for some trait binding `FnFoo`? - match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) { + match self.tcx().lang_items.fn_trait_kind(obligation.predicate.def_id()) { Some(_) => { } None => { return; } } @@ -590,7 +590,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This suffices to allow chains like `FnMut` implemented in // terms of `Fn` etc, but we could probably make this more // precise still. - let input_types = stack.fresh_trait_ref.0.input_types(); + // + // (*) ok to `skip_binder`, don't care about bound regions here + let input_types = stack.fresh_trait_ref.skip_binder().input_types(); // (*) let unbound_input_types = input_types.iter().any(|ty| ty.is_fresh()); if unbound_input_types && self.intercrate { debug!("evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous", @@ -946,7 +948,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { let cache = self.pick_candidate_cache(); let hashmap = cache.hashmap.borrow(); - hashmap.get(&cache_fresh_trait_pred.0.trait_ref).cloned() + let trait_ref = cache_fresh_trait_pred.map_bound_ref(|p| p.trait_ref); + hashmap.get(&trait_ref).cloned() } fn insert_candidate_cache(&mut self, @@ -955,7 +958,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { let cache = self.pick_candidate_cache(); let mut hashmap = cache.hashmap.borrow_mut(); - hashmap.insert(cache_fresh_trait_pred.0.trait_ref.clone(), candidate); + let trait_ref = cache_fresh_trait_pred.map_bound_ref(|p| p.trait_ref); + hashmap.insert(trait_ref, candidate); } fn should_update_candidate_cache(&mut self, @@ -994,7 +998,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match *candidate { Ok(Some(_)) | Err(_) => true, Ok(None) => { - cache_fresh_trait_pred.0.trait_ref.substs.types.has_infer_types() + cache_fresh_trait_pred.skip_binder() // (*) + .trait_ref + .substs.types.has_infer_types() + // (*) bound regions not relevant } } } @@ -1034,7 +1041,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { Some(ty::BoundCopy) => { debug!("obligation self ty is {:?}", - obligation.predicate.0.self_ty()); + obligation.predicate.skip_binder().self_ty()); // User-defined copy impls are permitted, but only for // structs and enums. @@ -1089,7 +1096,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // before we go into the whole skolemization thing, just // quickly check if the self-type is a projection at all. - let trait_def_id = match obligation.predicate.0.trait_ref.self_ty().sty { + let trait_def_id = match obligation.predicate.skip_binder() + .trait_ref + .self_ty() + .sty { ty::TyProjection(ref data) => data.trait_ref.def_id, ty::TyInfer(ty::TyVar(_)) => { span_bug!(obligation.cause.span, @@ -1188,7 +1198,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.infcx.sub_poly_trait_refs(false, origin, trait_bound.clone(), - ty::Binder(skol_trait_ref.clone())) { + ty::Binder::new(skol_trait_ref.clone())) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations assert!(obligations.is_empty()); @@ -1254,7 +1264,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - let kind = match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) { + let kind = match self.tcx().lang_items.fn_trait_kind(obligation.predicate.def_id()) { Some(k) => k, None => { return Ok(()); } }; @@ -1317,21 +1327,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TyFnDef(_, _, &ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, - sig: ty::Binder(ty::FnSig { - inputs: _, - output: ty::FnConverging(_), - variadic: false - }) + ref sig }) | ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, - sig: ty::Binder(ty::FnSig { - inputs: _, - output: ty::FnConverging(_), - variadic: false - }) - }) => { + ref sig + }) if sig.is_converging() && !sig.variadic() => { candidates.vec.push(FnPointerCandidate); } @@ -1353,7 +1355,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { def.for_each_relevant_impl( self.tcx(), - obligation.predicate.0.trait_ref.self_ty(), + obligation.predicate.skip_binder().trait_ref.self_ty(), // (*) |impl_def_id| { self.infcx.probe(|snapshot| { if let Ok(_) = self.match_impl(impl_def_id, obligation, snapshot) { @@ -1363,6 +1365,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ); + // (*) just used to extract simplified type, which doesn't + // care about LBR + Ok(()) } @@ -1525,7 +1530,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } }; - let target = obligation.predicate.0.input_types()[0]; + let target = obligation.predicate.skip_binder().input_types()[0]; // (*) + // (*) tests below do not examine regions debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", source, target); @@ -1688,7 +1694,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // forego the skolemization and defer it until the // confirmation step. - let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty()); + let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); return match self_ty.sty { ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | @@ -1861,7 +1867,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn ok_if<'tcx>(v: Vec>) -> Result, SelectionError<'tcx>> { - Ok(If(ty::Binder(v))) + Ok(If(ty::Binder::new(v))) } fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound, @@ -1996,7 +2002,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let bound_types: Vec>> = types.skip_binder() .iter() - .map(|&nested_ty| ty::Binder(nested_ty)) + .map(|&nested_ty| ty::Binder::new(nested_ty)) .collect(); // For each type, produce a vector of resulting obligations @@ -2203,10 +2209,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation, trait_def_id); - // binder is moved below - let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); - let types = self.constituent_types_for_ty(self_ty); - self.vtable_default_impl(obligation, trait_def_id, ty::Binder(types)) + let types = obligation.predicate.map_bound_ref(|predicate| { + let self_ty = self.infcx.shallow_resolve(predicate.self_ty()); + self.constituent_types_for_ty(self_ty) + }); + self.vtable_default_impl(obligation, trait_def_id, types) } fn confirm_default_impl_object_candidate(&mut self, @@ -2234,7 +2241,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .collect(); // reintroduce the two binding levels we skipped, then flatten into one - let all_types = ty::Binder(ty::Binder(all_types)); + let all_types = ty::Binder::new(ty::Binder::new(all_types)); let all_types = self.tcx().flatten_late_bound_regions(&all_types); self.vtable_default_impl(obligation, trait_def_id, all_types) @@ -2513,7 +2520,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // regions here. See the comment there for more details. let source = self.infcx.shallow_resolve( tcx.no_late_bound_regions(&obligation.self_ty()).unwrap()); - let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]); + let target = + self.infcx.shallow_resolve( + obligation.predicate.skip_binder().input_types()[0]); // (*) + // (*) ok to skip_binder + // as tests below do not consider regions debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", source, target); @@ -2545,7 +2556,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { data_b.bounds.region_bound); nested.push(Obligation::with_depth(cause, obligation.recursion_depth + 1, - ty::Binder(outlives).to_predicate())); + ty::Binder::new(outlives).to_predicate())); } // T -> Trait. @@ -2592,7 +2603,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // being cast to `Foo+'a` outlives `'a`: let outlives = ty::OutlivesPredicate(source, data.bounds.region_bound); - push(ty::Binder(outlives).to_predicate()); + push(ty::Binder::new(outlives).to_predicate()); } // [T; n] -> [T]. @@ -2779,8 +2790,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // We can avoid creating type variables and doing the full // substitution if we find that any of the input types, when // simplified, do not match. + // + // (*) OK to skip_binder, fast-reject doesn't care about LBR - obligation.predicate.0.input_types().iter() + obligation.predicate.skip_binder().input_types().iter() // (*) .zip(impl_trait_ref.input_types()) .any(|(&obligation_ty, &impl_ty)| { let simplified_obligation_ty = @@ -2863,19 +2876,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { -> ty::PolyTraitRef<'tcx> { let closure_type = self.infcx.closure_type(closure_def_id, substs); - let ty::Binder((trait_ref, _)) = - util::closure_trait_ref_and_return_type(self.tcx(), - obligation.predicate.def_id(), - obligation.predicate.0.self_ty(), // (1) - &closure_type.sig, - util::TupleArgumentsFlag::No); + let self_ty = obligation.predicate.skip_binder().self_ty(); // (1) + util::closure_trait_ref_and_return_type(self.tcx(), + obligation.predicate.def_id(), + self_ty, + &closure_type.sig, + util::TupleArgumentsFlag::No) + .map_bound(|(trait_ref, _)| trait_ref) + // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an unboxed closure type and hence is // in fact unparameterized (or at least does not reference any // regions bound in the obligation). Still probably some // refactoring could make this nicer. - - ty::Binder(trait_ref) } fn closure_trait_ref(&mut self, diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 7668b8bf20282..4c3eb3d19a01a 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -495,14 +495,16 @@ pub fn closure_trait_ref_and_return_type<'tcx>( tuple_arguments: TupleArgumentsFlag) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> { - let arguments_tuple = match tuple_arguments { - TupleArgumentsFlag::No => sig.0.inputs[0], - TupleArgumentsFlag::Yes => tcx.mk_tup(sig.0.inputs.to_vec()), - }; - let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty); - let trait_ref = ty::TraitRef { - def_id: fn_trait_def_id, - substs: tcx.mk_substs(trait_substs), - }; - ty::Binder((trait_ref, sig.0.output.unwrap_or(tcx.mk_nil()))) + sig.map_bound_ref(|sig| { + let arguments_tuple = match tuple_arguments { + TupleArgumentsFlag::No => sig.inputs[0], + TupleArgumentsFlag::Yes => tcx.mk_tup(sig.inputs.to_vec()), + }; + let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty); + let trait_ref = ty::TraitRef { + def_id: fn_trait_def_id, + substs: tcx.mk_substs(trait_substs), + }; + (trait_ref, sig.output.unwrap_or(tcx.mk_nil())) + }) } diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs index d0ccc3e0fdd80..445a46627c105 100644 --- a/src/librustc/ty/_match.rs +++ b/src/librustc/ty/_match.rs @@ -91,6 +91,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { -> RelateResult<'tcx, ty::Binder> where T: Relate<'a,'tcx> { - Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) + Ok(ty::Binder::new(self.relate(a.skip_binder(), b.skip_binder())?)) } } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 29647253ad2ad..44f89855668c9 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -84,7 +84,7 @@ pub fn simplify_type(tcx: &TyCtxt, Some(TupleSimplifiedType(tys.len())) } ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => { - Some(FunctionSimplifiedType(f.sig.0.inputs.len())) + Some(FunctionSimplifiedType(f.sig.skip_binder().inputs.len())) } ty::TyProjection(_) | ty::TyParam(_) => { if can_simplify_params { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index f3dcccedc594b..40f37d3088bb2 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -106,10 +106,11 @@ impl FlagComputation { &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { let mut computation = FlagComputation::new(); - computation.add_substs(principal.0.substs); + computation.add_substs(principal.skip_binder().substs); for projection_bound in &bounds.projection_bounds { let mut proj_computation = FlagComputation::new(); - proj_computation.add_projection_predicate(&projection_bound.0); + proj_computation.add_projection_predicate( + projection_bound.skip_binder()); self.add_bound_computation(&proj_computation); } self.add_bound_computation(&computation); @@ -159,9 +160,9 @@ impl FlagComputation { fn add_fn_sig(&mut self, fn_sig: &ty::PolyFnSig) { let mut computation = FlagComputation::new(); - computation.add_tys(&fn_sig.0.inputs); + computation.add_tys(&fn_sig.skip_binder().inputs); - if let ty::FnConverging(output) = fn_sig.0.output { + if let ty::FnConverging(output) = fn_sig.skip_binder().output { computation.add_ty(output); } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 54223e16e17c5..6086bd82b3412 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -369,16 +369,16 @@ impl<'tcx> TyCtxt<'tcx> { } } }); - Binder(value) + Binder::new(value) } pub fn no_late_bound_regions(&self, value: &Binder) -> Option where T : TypeFoldable<'tcx> { - if value.0.has_escaping_regions() { + if value.skip_binder().has_escaping_regions() { None } else { - Some(value.0.clone()) + Some(value.skip_binder().clone()) } } @@ -402,7 +402,7 @@ impl<'tcx> TyCtxt<'tcx> { where T : TypeFoldable<'tcx>, { let mut counter = 0; - Binder(self.replace_late_bound_regions(sig, |_| { + Binder::new(self.replace_late_bound_regions(sig, |_| { counter += 1; ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(counter)) }).0) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 47e8f91b48c61..9b09501a94f3d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -905,18 +905,18 @@ impl<'tcx> Predicate<'tcx> { // from the substitution and the value being substituted into, and // this trick achieves that). - let substs = &trait_ref.0.substs; + let substs = &trait_ref.skip_binder().substs; // (*) see final paragraph above match *self { - Predicate::Trait(ty::Binder(ref data)) => - Predicate::Trait(ty::Binder(data.subst(tcx, substs))), - Predicate::Equate(ty::Binder(ref data)) => - Predicate::Equate(ty::Binder(data.subst(tcx, substs))), - Predicate::RegionOutlives(ty::Binder(ref data)) => - Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))), - Predicate::TypeOutlives(ty::Binder(ref data)) => - Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))), - Predicate::Projection(ty::Binder(ref data)) => - Predicate::Projection(ty::Binder(data.subst(tcx, substs))), + Predicate::Trait(ref data) => + Predicate::Trait(data.map_bound_ref(|d| d.subst(tcx, substs))), + Predicate::Equate(ref data) => + Predicate::Equate(data.map_bound_ref(|d| d.subst(tcx, substs))), + Predicate::RegionOutlives(ref data) => + Predicate::RegionOutlives(data.map_bound_ref(|d| d.subst(tcx, substs))), + Predicate::TypeOutlives(ref data) => + Predicate::TypeOutlives(data.map_bound_ref(|d| d.subst(tcx, substs))), + Predicate::Projection(ref data) => + Predicate::Projection(data.map_bound_ref(|d| d.subst(tcx, substs))), Predicate::WellFormed(data) => Predicate::WellFormed(data.subst(tcx, substs)), Predicate::ObjectSafe(trait_def_id) => @@ -953,12 +953,12 @@ impl<'tcx> TraitPredicate<'tcx> { impl<'tcx> PolyTraitPredicate<'tcx> { pub fn def_id(&self) -> DefId { // ok to skip binder since trait def-id does not care about regions - self.0.def_id() + self.skip_binder().def_id() } pub fn dep_node(&self) -> DepNode { // ok to skip binder since depnode does not care about regions - self.0.dep_node() + self.skip_binder().dep_node() } } @@ -994,11 +994,11 @@ pub type PolyProjectionPredicate<'tcx> = Binder>; impl<'tcx> PolyProjectionPredicate<'tcx> { pub fn item_name(&self) -> Name { - self.0.projection_ty.item_name // safe to skip the binder to access a name + self.skip_binder().projection_ty.item_name // safe to skip the binder to access a name } pub fn sort_key(&self) -> (DefId, Name) { - self.0.projection_ty.sort_key() + self.skip_binder().projection_ty.sort_key() } } @@ -1009,7 +1009,7 @@ pub trait ToPolyTraitRef<'tcx> { impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { assert!(!self.has_escaping_regions()); - ty::Binder(self.clone()) + ty::Binder::new(self.clone()) } } @@ -1021,12 +1021,7 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - // Note: unlike with TraitRef::to_poly_trait_ref(), - // self.0.trait_ref is permitted to have escaping regions. - // This is because here `self` has a `Binder` and so does our - // return value, so we are preserving the number of binding - // levels. - ty::Binder(self.0.projection_ty.trait_ref) + self.map_bound_ref(|s| s.projection_ty.trait_ref) } } @@ -1041,7 +1036,7 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { // weird debruijn accounting. assert!(!self.has_escaping_regions()); - ty::Predicate::Trait(ty::Binder(ty::TraitPredicate { + ty::Predicate::Trait(ty::Binder::new(ty::TraitPredicate { trait_ref: self.clone() })) } @@ -1084,22 +1079,25 @@ impl<'tcx> Predicate<'tcx> { pub fn walk_tys(&self) -> IntoIter> { let vec: Vec<_> = match *self { ty::Predicate::Trait(ref data) => { - data.0.trait_ref.substs.types.as_slice().to_vec() + data.skip_binder().trait_ref.substs.types.as_slice().to_vec() + // ^ skip binders } - ty::Predicate::Equate(ty::Binder(ref data)) => { + ty::Predicate::Equate(ref data) => { + let data = data.skip_binder(); // as noted above, skip binders vec![data.0, data.1] } - ty::Predicate::TypeOutlives(ty::Binder(ref data)) => { - vec![data.0] + ty::Predicate::TypeOutlives(ref data) => { + vec![data.skip_binder().0] // as noted above, skip binders } ty::Predicate::RegionOutlives(..) => { vec![] } ty::Predicate::Projection(ref data) => { - let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice(); + let trait_inputs = + data.skip_binder().projection_ty.trait_ref.substs.types.as_slice(); trait_inputs.iter() .cloned() - .chain(Some(data.0.ty)) + .chain(Some(data.skip_binder().ty)) .collect() } ty::Predicate::WellFormed(data) => { @@ -2670,7 +2668,8 @@ impl<'tcx> TyCtxt<'tcx> { // let bounds = generic_predicates.instantiate(self, &free_substs); - let bounds = self.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds)); + let bounds = self.liberate_late_bound_regions(free_id_outlive, + &ty::Binder::new(bounds)); let predicates = bounds.predicates.into_vec(); // Finally, we have to normalize the bounds in the environment, in diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index bbf6d0329b4ee..f7c1e385790fe 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -104,7 +104,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder { type Lifted = ty::Binder; fn lift_to_tcx(&self, tcx: &TyCtxt<'tcx>) -> Option { - tcx.lift(&self.0).map(|x| ty::Binder(x)) + tcx.lift(self.skip_binder()).map(|x| ty::Binder::new(x)) } } @@ -190,7 +190,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { fn super_fold_with>(&self, folder: &mut F) -> Self { - ty::Binder(self.0.fold_with(folder)) + ty::Binder::new(self.skip_binder().fold_with(folder)) } fn fold_with>(&self, folder: &mut F) -> Self { @@ -198,7 +198,7 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.0.visit_with(visitor) + self.skip_binder().visit_with(visitor) } fn visit_with>(&self, visitor: &mut V) -> bool { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index c0fb60d4dd3dc..1a338eb976bad 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -273,7 +273,7 @@ pub struct TraitTy<'tcx> { impl<'tcx> TraitTy<'tcx> { pub fn principal_def_id(&self) -> DefId { - self.principal.0.def_id + self.principal.skip_binder().def_id } /// Object types don't have a self-type specified. Therefore, when @@ -288,9 +288,11 @@ impl<'tcx> TraitTy<'tcx> { // otherwise the escaping regions would be captured by the binder assert!(!self_ty.has_escaping_regions()); - ty::Binder(TraitRef { - def_id: self.principal.0.def_id, - substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)), + self.principal.map_bound_ref(|p| { + TraitRef { + def_id: p.def_id, + substs: tcx.mk_substs(p.substs.with_self_ty(self_ty)) + } }) } @@ -304,17 +306,21 @@ impl<'tcx> TraitTy<'tcx> { self.bounds.projection_bounds.iter() .map(|in_poly_projection_predicate| { - let in_projection_ty = &in_poly_projection_predicate.0.projection_ty; - let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty)); - let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id, - substs); - let projection_ty = ty::ProjectionTy { - trait_ref: trait_ref, - item_name: in_projection_ty.item_name - }; - ty::Binder(ty::ProjectionPredicate { - projection_ty: projection_ty, - ty: in_poly_projection_predicate.0.ty + in_poly_projection_predicate.map_bound_ref(|in_projection_predicate| { + let in_projection_ty = &in_projection_predicate.projection_ty; + let substs = + tcx.mk_substs( + in_projection_ty.trait_ref.substs.with_self_ty(self_ty)); + let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id, + substs); + let projection_ty = ty::ProjectionTy { + trait_ref: trait_ref, + item_name: in_projection_ty.item_name + }; + ty::ProjectionPredicate { + projection_ty: projection_ty, + ty: in_projection_predicate.ty + } }) }) .collect() @@ -346,26 +352,27 @@ pub type PolyTraitRef<'tcx> = Binder>; impl<'tcx> PolyTraitRef<'tcx> { pub fn self_ty(&self) -> Ty<'tcx> { - self.0.self_ty() + // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> + self.skip_binder().self_ty() } pub fn def_id(&self) -> DefId { - self.0.def_id + self.skip_binder().def_id } pub fn substs(&self) -> &'tcx Substs<'tcx> { // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> - self.0.substs + self.skip_binder().substs } pub fn input_types(&self) -> &[Ty<'tcx>] { // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> - self.0.input_types() + self.skip_binder().input_types() } pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { // Note that we preserve binding levels - Binder(ty::TraitPredicate { trait_ref: self.0.clone() }) + self.map_bound_ref(|&trait_ref| ty::TraitPredicate { trait_ref: trait_ref }) } } @@ -377,9 +384,15 @@ impl<'tcx> PolyTraitRef<'tcx> { /// type from `Binder` to just `T` (see /// e.g. `liberate_late_bound_regions`). #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub struct Binder(pub T); +pub struct Binder { + bound: T +} impl Binder { + pub fn new(bound: T) -> Binder { + Binder { bound: bound } + } + /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// debruijn indices and the like. It is usually better to @@ -396,11 +409,15 @@ impl Binder { /// - comparing the self type of a PolyTraitRef to see if it is equal to /// a type parameter `X`, since the type `X` does not reference any regions pub fn skip_binder(&self) -> &T { - &self.0 + &self.bound + } + + pub fn skip_binder_mut(&mut self) -> &mut T { + &mut self.bound } pub fn as_ref(&self) -> Binder<&T> { - ty::Binder(&self.0) + ty::Binder::new(&self.bound) } pub fn map_bound_ref(&self, f: F) -> Binder @@ -412,7 +429,7 @@ impl Binder { pub fn map_bound(self, f: F) -> Binder where F: FnOnce(T) -> U { - ty::Binder(f(self.0)) + ty::Binder::new(f(self.bound)) } } @@ -483,7 +500,7 @@ pub type PolyFnOutput<'tcx> = Binder>; impl<'tcx> PolyFnOutput<'tcx> { pub fn diverges(&self) -> bool { - self.0.diverges() + self.skip_binder().diverges() } } @@ -503,6 +520,9 @@ pub struct FnSig<'tcx> { pub type PolyFnSig<'tcx> = Binder>; impl<'tcx> PolyFnSig<'tcx> { + pub fn inputs_len(&self) -> usize { + self.skip_binder().inputs.len() + } pub fn inputs(&self) -> ty::Binder>> { self.map_bound_ref(|fn_sig| fn_sig.inputs.clone()) } @@ -512,6 +532,12 @@ impl<'tcx> PolyFnSig<'tcx> { pub fn output(&self) -> ty::Binder> { self.map_bound_ref(|fn_sig| fn_sig.output.clone()) } + pub fn is_converging(&self) -> bool { + !self.diverges() + } + pub fn diverges(&self) -> bool { + self.skip_binder().output.diverges() + } pub fn variadic(&self) -> bool { self.skip_binder().variadic } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 354744b27875d..3acbf9ddb0428 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -304,7 +304,9 @@ impl<'tcx> TyCtxt<'tcx> { ty::Predicate::RegionOutlives(..) => { None } - ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => { + ty::Predicate::TypeOutlives(ref data) => { + let &ty::OutlivesPredicate(t, r) = data.skip_binder(); // (*) + // Search for a bound of the form `erased_self_ty // : 'a`, but be wary of something like `for<'a> // erased_self_ty : 'a` (we interpret a @@ -314,6 +316,9 @@ impl<'tcx> TyCtxt<'tcx> { // it's kind of a moot point since you could never // construct such an object, but this seems // correct even if that code changes). + // + // (*) ok to skip-binder because we are + // careful about escaping regions below. if t == erased_self_ty && !r.has_escaping_regions() { Some(r) } else { @@ -368,7 +373,8 @@ impl<'tcx> TyCtxt<'tcx> { mt.mutbl.hash(state); }; let fn_sig = |state: &mut SipHasher, sig: &ty::Binder>| { - let sig = tcx.anonymize_late_bound_regions(sig).0; + let sig = tcx.anonymize_late_bound_regions(sig); + let sig = sig.skip_binder(); for a in &sig.inputs { helper(tcx, *a, svh, state); } if let ty::FnConverging(output) = sig.output { helper(tcx, output, svh, state); @@ -432,7 +438,10 @@ impl<'tcx> TyCtxt<'tcx> { did(state, data.principal_def_id()); hash!(data.bounds); - let principal = tcx.anonymize_late_bound_regions(&data.principal).0; + let principal = + tcx.anonymize_late_bound_regions(&data.principal) + .skip_binder() + .clone(); for subty in &principal.substs.types { helper(tcx, subty, svh, state); } diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index fa7c9b782311f..c52eca4bf81d0 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -84,7 +84,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { push_reversed(stack, principal.substs().types.as_slice()); push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| { - pred.0.ty + pred.skip_binder().ty // walk ignores LBR }).collect::>()); } ty::TyEnum(_, ref substs) | @@ -109,11 +109,11 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { } fn push_sig_subtypes<'tcx>(stack: &mut Vec>, sig: &ty::PolyFnSig<'tcx>) { - match sig.0.output { + match sig.skip_binder().output { ty::FnConverging(output) => { stack.push(output); } ty::FnDiverging => { } } - push_reversed(stack, &sig.0.inputs); + push_reversed(stack, &sig.skip_binder().inputs); } fn push_reversed<'tcx>(stack: &mut Vec>, tys: &[Ty<'tcx>]) { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 9ea634bb41c1b..3440c291c679a 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -339,7 +339,7 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> { traits::Obligation::new( cause, ty::Predicate::TypeOutlives( - ty::Binder( + ty::Binder::new( ty::OutlivesPredicate(mt.ty, *r))))); } } @@ -473,7 +473,9 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> { for implicit_bound in implicit_bounds { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); - let outlives = ty::Binder(ty::OutlivesPredicate(explicit_bound, implicit_bound)); + let outlives = + ty::Binder::new(ty::OutlivesPredicate(explicit_bound, + implicit_bound)); self.out.push(traits::Obligation::new(cause, outlives.to_predicate())); } } @@ -497,10 +499,12 @@ pub fn object_region_bounds<'tcx>( // a skolemized type. let open_ty = tcx.mk_infer(ty::FreshTy(0)); - // Note that we preserve the overall binding levels here. assert!(!open_ty.has_escaping_regions()); - let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty)); - let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs))); + let trait_ref = principal.map_bound_ref(|principal| { + let substs = tcx.mk_substs(principal.substs.with_self_ty(open_ty)); + ty::TraitRef::new(principal.def_id, substs) + }); + let trait_refs = vec!(trait_ref); let mut predicates = others.to_predicates(tcx, open_ty); predicates.extend(trait_refs.iter().map(|t| t.to_predicate())); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 2173b919d1336..da0548e421f60 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -244,7 +244,7 @@ fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter, let value = if let Some(v) = lifted { v } else { - return write!(f, "{}", original.0); + return write!(f, "{}", original.skip_binder()); }; let mut empty = true; @@ -319,14 +319,16 @@ impl<'tcx> fmt::Display for ty::TraitTy<'tcx> { // Generate the main trait ref, including associated types. ty::tls::with(|tcx| { - let principal = tcx.lift(&self.principal.0) + let principal = tcx.lift(self.principal.skip_binder()) .expect("could not lift TraitRef for printing"); let projections = tcx.lift(&bounds.projection_bounds[..]) .expect("could not lift projections for printing"); - let projections = projections.into_iter().map(|p| p.0).collect(); + let projections = projections.into_iter() + .map(|p| p.skip_binder().clone()) + .collect(); - let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap)) + let tap = ty::Binder::new(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder::new(""), Some(tap)) })?; // Builtin bounds. @@ -855,7 +857,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { write!(f, "extern {} ", bare_fn.abi)?; } - write!(f, "{} {{", bare_fn.sig.0)?; + write!(f, "{} {{", bare_fn.sig.skip_binder())?; parameterized(f, substs, def_id, Ns::Value, &[], |tcx| tcx.lookup_item_type(def_id).generics)?; write!(f, "}}") @@ -869,7 +871,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { write!(f, "extern {} ", bare_fn.abi)?; } - write!(f, "{}", bare_fn.sig.0) + write!(f, "{}", bare_fn.sig.skip_binder()) } TyInfer(infer_ty) => write!(f, "{}", infer_ty), TyError => write!(f, "[type error]"), diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 45a90bf00681c..a58d813201ab0 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -990,7 +990,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>, rcvr_substs: subst::Substs<'tcx>) -> Option<(&'tcx Expr, Option>)> { - let trait_ref = ty::Binder( + let trait_ref = ty::Binder::new( rcvr_substs.erase_regions().to_trait_ref(tcx, trait_id) ); debug!("resolve_trait_associated_const: trait_ref={:?}", diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index fc12d546288b4..2be098852ea56 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -269,7 +269,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { self.infcx.tcx.mk_fn_ptr(ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, - sig: ty::Binder(ty::FnSig { + sig: ty::Binder::new(ty::FnSig { inputs: input_args, output: ty::FnConverging(output_ty), variadic: false, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 5e3a47701ebbf..45e3c1ffb790b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -858,7 +858,7 @@ impl LateLintPass for UnconditionalRecursion { // Attempt to select a concrete impl before checking. ty::TraitContainer(trait_def_id) => { let trait_ref = callee_substs.to_trait_ref(tcx, trait_def_id); - let trait_ref = ty::Binder(trait_ref); + let trait_ref = ty::Binder::new(trait_ref); let span = tcx.map.span(expr_id); let obligation = traits::Obligation::new(traits::ObligationCause::misc(span, expr_id), @@ -1071,8 +1071,9 @@ impl LateLintPass for MutableTransmutes { let typ = cx.tcx.node_id_to_type(expr.id); match typ.sty { ty::TyFnDef(_, _, ref bare_fn) if bare_fn.abi == RustIntrinsic => { - if let ty::FnConverging(to) = bare_fn.sig.0.output { - let from = bare_fn.sig.0.inputs[0]; + let sig = bare_fn.sig.skip_binder(); + if let ty::FnConverging(to) = sig.output { + let from = sig.inputs[0]; return Some((&from.sty, &to.sty)); } }, diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 6fd9f27f0fb9f..a1b28aebfc068 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -948,7 +948,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> ty::PolyTraitRef<'tcx> { - ty::Binder(self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref())) + ty::Binder::new(self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref())) } fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index a0881f1153e39..e6a22b43336b9 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -468,10 +468,9 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner, variant.name, ctor_ty); let field_tys = match ctor_ty.sty { - ty::TyFnDef(_, _, &ty::BareFnTy { sig: ty::Binder(ty::FnSig { - ref inputs, .. - }), ..}) => { + ty::TyFnDef(_, _, &ty::BareFnTy { ref sig, .. }) => { // tuple-struct constructors don't have escaping regions + let inputs = &sig.skip_binder().inputs; assert!(!inputs.has_escaping_regions()); inputs }, diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 3004246d1d7e7..edd5783ab8969 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -329,7 +329,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } 'x' => { assert_eq!(self.next(), '['); - let trait_ref = ty::Binder(self.parse_trait_ref()); + let trait_ref = ty::Binder::new(self.parse_trait_ref()); let bounds = self.parse_existential_bounds(); assert_eq!(self.next(), ']'); return tcx.mk_trait(trait_ref, bounds); @@ -532,21 +532,21 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } _ => ty::FnConverging(self.parse_ty()) }; - ty::Binder(ty::FnSig {inputs: inputs, - output: output, - variadic: variadic}) + ty::Binder::new(ty::FnSig {inputs: inputs, + output: output, + variadic: variadic}) } pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> { match self.next() { - 't' => ty::Binder(self.parse_trait_ref()).to_predicate(), - 'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(), - self.parse_ty())).to_predicate(), - 'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(), - self.parse_region())).to_predicate(), - 'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(), - self.parse_region())).to_predicate(), - 'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(), + 't' => ty::Binder::new(self.parse_trait_ref()).to_predicate(), + 'e' => ty::Binder::new(ty::EquatePredicate(self.parse_ty(), + self.parse_ty())).to_predicate(), + 'r' => ty::Binder::new(ty::OutlivesPredicate(self.parse_region(), + self.parse_region())).to_predicate(), + 'o' => ty::Binder::new(ty::OutlivesPredicate(self.parse_ty(), + self.parse_region())).to_predicate(), + 'p' => ty::Binder::new(self.parse_projection_predicate()).to_predicate(), 'w' => ty::Predicate::WellFormed(self.parse_ty()), 'O' => { let def_id = self.parse_def(); @@ -636,7 +636,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { loop { match self.next() { 'P' => { - projection_bounds.push(ty::Binder(self.parse_projection_predicate())); + projection_bounds.push(ty::Binder::new(self.parse_projection_predicate())); } '.' => { break; } c => { diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index f49c2e22c6a80..afe763cfe5af8 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -106,7 +106,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { write!(w, "x["); - enc_trait_ref(w, cx, principal.0); + enc_trait_ref(w, cx, *principal.skip_binder()); enc_existential_bounds(w, cx, bounds); write!(w, "]"); } @@ -358,16 +358,16 @@ pub fn enc_closure_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, fsig: &ty::PolyFnSig<'tcx>) { write!(w, "["); - for ty in &fsig.0.inputs { + for ty in &fsig.skip_binder().inputs { enc_ty(w, cx, *ty); } write!(w, "]"); - if fsig.0.variadic { + if fsig.skip_binder().variadic { write!(w, "V"); } else { write!(w, "N"); } - match fsig.0.output { + match fsig.skip_binder().output { ty::FnConverging(result_type) => { enc_ty(w, cx, result_type); } @@ -399,7 +399,7 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor>, for tp in &bs.projection_bounds { write!(w, "P"); - enc_projection_predicate(w, cx, &tp.0); + enc_projection_predicate(w, cx, tp.skip_binder()); } write!(w, "."); @@ -451,26 +451,29 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, match *p { ty::Predicate::Trait(ref trait_ref) => { write!(w, "t"); - enc_trait_ref(w, cx, trait_ref.0.trait_ref); + enc_trait_ref(w, cx, trait_ref.skip_binder().trait_ref); } - ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => { + ty::Predicate::Equate(ref data) => { + let &ty::EquatePredicate(a, b) = data.skip_binder(); write!(w, "e"); enc_ty(w, cx, a); enc_ty(w, cx, b); } - ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => { + ty::Predicate::RegionOutlives(ref data) => { + let &ty::OutlivesPredicate(a, b) = data.skip_binder(); write!(w, "r"); enc_region(w, cx, a); enc_region(w, cx, b); } - ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => { + ty::Predicate::TypeOutlives(ref data) => { + let &ty::OutlivesPredicate(a, b) = data.skip_binder(); write!(w, "o"); enc_ty(w, cx, a); enc_region(w, cx, b); } - ty::Predicate::Projection(ty::Binder(ref data)) => { + ty::Predicate::Projection(ref data) => { write!(w, "p"); - enc_projection_predicate(w, cx, data); + enc_projection_predicate(w, cx, data.skip_binder()); } ty::Predicate::WellFormed(data) => { write!(w, "w"); diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 231d7da10a02d..f04ee4384b241 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -268,7 +268,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { ExprKind::Call { ty, fun, args } => { let diverges = match ty.sty { ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => { - f.sig.0.output.diverges() + f.sig.diverges() } _ => false }; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index a6ce4cc3ee41a..376f1b633fed1 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -450,10 +450,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { if let Def::Struct(..) = self.tcx.resolve_expr(expr) { let expr_ty = self.tcx.expr_ty(expr); let def = match expr_ty.sty { - ty::TyFnDef(_, _, &ty::BareFnTy { sig: ty::Binder(ty::FnSig { - output: ty::FnConverging(ty), .. - }), ..}) => ty, - _ => expr_ty + ty::TyFnDef(_, _, &ty::BareFnTy { ref sig, .. }) => + match *sig.output().skip_binder() { + ty::FnConverging(ty) => ty, + ty::FnDiverging => expr_ty, + }, + _ => + expr_ty, }.ty_adt_def().unwrap(); let any_priv = def.struct_variant().fields.iter().any(|f| { !f.vis.is_accessible_from(self.curitem, &self.tcx.map) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c8ed4e629e4c1..0c5238a43203b 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -565,11 +565,13 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, } (_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => { // Note that we preserve binding levels here: - let substs = principal.0.substs.with_self_ty(source).erase_regions(); - let substs = ccx.tcx().mk_substs(substs); - let trait_ref = ty::Binder(ty::TraitRef { - def_id: principal.def_id(), - substs: substs, + let trait_ref = principal.map_bound_ref(|p| { + let substs = p.substs.with_self_ty(source).erase_regions(); + let substs = ccx.tcx().mk_substs(substs); + ty::TraitRef { + def_id: principal.def_id(), + substs: substs, + } }); consts::ptrcast(meth::get_vtable(ccx, trait_ref), Type::vtable_ptr(ccx)) @@ -675,7 +677,7 @@ pub fn custom_coerce_unsize_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, Vec::new()), subst::VecPerParamSpace::empty()); - let trait_ref = ty::Binder(ty::TraitRef { + let trait_ref = ty::Binder::new(ty::TraitRef { def_id: ccx.tcx().lang_items.coerce_unsized_trait().unwrap(), substs: ccx.tcx().mk_substs(trait_substs) }); diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 392c40a60155c..9299b330ce456 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -155,7 +155,7 @@ impl<'tcx> Callee<'tcx> { let method_item = tcx.impl_or_trait_item(def_id); let trait_id = method_item.container().id(); - let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id)); + let trait_ref = ty::Binder::new(substs.to_trait_ref(tcx, trait_id)); match common::fulfill_obligation(ccx, DUMMY_SP, trait_ref) { traits::VtableImpl(vtable_impl) => { let impl_did = vtable_impl.impl_def_id; @@ -373,7 +373,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( let tuple_fn_ty = tcx.mk_fn_ptr(ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: Abi::RustCall, - sig: ty::Binder(sig) + sig: ty::Binder::new(sig) }); debug!("tuple_fn_ty: {:?}", tuple_fn_ty); @@ -624,7 +624,7 @@ fn trans_call_inner<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let extra_args = match args { ArgExprs(args) if abi != Abi::RustCall => { - args[sig.0.inputs.len()..].iter().map(|expr| { + args[sig.inputs_len()..].iter().map(|expr| { common::expr_ty_adjusted(bcx, expr) }).collect() } diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 6bd5fd355a731..1b2c2dc52c94f 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -163,7 +163,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let function_type = tcx.mk_fn_ptr(ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: Abi::RustCall, - sig: ty::Binder(ty::FnSig { + sig: ty::Binder::new(ty::FnSig { inputs: Some(get_self_type(tcx, closure_id, closure_type)) .into_iter().chain(sig.inputs).collect(), output: sig.output, @@ -355,7 +355,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( // Make a version with the type of by-ref closure. let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, &substs); - sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet + sig.skip_binder_mut().inputs.insert(0, ref_closure_ty); // sig has no self type as of yet let llref_fn_ty = tcx.mk_fn_ptr(ty::BareFnTy { unsafety: unsafety, abi: abi, @@ -368,7 +368,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( // Make a version of the closure type with the same arguments, but // with argument #0 being by value. assert_eq!(abi, Abi::RustCall); - sig.0.inputs[0] = closure_ty; + sig.skip_binder_mut().inputs[0] = closure_ty; let sig = tcx.erase_late_bound_regions(&sig); let sig = infer::normalize_associated_type(ccx.tcx(), &sig); @@ -377,7 +377,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( let llonce_fn_ty = tcx.mk_fn_ptr(ty::BareFnTy { unsafety: unsafety, abi: abi, - sig: ty::Binder(sig) + sig: ty::Binder::new(sig) }); // Create the by-value helper. diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index c72a1a6bef32f..2eac880fe0c69 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -733,7 +733,7 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, param_substs, callee_substs); - let trait_ref = ty::Binder(rcvr_substs.to_trait_ref(tcx, trait_id)); + let trait_ref = ty::Binder::new(rcvr_substs.to_trait_ref(tcx, trait_id)); let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref); // Now that we know which impl is being used, we can dispatch to diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 5ce7caf5deb06..0a7d134883c6f 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -500,7 +500,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { let ty = tcx.mk_fn_ptr(ty::BareFnTy { unsafety: hir::Unsafety::Unsafe, abi: Abi::C, - sig: ty::Binder(ty::FnSig { + sig: ty::Binder::new(ty::FnSig { inputs: vec![tcx.mk_mut_ptr(tcx.types.u8)], output: ty::FnDiverging, variadic: false @@ -1181,10 +1181,10 @@ pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("inlined_variant_def: ctor_ty={:?} inlined_vid={:?}", ctor_ty, inlined_vid); let adt_def = match ctor_ty.sty { - ty::TyFnDef(_, _, &ty::BareFnTy { sig: ty::Binder(ty::FnSig { - output: ty::FnConverging(ty), .. - }), ..}) => ty, - _ => ctor_ty + ty::TyFnDef(_, _, &ty::BareFnTy { ref sig, .. }) => + ccx.tcx().no_late_bound_regions(&sig.output()).unwrap().unwrap(), + _ => + ctor_ty, }.ty_adt_def().unwrap(); let inlined_vid_def_id = ccx.tcx().map.local_def_id(inlined_vid); adt_def.variants.iter().find(|v| { diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 5676024ea956e..07a9ea469c1c7 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -361,7 +361,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, &unsized_args }; - let trait_ref = ty::Binder(ty::TraitRef { + let trait_ref = ty::Binder::new(ty::TraitRef { def_id: tcx.lang_items.drop_trait().unwrap(), substs: tcx.mk_substs(Substs::empty().with_self_ty(t)) }); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 5924ae1ad84c5..8e5ef39be40eb 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -1316,7 +1316,7 @@ fn gen_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>, let rust_fn_ty = ccx.tcx().mk_fn_ptr(ty::BareFnTy { unsafety: hir::Unsafety::Unsafe, abi: Abi::Rust, - sig: ty::Binder(sig) + sig: ty::Binder::new(sig) }); let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty); let empty_substs = ccx.tcx().mk_substs(Substs::empty()); @@ -1347,7 +1347,7 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>, let fn_ty = tcx.mk_fn_ptr(ty::BareFnTy { unsafety: hir::Unsafety::Unsafe, abi: Abi::Rust, - sig: ty::Binder(ty::FnSig { + sig: ty::Binder::new(ty::FnSig { inputs: vec![i8p], output: ty::FnOutput::FnConverging(tcx.mk_nil()), variadic: false, diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 3fabdd8fd4226..02298f316d794 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -215,7 +215,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { return; } - let extra_args = &args[sig.0.inputs.len()..]; + let extra_args = &args[sig.inputs_len()..]; let extra_args = extra_args.iter().map(|op_arg| { self.mir.operand_ty(bcx.tcx(), op_arg) }).collect::>(); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 21122e7095dd1..9391a42433fba 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -778,7 +778,7 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>( trait_def_id, self_ty, trait_segment); - let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs)); + let poly_trait_ref = ty::Binder::new(ty::TraitRef::new(trait_def_id, substs)); { let converted_bindings = @@ -909,12 +909,14 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>( // Simple case: X is defined in the current trait. if this.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { - return Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------+ - projection_ty: ty::ProjectionTy { // | - trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+ - item_name: binding.item_name, - }, - ty: binding.ty, + return Ok(trait_ref.map_bound(|trait_ref| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref, + item_name: binding.item_name, + }, + ty: binding.ty, + } })); } @@ -928,11 +930,13 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>( let dummy_self_ty = tcx.mk_infer(ty::FreshTy(0)); if self_ty.is_none() { // if converting for an object type - let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+ - assert!(dummy_substs.self_ty().is_none()); // | - dummy_substs.types.push(SelfSpace, dummy_self_ty); // | - trait_ref = ty::Binder(ty::TraitRef::new(trait_ref.def_id(), // <------------+ - tcx.mk_substs(dummy_substs))); + trait_ref = trait_ref.map_bound(|trait_ref| { + let mut dummy_substs = trait_ref.substs.clone(); + assert!(dummy_substs.self_ty().is_none()); + dummy_substs.types.push(SelfSpace, dummy_self_ty); + ty::TraitRef::new(trait_ref.def_id, + tcx.mk_substs(dummy_substs)) + }); } this.ensure_super_predicates(binding.span, trait_ref.def_id())?; @@ -946,11 +950,12 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>( // Yuckety yuck. if self_ty.is_none() { for candidate in &mut candidates { - let mut dummy_substs = candidate.0.substs.clone(); - assert!(dummy_substs.self_ty() == Some(dummy_self_ty)); - dummy_substs.types.pop(SelfSpace); - *candidate = ty::Binder(ty::TraitRef::new(candidate.def_id(), - tcx.mk_substs(dummy_substs))); + *candidate = candidate.map_bound_ref(|candidate| { + let mut dummy_substs = candidate.substs.clone(); + assert!(dummy_substs.self_ty() == Some(dummy_self_ty)); + dummy_substs.types.pop(SelfSpace); + ty::TraitRef::new(candidate.def_id, tcx.mk_substs(dummy_substs)) + }); } } @@ -960,12 +965,14 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>( &binding.item_name.as_str(), binding.span)?; - Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+ - projection_ty: ty::ProjectionTy { // | - trait_ref: candidate.skip_binder().clone(), // binder is moved up here --+ - item_name: binding.item_name, - }, - ty: binding.ty, + Ok(candidate.map_bound_ref(|candidate| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: candidate.clone(), + item_name: binding.item_name, + }, + ty: binding.ty, + } })) } @@ -1154,8 +1161,8 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>, .collect(); for projection_bound in &object.bounds.projection_bounds { - let pair = (projection_bound.0.projection_ty.trait_ref.def_id, - projection_bound.0.projection_ty.item_name); + let pair = (projection_bound.skip_binder().projection_ty.trait_ref.def_id, + projection_bound.skip_binder().projection_ty.item_name); associated_types.remove(&pair); } @@ -1294,7 +1301,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, } let candidates: Vec = - traits::supertraits(tcx, ty::Binder(trait_ref)) + traits::supertraits(tcx, ty::Binder::new(trait_ref)) .filter(|r| this.trait_defines_associated_type_named(r.def_id(), assoc_name)) .collect(); @@ -1340,7 +1347,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, } }; - let trait_did = bound.0.def_id; + let trait_did = bound.def_id(); let ty = this.projected_ty_from_poly_trait_ref(span, bound, assoc_name); let item_did = if let Some(trait_id) = tcx.map.as_local_node_id(trait_did) { @@ -1819,7 +1826,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, (ty::BareFnTy { unsafety: unsafety, abi: abi, - sig: ty::Binder(ty::FnSig { + sig: ty::Binder::new(ty::FnSig { inputs: self_ty.into_iter().chain(arg_tys).collect(), output: output_ty, variadic: decl.variadic @@ -1971,9 +1978,9 @@ pub fn ty_of_closure<'tcx>( ty::ClosureTy { unsafety: unsafety, abi: abi, - sig: ty::Binder(ty::FnSig {inputs: input_tys, - output: output_ty, - variadic: decl.variadic}), + sig: ty::Binder::new(ty::FnSig {inputs: input_tys, + output: output_ty, + variadic: decl.variadic}), } } @@ -2266,7 +2273,9 @@ impl<'tcx> Bounds<'tcx> { // account for the binder being introduced below; no need to shift `param_ty` // because, at present at least, it can only refer to early-bound regions let region_bound = ty::fold::shift_region(region_bound, 1); - vec.push(ty::Binder(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate()); + vec.push( + ty::Binder::new( + ty::OutlivesPredicate(param_ty, region_bound)).to_predicate()); } for bound_trait_ref in &self.trait_bounds { diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 21800d91d9458..28cf143447527 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -250,7 +250,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, // This is the "default" function signature, used in case of error. // In that case, we check each argument against "error" in order to // set up all the node type bindings. - error_fn_sig = ty::Binder(ty::FnSig { + error_fn_sig = ty::Binder::new(ty::FnSig { inputs: err_args(fcx.tcx(), arg_exprs.len()), output: ty::FnConverging(fcx.tcx().types.err), variadic: false diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 7bca570411ceb..014dcde555e0e 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -88,7 +88,8 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, // Tuple up the arguments and insert the resulting function type into // the `closures` table. - fn_ty.sig.0.inputs = vec![fcx.tcx().mk_tup(fn_ty.sig.0.inputs)]; + fn_ty.sig.skip_binder_mut().inputs = + vec![fcx.tcx().mk_tup(fn_ty.sig.skip_binder().inputs.clone())]; debug!("closure for {:?} --> sig={:?} opt_kind={:?}", expr_def_id, @@ -227,7 +228,7 @@ fn deduce_sig_from_projection<'a,'tcx>( }; debug!("deduce_sig_from_projection: input_tys {:?}", input_tys); - let ret_param_ty = projection.0.ty; + let ret_param_ty = projection.skip_binder().ty; let ret_param_ty = fcx.infcx().resolve_type_vars_if_possible(&ret_param_ty); debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 3c12ab8d59840..ce1f275c3b141 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -92,15 +92,15 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>, return; } - if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() { + if impl_m.fty.sig.inputs_len() != trait_m.fty.sig.inputs_len() { span_err!(tcx.sess, impl_m_span, E0050, "method `{}` has {} parameter{} \ but the declaration in trait `{}` has {}", trait_m.name, - impl_m.fty.sig.0.inputs.len(), - if impl_m.fty.sig.0.inputs.len() == 1 {""} else {"s"}, + impl_m.fty.sig.inputs_len(), + if impl_m.fty.sig.inputs_len() == 1 {""} else {"s"}, tcx.item_path_str(trait_m.def_id), - trait_m.fty.sig.0.inputs.len()); + trait_m.fty.sig.inputs_len()); return; } @@ -208,7 +208,7 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>, infcx.replace_late_bound_regions_with_fresh_var( impl_m_span, infer::HigherRankedType, - &ty::Binder(impl_bounds)); + &ty::Binder::new(impl_bounds)); debug!("compare_impl_method: impl_bounds={:?}", impl_bounds); @@ -299,7 +299,7 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>, let impl_fty = tcx.mk_fn_ptr(ty::BareFnTy { unsafety: impl_m.fty.unsafety, abi: impl_m.fty.abi, - sig: ty::Binder(impl_sig) + sig: ty::Binder::new(impl_sig) }); debug!("compare_impl_method: impl_fty={:?}", impl_fty); @@ -317,7 +317,7 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>, let trait_fty = tcx.mk_fn_ptr(ty::BareFnTy { unsafety: trait_m.fty.unsafety, abi: trait_m.fty.abi, - sig: ty::Binder(trait_sig) + sig: ty::Binder::new(trait_sig) }); debug!("compare_impl_method: trait_fty={:?}", diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index eae0cfb0f2267..e74e9920ecf25 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -42,7 +42,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: &TyCtxt<'tcx>, it: &hir::ForeignItem, let fty = tcx.mk_fn_def(def_id, tcx.mk_substs(substs), ty::BareFnTy { unsafety: hir::Unsafety::Unsafe, abi: abi, - sig: ty::Binder(FnSig { + sig: ty::Binder::new(FnSig { inputs: inputs, output: output, variadic: false, @@ -293,7 +293,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { let fn_ty = ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, - sig: ty::Binder(FnSig { + sig: ty::Binder::new(FnSig { inputs: vec![mut_u8], output: ty::FnOutput::FnConverging(tcx.mk_nil()), variadic: false, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index b98f1884f01ce..29dd86bd8c6ea 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -108,7 +108,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { let def_id = pick.item.def_id(); let method_ty = pick.item.as_opt_method().unwrap(); let fty = self.tcx().mk_fn_def(def_id, all_substs, ty::BareFnTy { - sig: ty::Binder(method_sig), + sig: ty::Binder::new(method_sig), unsafety: method_ty.fty.unsafety, abi: method_ty.fty.abi.clone(), }); @@ -463,7 +463,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { _ => return, }; - match sig.0.inputs[0].sty { + match sig.skip_binder().inputs[0].sty { ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 31d95af4fbb9c..d1dbe189303ed 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -236,7 +236,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let transformed_self_ty = fn_sig.inputs[0]; let def_id = method_item.def_id(); let fty = tcx.mk_fn_def(def_id, trait_ref.substs, ty::BareFnTy { - sig: ty::Binder(fn_sig), + sig: ty::Binder::new(fn_sig), unsafety: method_ty.fty.unsafety, abi: method_ty.fty.abi.clone(), }); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 0ffbbfea84ef0..3da446dc3f9ad 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -479,7 +479,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { .filter_map(|predicate| { match *predicate { ty::Predicate::Trait(ref trait_predicate) => { - match trait_predicate.0.trait_ref.self_ty().sty { + match trait_predicate.skip_binder().trait_ref.self_ty().sty { ty::TyParam(ref p) if *p == param_ty => { Some(trait_predicate.to_poly_trait_ref()) } @@ -1097,7 +1097,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { if !selcx.evaluate_obligation(o) { all_true = false; if let &ty::Predicate::Trait(ref pred) = &o.predicate { - possibly_unsatisfied_predicates.push(pred.0.trait_ref); + possibly_unsatisfied_predicates.push( + pred.skip_binder().trait_ref); } } } @@ -1200,7 +1201,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { { debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", impl_ty, - method.fty.sig.0.inputs.get(0), + method.fty.sig.skip_binder().inputs.get(0), substs); assert!(!substs.has_escaping_regions()); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 45877d7099bbf..05ab77c5b742b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1165,23 +1165,24 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { { let def = self.tcx().type_parameter_def(node_id); let r = self.inh.infcx.parameter_environment - .caller_bounds - .iter() - .filter_map(|predicate| { - match *predicate { - ty::Predicate::Trait(ref data) => { - if data.0.self_ty().is_param(def.space, def.index) { - Some(data.to_poly_trait_ref()) - } else { - None - } - } - _ => { + .caller_bounds + .iter() + .filter_map(|predicate| { + match *predicate { + ty::Predicate::Trait(ref data) => { + let self_ty = data.skip_binder().self_ty(); + if self_ty.is_param(def.space, def.index) { + Some(data.to_poly_trait_ref()) + } else { None } } - }) - .collect(); + _ => { + None + } + } + }) + .collect(); Ok(r) } @@ -2367,19 +2368,22 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, match method_fn_ty.sty { ty::TyFnDef(_, _, ref fty) => { // HACK(eddyb) ignore self in the definition (see above). - let expected_arg_tys = expected_types_for_fn_args(fcx, - sp, - expected, - fty.sig.0.output, - &fty.sig.0.inputs[1..]); + let fty_sig = + fcx.tcx().no_late_bound_regions(&fty.sig).unwrap(); + let expected_arg_tys = + expected_types_for_fn_args(fcx, + sp, + expected, + fty_sig.output, + &fty_sig.inputs[1..]); check_argument_types(fcx, sp, - &fty.sig.0.inputs[1..], + &fty_sig.inputs[1..], &expected_arg_tys[..], args_no_rcvr, - fty.sig.0.variadic, + fty_sig.variadic, tuple_arguments); - fty.sig.0.output + fty_sig.output } _ => { span_bug!(callee_expr.span, "method without bare fn type"); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 1b21e6ce9ebe3..0c128a45548db 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -411,7 +411,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { }; let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty); let rcvr_ty = fcx.tcx().liberate_late_bound_regions(free_id_outlive, - &ty::Binder(rcvr_ty)); + &ty::Binder::new(rcvr_ty)); debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2e1a684684375..cd7998ae26515 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -931,7 +931,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, tcx.mk_fn_def(def_id, substs, ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: abi::Abi::Rust, - sig: ty::Binder(ty::FnSig { + sig: ty::Binder::new(ty::FnSig { inputs: inputs, output: ty::FnConverging(scheme.ty), variadic: false @@ -1775,7 +1775,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, }); for bound in ¶m.bounds { let bound_region = ast_region_to_region(ccx.tcx, bound); - let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); + let outlives = ty::Binder::new(ty::OutlivesPredicate(region, bound_region)); result.predicates.push(space, outlives.to_predicate()); } } @@ -1809,7 +1809,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, &hir::TyParamBound::RegionTyParamBound(ref lifetime) => { let region = ast_region_to_region(tcx, lifetime); - let pred = ty::Binder(ty::OutlivesPredicate(ty, region)); + let pred = ty::Binder::new(ty::OutlivesPredicate(ty, region)); result.predicates.push(space, ty::Predicate::TypeOutlives(pred)) } } @@ -1820,7 +1820,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let r1 = ast_region_to_region(tcx, ®ion_pred.lifetime); for bound in ®ion_pred.bounds { let r2 = ast_region_to_region(tcx, bound); - let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); + let pred = ty::Binder::new(ty::OutlivesPredicate(r1, r2)); result.predicates.push(space, ty::Predicate::RegionOutlives(pred)) } } @@ -2064,7 +2064,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>, } hir::RegionTyParamBound(ref lifetime) => { let region = ast_region_to_region(astconv.tcx(), lifetime); - let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region)); + let pred = ty::Binder::new(ty::OutlivesPredicate(param_ty, region)); vec![ty::Predicate::TypeOutlives(pred)] } hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => { @@ -2185,9 +2185,9 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( let t_fn = ccx.tcx.mk_fn_def(id, substs, ty::BareFnTy { abi: abi, unsafety: hir::Unsafety::Unsafe, - sig: ty::Binder(ty::FnSig {inputs: input_tys, - output: output, - variadic: decl.variadic}), + sig: ty::Binder::new(ty::FnSig {inputs: input_tys, + output: output, + variadic: decl.variadic}), }); ty::TypeScheme { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 7f27d10ce1ec3..a812c5ccf0ede 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -242,7 +242,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, let se_ty = tcx.mk_fn_def(main_def_id, substs, ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, - sig: ty::Binder(ty::FnSig { + sig: ty::Binder::new(ty::FnSig { inputs: Vec::new(), output: ty::FnConverging(tcx.mk_nil()), variadic: false @@ -290,7 +290,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, let se_ty = tcx.mk_fn_def(start_def_id, substs, ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, - sig: ty::Binder(ty::FnSig { + sig: ty::Binder::new(ty::FnSig { inputs: vec!( tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)) diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 3b03a713a5b93..54185f2d3fb59 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -404,12 +404,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_region(generics, data.bounds.region_bound, contra); // Ignore the SelfSpace, it is erased. - self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); + self.add_constraints_from_trait_ref(generics, + *poly_trait_ref.skip_binder(), + variance); let projections = data.projection_bounds_with_self_ty(self.tcx(), self.tcx().types.err); for projection in &projections { - self.add_constraints_from_ty(generics, projection.0.ty, self.invariant); + self.add_constraints_from_ty(generics, + projection.skip_binder().ty, + self.invariant); } } @@ -487,10 +491,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { sig: &ty::PolyFnSig<'tcx>, variance: VarianceTermPtr<'a>) { let contra = self.contravariant(variance); - for &input in &sig.0.inputs { + for &input in &sig.skip_binder().inputs { self.add_constraints_from_ty(generics, input, contra); } - if let ty::FnConverging(result_type) = sig.0.output { + if let ty::FnConverging(result_type) = sig.skip_binder().output { self.add_constraints_from_ty(generics, result_type, variance); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 673aa17ecd145..1ea4415e693a2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -106,7 +106,7 @@ impl, U> Clean> for Option { impl Clean for ty::Binder where T: Clean { fn clean(&self, cx: &DocContext) -> U { - self.0.clean(cx) + self.skip_binder().clean(cx) } } @@ -602,7 +602,8 @@ impl<'tcx> Clean<(Vec, Vec)> for ty::ExistentialBound } let mut bindings = vec![]; - for &ty::Binder(ref pb) in &self.projection_bounds { + for pb in &self.projection_bounds { + let pb = pb.skip_binder(); bindings.push(TypeBinding { name: pb.projection_ty.item_name.clean(cx), ty: pb.ty.clean(cx) @@ -1175,11 +1176,11 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { let _ = names.next(); } FnDecl { - output: Return(sig.0.output.clean(cx)), + output: Return(sig.skip_binder().output.clean(cx)), attrs: Vec::new(), - variadic: sig.0.variadic, + variadic: sig.variadic(), inputs: Arguments { - values: sig.0.inputs.iter().map(|t| { + values: sig.skip_binder().inputs.iter().map(|t| { Argument { type_: t.clean(cx), id: 0, @@ -1337,14 +1338,14 @@ impl<'tcx> Clean for ty::Method<'tcx> { ty::ExplicitSelfCategory::Static => (hir::SelfStatic.clean(cx), self.fty.sig.clone()), s => { - let sig = ty::Binder(ty::FnSig { - inputs: self.fty.sig.0.inputs[1..].to_vec(), - ..self.fty.sig.0.clone() + let sig = ty::Binder::new(ty::FnSig { + inputs: self.fty.sig.skip_binder().inputs[1..].to_vec(), + ..self.fty.sig.skip_binder().clone() }); let s = match s { ty::ExplicitSelfCategory::ByValue => SelfValue, ty::ExplicitSelfCategory::ByReference(..) => { - match self.fty.sig.0.inputs[0].sty { + match self.fty.sig.skip_binder().inputs[0].sty { ty::TyRef(r, mt) => { SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx)) } @@ -1352,7 +1353,7 @@ impl<'tcx> Clean for ty::Method<'tcx> { } } ty::ExplicitSelfCategory::ByBox => { - SelfExplicit(self.fty.sig.0.inputs[0].clean(cx)) + SelfExplicit(self.fty.sig.skip_binder().inputs[0].clean(cx)) } ty::ExplicitSelfCategory::Static => unreachable!(), }; From c909c737ee5756dcb12e2e0935c1643227fc2176 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 8 Apr 2016 15:43:26 -0400 Subject: [PATCH 2/3] eagerly process builtin bound obligations This avoids normalizing for structural types, which kind of gives us a poor man's lazy normalization. It's enough to fix issue #31299, anyway, though you can still get false failures if you try hard enough. Fixes #31299. --- src/librustc/traits/select.rs | 176 +++++++++++++++++++++++++------ src/librustc/ty/sty.rs | 4 + src/test/run-pass/issue-31299.rs | 36 +++++++ 3 files changed, 184 insertions(+), 32 deletions(-) create mode 100644 src/test/run-pass/issue-31299.rs diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6b5a1868913e0..69811fbe64144 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1688,13 +1688,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bound: ty::BuiltinBound, obligation: &TraitObligation<'tcx>) -> Result,SelectionError<'tcx>> + { + let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); + self.builtin_bound_for_self_ty(bound, self_ty) + } + + fn builtin_bound_for_self_ty(&mut self, + bound: ty::BuiltinBound, + self_ty: Ty<'tcx>) + -> Result, + SelectionError<'tcx>> { // Note: these tests operate on types that may contain bound // regions. To be proper, we ought to skolemize here, but we // forego the skolemization and defer it until the // confirmation step. - let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); return match self_ty.sty { ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | @@ -1706,14 +1715,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TyFnPtr(_) | ty::TyChar => { // safe for everything - ok_if(Vec::new()) + self.builtin_bound_ok_if(bound, vec![]) } ty::TyBox(_) => { // Box match bound { ty::BoundCopy => Err(Unimplemented), - ty::BoundSized => ok_if(Vec::new()), + ty::BoundSized => self.builtin_bound_ok_if(bound, vec![]), ty::BoundSync | ty::BoundSend => { bug!("Send/Sync shouldn't occur in builtin_bounds()"); @@ -1723,7 +1732,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TyRawPtr(..) => { // *const T, *mut T match bound { - ty::BoundCopy | ty::BoundSized => ok_if(Vec::new()), + ty::BoundCopy | ty::BoundSized => self.builtin_bound_ok_if(bound, vec![]), ty::BoundSync | ty::BoundSend => { bug!("Send/Sync shouldn't occur in builtin_bounds()"); @@ -1736,17 +1745,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::BoundSized => Err(Unimplemented), ty::BoundCopy => { if data.bounds.builtin_bounds.contains(&bound) { - ok_if(Vec::new()) + self.builtin_bound_ok_if(bound, vec![]) } else { // Recursively check all supertraits to find out if any further // bounds are required and thus we must fulfill. let principal = data.principal_trait_ref_with_self_ty(self.tcx(), self.tcx().types.err); - let copy_def_id = obligation.predicate.def_id(); + let copy_def_id = self.tcx().lang_items.copy_trait() + .unwrap(); for tr in util::supertraits(self.tcx(), principal) { if tr.def_id() == copy_def_id { - return ok_if(Vec::new()) + return self.builtin_bound_ok_if(bound, vec![]) } } @@ -1768,11 +1778,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { hir::MutMutable => Err(Unimplemented), // &T is always copyable - hir::MutImmutable => ok_if(Vec::new()), + hir::MutImmutable => self.builtin_bound_ok_if(bound, vec![]), } } - ty::BoundSized => ok_if(Vec::new()), + ty::BoundSized => self.builtin_bound_ok_if(bound, vec![]), ty::BoundSync | ty::BoundSend => { bug!("Send/Sync shouldn't occur in builtin_bounds()"); @@ -1783,8 +1793,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TyArray(element_ty, _) => { // [T; n] match bound { - ty::BoundCopy => ok_if(vec![element_ty]), - ty::BoundSized => ok_if(Vec::new()), + ty::BoundCopy => self.builtin_bound_ok_if(bound, vec![element_ty]), + ty::BoundSized => self.builtin_bound_ok_if(bound, vec![]), ty::BoundSync | ty::BoundSend => { bug!("Send/Sync shouldn't occur in builtin_bounds()"); } @@ -1802,7 +1812,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - ty::TyTuple(ref tys) => ok_if(tys.clone()), + ty::TyTuple(ref tys) => self.builtin_bound_ok_if(bound, tys.clone()), ty::TyClosure(_, ref substs) => { // FIXME -- This case is tricky. In the case of by-ref @@ -1826,17 +1836,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // unsized, so the closure struct as a whole must be // Sized. if bound == ty::BoundSized { - return ok_if(Vec::new()); + return self.builtin_bound_ok_if(bound, vec![]); } - ok_if(substs.upvar_tys.clone()) + self.builtin_bound_ok_if(bound, substs.upvar_tys.clone()) } ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { let types: Vec = def.all_fields().map(|f| { f.ty(self.tcx(), substs) }).collect(); - nominal(bound, types) + self.builtin_bound_nominal(bound, types) } ty::TyProjection(_) | ty::TyParam(_) => { @@ -1855,7 +1865,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(AmbiguousBuiltin) } - ty::TyError => ok_if(Vec::new()), + ty::TyError => self.builtin_bound_ok_if(bound, vec![]), ty::TyInfer(ty::FreshTy(_)) | ty::TyInfer(ty::FreshIntTy(_)) @@ -1864,27 +1874,129 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self_ty); } }; + } - fn ok_if<'tcx>(v: Vec>) - -> Result, SelectionError<'tcx>> { - Ok(If(ty::Binder::new(v))) + fn builtin_bound_ok_if(&mut self, bound: ty::BuiltinBound, v: Vec>) + -> Result, + SelectionError<'tcx>> + { + match bound { + ty::BoundCopy | ty::BoundSized => { /* see code below */ } + _ => { + // these really ought not to be builtin, but just auto + // trait; we can't apply the logic below because there + // are impls (negative ones) for *mut T etc. + return Ok(If(ty::Binder::new(v))); + } } - fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound, - types: Vec>) - -> Result, SelectionError<'tcx>> - { - // First check for markers and other nonsense. - match bound { - // Fallback to whatever user-defined impls exist in this case. - ty::BoundCopy => Ok(ParameterBuiltin), + // FIXME(lazy normalization): It turns out that lazy + // normalization is actually more expressive than the eager + // normalization we do now. In particular, if you have structs + // like this (from #31299): + // + // ``` + // trait Front { + // type Back; + // } + // + // impl Front for Vec { + // type Back = Vec; + // } + // + // struct PtrBack(*mut T::Back); + // + // struct M(PtrBack>); + // ``` + // + // If we try to validate that `M: Sized`, and you are doing + // eager normalization, you will wind up with a new obligation + // `PtrBack>: Sized`, and then from there `*mut + // as Front>::Back: Sized`, which we will then try to + // normalize. This requires us normalizing `*mut as + // Front>::Back`, and hence ` as Front>::Back`. But to + // normalize, we must apply the impl of `Front`, and that impl + // requires that `M: Sized`. So now we have a cycle, leading + // to overflow. + // + // But with lazy normalization, we could defer doing that + // normalization. Then we would see the inference rule: + // + // ------------- + // *mut T: Sized + // + // which, notably, has no condition on `T`, and hence we never + // need to normalize at all. + // + // In order to fix #31299, this code does a little bit of + // "pre-expansion" to sidestep this deficit for eager + // normalization. The idea is that we take the types we would + // otherwise convert into new obligations and try to eagerly + // expand them. So if we see `M: Sized`, we will expand to + // `PtrBack>: Sized` as before. But then + // `PtrBack>: Sized` will expand to `*mut as + // Front>::Back`. This is where we go differently: instead of + // generating an obligation from that, we will immediately + // recurse and observe that `*mut X: Sized` for any `X`, so we + // never wind up normalizing. + // + // We only recurse in the case of a structural type, since + // that ensures that we can never loop. + let v = + v.iter() + .flat_map(|&ty| { + match ty.sty { + ty::TyInfer(ty::IntVar(..)) | + ty::TyInfer(ty::FloatVar(..)) | + ty::TyUint(..) | + ty::TyInt(..) | + ty::TyBool | + ty::TyFloat(..) | + ty::TyFnDef(..) | + ty::TyFnPtr(..) | + ty::TyChar | + ty::TyBox(..) | + ty::TyRawPtr(..) | + ty::TyRef(..) | + ty::TyArray(..) | + ty::TyStr | + ty::TySlice(..) | + ty::TyTuple(..) => + match self.builtin_bound_for_self_ty(bound, ty) { + Ok(If(subtypes)) => subtypes.into_skip_binder(), + _ => vec![ty], + }, + + ty::TyTrait(..) | + ty::TyClosure(..) | + ty::TyStruct(..) | + ty::TyEnum(..) | + ty::TyProjection(..) | + ty::TyParam(..) | + ty::TyInfer(..) | + ty::TyError => + vec![ty], + } + }) + .collect(); + Ok(If(ty::Binder::new(v))) + } + + fn builtin_bound_nominal(&mut self, + bound: ty::BuiltinBound, + types: Vec>) + -> Result, SelectionError<'tcx>> + { + // First check for markers and other nonsense. + match bound { + // Fallback to whatever user-defined impls exist in this case. + ty::BoundCopy => Ok(ParameterBuiltin), - // Sized if all the component types are sized. - ty::BoundSized => ok_if(types), + // Sized if all the component types are sized. + ty::BoundSized => self.builtin_bound_ok_if(bound, types), - // Shouldn't be coming through here. - ty::BoundSend | ty::BoundSync => bug!(), - } + // Shouldn't be coming through here. + ty::BoundSend | ty::BoundSync => bug!(), } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 1a338eb976bad..34ad269de4807 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -412,6 +412,10 @@ impl Binder { &self.bound } + pub fn into_skip_binder(self) -> T { + self.bound + } + pub fn skip_binder_mut(&mut self) -> &mut T { &mut self.bound } diff --git a/src/test/run-pass/issue-31299.rs b/src/test/run-pass/issue-31299.rs new file mode 100644 index 0000000000000..28977017ec4e2 --- /dev/null +++ b/src/test/run-pass/issue-31299.rs @@ -0,0 +1,36 @@ +// 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. + +// Regression test for #31299. This was generating an overflow error +// because of eager normalization: +// +// proving `M: Sized` requires +// - proving `PtrBack>: Sized` requis +// - normalizing `*mut as Front>::Back>: Sized` requires +// - proving `Vec: Front` requires +// - `M: Sized` <-- cycle! +// +// If we skip the normalization step, though, everything goes fine. + +trait Front { + type Back; +} + +impl Front for Vec { + type Back = Vec; +} + +struct PtrBack(*mut T::Back); + +struct M(PtrBack>); + +fn main() { + println!("{}", std::mem::size_of::()); +} From 1d8b408609a5efe55d1be3e6f7a950f46c01986a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 8 Apr 2016 16:18:09 -0400 Subject: [PATCH 3/3] struct S is Sized if last field is Sized Leverage the fact that wfcheck requires that all struct fields are of sized type except the last, so we don't need to check that again. --- src/librustc/traits/select.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 69811fbe64144..fb25b64383504 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1984,7 +1984,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn builtin_bound_nominal(&mut self, bound: ty::BuiltinBound, - types: Vec>) + mut types: Vec>) -> Result, SelectionError<'tcx>> { // First check for markers and other nonsense. @@ -1992,8 +1992,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Fallback to whatever user-defined impls exist in this case. ty::BoundCopy => Ok(ParameterBuiltin), - // Sized if all the component types are sized. - ty::BoundSized => self.builtin_bound_ok_if(bound, types), + // Sized if all the component types are sized. The WF + // rules require that all the field types except the last + // one (if any) are sized. If there are no fields, then it + // is also sized. + ty::BoundSized => { + let last_ty = types.pop(); // just keep the last type + types.clear(); + types.extend(last_ty); + self.builtin_bound_ok_if(bound, types) + } // Shouldn't be coming through here. ty::BoundSend | ty::BoundSync => bug!(),