diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 05fbe07cac2a4..4040c0166d859 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1050,10 +1050,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { if !self.in_body { // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE. // The traits' privacy in bodies is already checked as a part of trait object types. - let (principal, bounds) = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref); - if self.visit_trait(*principal.skip_binder()) { - return; + let bounds = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref); + + for (trait_predicate, _) in bounds.trait_bounds { + if self.visit_trait(*trait_predicate.skip_binder()) { + return; + } } + for (poly_predicate, _) in bounds.projection_bounds { let tcx = self.tcx; if self.visit(poly_predicate.skip_binder().ty) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 9857dee05835a..64c0011a7b39c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -775,11 +775,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// The given trait-ref must actually be a trait. pub(super) fn instantiate_poly_trait_ref_inner(&self, trait_ref: &hir::TraitRef, + span: Span, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, - ) -> (ty::PolyTraitRef<'tcx>, Option>) - { + ) -> Option> { let trait_def_id = trait_ref.trait_def_id(); debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); @@ -794,6 +794,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); + bounds.trait_bounds.push((poly_trait_ref, span)); + let mut dup_bindings = FxHashMap::default(); for binding in &assoc_bindings { // Specify type to assert that error was already reported in `Err` case. @@ -811,7 +813,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}", trait_ref, bounds, poly_trait_ref); - (poly_trait_ref, potential_assoc_types) + potential_assoc_types } /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct @@ -836,10 +838,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn instantiate_poly_trait_ref(&self, poly_trait_ref: &hir::PolyTraitRef, self_ty: Ty<'tcx>, - bounds: &mut Bounds<'tcx> - ) -> (ty::PolyTraitRef<'tcx>, Option>) - { - self.instantiate_poly_trait_ref_inner(&poly_trait_ref.trait_ref, self_ty, bounds, false) + bounds: &mut Bounds<'tcx>, + ) -> Option> { + self.instantiate_poly_trait_ref_inner( + &poly_trait_ref.trait_ref, + poly_trait_ref.span, + self_ty, + bounds, + false, + ) } fn ast_path_to_mono_trait_ref(&self, @@ -983,12 +990,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } for bound in trait_bounds { - let (poly_trait_ref, _) = self.instantiate_poly_trait_ref( + let _ = self.instantiate_poly_trait_ref( bound, param_ty, bounds, ); - bounds.trait_bounds.push((poly_trait_ref, bound.span)) } bounds.region_bounds.extend(region_bounds @@ -1172,11 +1178,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs); - self.add_bounds( - param_ty, - ast_bounds, - bounds, - ); + self.add_bounds(param_ty, ast_bounds, bounds); } } Ok(()) @@ -1216,25 +1218,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut bounds = Bounds::default(); let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; - // FIXME: we want to avoid collecting into a `Vec` here, but simply cloning the iterator is - // not straightforward due to the borrow checker. - let bound_trait_refs: Vec<_> = trait_bounds - .iter() - .rev() - .map(|trait_bound| { - let (trait_ref, cur_potential_assoc_types) = self.instantiate_poly_trait_ref( - trait_bound, - dummy_self, - &mut bounds, - ); - potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); - (trait_ref, trait_bound.span) - }) - .collect(); + for trait_bound in trait_bounds.iter().rev() { + let cur_potential_assoc_types = self.instantiate_poly_trait_ref( + trait_bound, + dummy_self, + &mut bounds, + ); + potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); + } // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. - let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.iter().cloned()); + let expanded_traits = + traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned()); let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { @@ -1276,7 +1272,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Use a `BTreeSet` to keep output in a more consistent order. let mut associated_types = BTreeSet::default(); - let regular_traits_refs = bound_trait_refs + let regular_traits_refs = bounds.trait_bounds .into_iter() .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())) .map(|(trait_ref, _)| trait_ref); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 44f9b82f8cd6e..4056d6f974c5d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -49,8 +49,6 @@ use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; use errors::{Applicability, DiagnosticId}; -use std::iter; - struct OnlySelfBounds(bool); /////////////////////////////////////////////////////////////////////////// @@ -2191,15 +2189,12 @@ fn explicit_predicates_of( match bound { &hir::GenericBound::Trait(ref poly_trait_ref, _) => { let mut bounds = Bounds::default(); - - let (trait_ref, _) = AstConv::instantiate_poly_trait_ref( + let _ = AstConv::instantiate_poly_trait_ref( &icx, poly_trait_ref, ty, &mut bounds, ); - - predicates.push((trait_ref.to_predicate(), poly_trait_ref.span)); predicates.extend(bounds.predicates(tcx, ty)); } @@ -2301,10 +2296,13 @@ fn predicates_from_bound<'tcx>( match *bound { hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => { let mut bounds = Bounds::default(); - let (pred, _) = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut bounds); - iter::once((pred.to_predicate(), tr.span)) - .chain(bounds.predicates(astconv.tcx(), param_ty)) - .collect() + let _ = astconv.instantiate_poly_trait_ref( + tr, + param_ty, + &mut bounds, + false, + ); + bounds.predicates(astconv.tcx(), param_ty) } hir::GenericBound::Outlives(ref lifetime) => { let region = astconv.ast_region_to_region(lifetime, None); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index a34b137aca971..9d9a9d9b559e4 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -108,7 +108,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::query::Providers; use rustc::util; -use syntax_pos::Span; +use syntax_pos::{DUMMY_SP, Span}; use util::common::time; use std::iter; @@ -375,7 +375,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty) -> Ty<'tcx> { pub fn hir_trait_to_predicates<'tcx>( tcx: TyCtxt<'tcx>, hir_trait: &hir::TraitRef, -) -> (ty::PolyTraitRef<'tcx>, Bounds<'tcx>) { +) -> Bounds<'tcx> { // In case there are any projections, etc., find the "environment" // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. @@ -383,11 +383,11 @@ pub fn hir_trait_to_predicates<'tcx>( let env_def_id = tcx.hir().local_def_id(env_hir_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id); let mut bounds = Bounds::default(); - let (principal, _) = AstConv::instantiate_poly_trait_ref_inner( - &item_cx, hir_trait, tcx.types.err, &mut bounds, true + let _ = AstConv::instantiate_poly_trait_ref_inner( + &item_cx, hir_trait, DUMMY_SP, tcx.types.err, &mut bounds, true ); - (principal, bounds) + bounds } __build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }