diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index a4aa685c0902..e57c16b5a0fb 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -2501,7 +2501,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let obligation_def_id = obligation.predicate.def_id(); let mut upcast_trait_refs = util::upcast(self.tcx(), obj_trait_ref, obligation_def_id); - // retain only those upcast versions that match the trait-ref we are looking for + // Retain only those upcast versions that match the trait-ref + // we are looking for. In particular, we know that all of + // `upcast_trait_refs` apply to the correct trait, but + // possibly with incorrect type parameters. For example, we + // may be trying to upcast `Foo` to `Bar`, but `Foo` is + // declared as `trait Foo : Bar`. upcast_trait_refs.retain(|upcast_trait_ref| { let upcast_trait_ref = upcast_trait_ref.clone(); self.infcx.probe(|_| self.match_poly_trait_ref(obligation, upcast_trait_ref)).is_ok() diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index d6dc57c5def4..4527985302ae 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -110,8 +110,8 @@ pub fn elaborate_predicates<'cx, 'tcx>( } impl<'cx, 'tcx> Elaborator<'cx, 'tcx> { - pub fn filter_to_traits(self) -> JustTraits> { - JustTraits::new(self) + pub fn filter_to_traits(self) -> FilterToTraits> { + FilterToTraits::new(self) } fn push(&mut self, predicate: &ty::Predicate<'tcx>) { @@ -193,7 +193,7 @@ impl<'cx, 'tcx> Iterator for Elaborator<'cx, 'tcx> { // Supertrait iterator /////////////////////////////////////////////////////////////////////////// -pub type Supertraits<'cx, 'tcx> = JustTraits>; +pub type Supertraits<'cx, 'tcx> = FilterToTraits>; pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) @@ -215,17 +215,17 @@ pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, /// A filter around an iterator of predicates that makes it yield up /// just trait references. -pub struct JustTraits { +pub struct FilterToTraits { base_iterator: I } -impl JustTraits { - fn new(base: I) -> JustTraits { - JustTraits { base_iterator: base } +impl FilterToTraits { + fn new(base: I) -> FilterToTraits { + FilterToTraits { base_iterator: base } } } -impl<'tcx,I:Iterator>> Iterator for JustTraits { +impl<'tcx,I:Iterator>> Iterator for FilterToTraits { type Item = ty::PolyTraitRef<'tcx>; fn next(&mut self) -> Option> { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index dfdb4002be24..add829074c4f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1510,7 +1510,7 @@ impl Binder { /// /// Some examples where `skip_binder` is reasonable: /// - extracting the def-id from a PolyTraitRef; - /// - compariing the self type of a PolyTraitRef to see if it is equal to + /// - 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 diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 7b4e3956cbd2..0c82d681eed1 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -300,7 +300,9 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, .position(|item| item.def_id() == method_id) .unwrap(); let (llfn, ty) = - trans_object_shim(ccx, data.object_ty, data.upcast_trait_ref.clone(), + trans_object_shim(ccx, + data.object_ty, + data.upcast_trait_ref.clone(), method_offset_in_trait); immediate_rvalue(llfn, ty) } @@ -387,8 +389,10 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Callee { bcx: bcx, data: Fn(llfn) } } traits::VtableObject(ref data) => { - let (llfn, _) = trans_object_shim(bcx.ccx(), data.object_ty, - data.upcast_trait_ref.clone(), n_method); + let (llfn, _) = trans_object_shim(bcx.ccx(), + data.object_ty, + data.upcast_trait_ref.clone(), + n_method); Callee { bcx: bcx, data: Fn(llfn) } } traits::VtableBuiltin(..) | diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 8f9ede32ae4d..12bcf5cf5ada 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1251,6 +1251,11 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, debug!("ensure_super_predicates_step(trait_def_id={})", trait_def_id.repr(tcx)); if trait_def_id.krate != ast::LOCAL_CRATE { + // If this trait comes from an external crate, then all of the + // supertraits it may depend on also must come from external + // crates, and hence all of them already have their + // super-predicates "converted" (and available from crate + // meta-data), so there is no need to transitively test them. return Vec::new(); } @@ -2111,8 +2116,11 @@ fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>, param_bounds } -/// Converts a specific TyParamBound from the AST into the -/// appropriate poly-trait-reference. +/// Converts a specific TyParamBound from the AST into a set of +/// predicates that apply to the self-type. A vector is returned +/// because this can be anywhere from 0 predicates (`T:?Sized` adds no +/// predicates) to 1 (`T:Foo`) to many (`T:Bar` adds `T:Bar` +/// and `::X == i32`). fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>, param_ty: Ty<'tcx>, bound: &ast::TyParamBound)