From 8f9ca24f55cc74159d00c4691c464ced5d51a669 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 17 Jun 2019 23:40:24 +0100 Subject: [PATCH 1/8] A few cosmetic improvements. --- src/librustc/hir/mod.rs | 2 +- src/librustc/ty/mod.rs | 14 +++++++------- src/librustc/ty/sty.rs | 13 +++++++------ src/librustc_codegen_llvm/debuginfo/metadata.rs | 14 +++++++------- src/librustc_privacy/lib.rs | 5 +++-- src/librustc_typeck/astconv.rs | 8 ++++---- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/collect.rs | 17 ++++++++--------- 8 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index b8d8394a02cee..3d049fe4ccdad 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2234,7 +2234,7 @@ pub enum UseKind { #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct TraitRef { pub path: P, - // Don't hash the ref_id. It is tracked via the thing it is used to access + // Don't hash the `ref_id`. It is tracked via the thing it is used to access. #[stable_hasher(ignore)] pub hir_ref_id: HirId, } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8e170578227c0..c6aadc598b7e1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -904,7 +904,7 @@ pub struct Generics { pub parent_count: usize, pub params: Vec, - /// Reverse map to the `index` field of each `GenericParamDef` + /// Reverse map to the `index` field of each `GenericParamDef`. #[stable_hasher(ignore)] pub param_def_id_to_index: FxHashMap, @@ -1252,7 +1252,7 @@ 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. + // Ok to skip binder since trait `DefId` does not care about regions. self.skip_binder().def_id() } } @@ -1319,7 +1319,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { /// Note that this is not the `DefId` of the `TraitRef` containing this /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. pub fn projection_def_id(&self) -> DefId { - // Ok to skip binder since trait def-ID does not care about regions. + // Ok to skip binder since trait `DefId` does not care about regions. self.skip_binder().projection_ty.item_def_id } } @@ -1646,10 +1646,10 @@ pub type PlaceholderConst = Placeholder; /// particular point. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] pub struct ParamEnv<'tcx> { - /// Obligations that the caller must satisfy. This is basically + /// `Obligation`s that the caller must satisfy. This is basically /// the set of bounds on the in-scope type parameters, translated - /// into Obligations, and elaborated and normalized. - pub caller_bounds: &'tcx List>, + /// into `Obligation`s, and elaborated and normalized. + pub caller_bounds: &'tcx List<(ty::Predicate<'tcx>, Span)>, /// Typically, this is `Reveal::UserFacing`, but during codegen we /// want `Reveal::All` -- note that this is always paired with an @@ -2796,7 +2796,7 @@ impl<'tcx> TyCtxt<'tcx> { _ => false, } } else { - match self.def_kind(def_id).expect("no def for def-id") { + match self.def_kind(def_id).expect("no def for `DefId`") { DefKind::AssocConst | DefKind::Method | DefKind::AssocTy => true, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 2b14558de6916..820e9990b92c7 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -646,7 +646,7 @@ impl<'tcx> List> { /// /// A Rust trait object type consists (in addition to a lifetime bound) /// of a set of trait bounds, which are separated into any number - /// of auto-trait bounds, and at most 1 non-auto-trait bound. The + /// of auto-trait bounds, and at most one non-auto-trait bound. The /// non-auto-trait bound is called the "principal" of the trait /// object. /// @@ -680,7 +680,8 @@ impl<'tcx> List> { #[inline] pub fn projection_bounds<'a>(&'a self) -> - impl Iterator> + 'a { + impl Iterator> + 'a + { self.iter().filter_map(|predicate| { match *predicate { ExistentialPredicate::Projection(p) => Some(p), @@ -690,7 +691,7 @@ impl<'tcx> List> { } #[inline] - pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { + pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { self.iter().filter_map(|predicate| { match *predicate { ExistentialPredicate::AutoTrait(d) => Some(d), @@ -711,17 +712,17 @@ impl<'tcx> Binder<&'tcx List>> { #[inline] pub fn projection_bounds<'a>(&'a self) -> - impl Iterator> + 'a { + impl Iterator> + 'a { self.skip_binder().projection_bounds().map(Binder::bind) } #[inline] - pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { + pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { self.skip_binder().auto_traits() } pub fn iter<'a>(&'a self) - -> impl DoubleEndedIterator>> + 'tcx { + -> impl DoubleEndedIterator>> + 'tcx { self.skip_binder().iter().cloned().map(Binder::bind) } } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index f0bdb0018efe7..f52ad33b3d037 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -450,11 +450,11 @@ fn subroutine_type_metadata( false); } -// FIXME(1563) This is all a bit of a hack because 'trait pointer' is an ill- -// defined concept. For the case of an actual trait pointer (i.e., Box, -// &Trait), trait_object_type should be the whole thing (e.g, Box) and -// trait_type should be the actual trait (e.g., Trait). Where the trait is part -// of a DST struct, there is no trait_object_type and the results of this +// FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill- +// defined concept. For the case of an actual trait pointer (i.e., `Box`, +// `&Trait`), `trait_object_type` should be the whole thing (e.g, `Box`) and +// `trait_type` should be the actual trait (e.g., `Trait`). Where the trait is part +// of a DST struct, there is no `trait_object_type` and the results of this // function will be a little bit weird. fn trait_pointer_metadata( cx: &CodegenCx<'ll, 'tcx>, @@ -464,13 +464,13 @@ fn trait_pointer_metadata( ) -> &'ll DIType { // The implementation provided here is a stub. It makes sure that the trait // type is assigned the correct name, size, namespace, and source location. - // But it does not describe the trait's methods. + // However, it does not describe the trait's methods. let containing_scope = match trait_type.sty { ty::Dynamic(ref data, ..) => data.principal_def_id().map(|did| get_namespace_for_item(cx, did)), _ => { - bug!("debuginfo: Unexpected trait-object type in \ + bug!("debuginfo: unexpected trait-object type in \ trait_pointer_metadata(): {:?}", trait_type); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 4800bb9365cb7..05fbe07cac2a4 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1056,8 +1056,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } for (poly_predicate, _) in bounds.projection_bounds { let tcx = self.tcx; - if self.visit(poly_predicate.skip_binder().ty) || - self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) { + if self.visit(poly_predicate.skip_binder().ty) + || self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) + { return; } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e8e0dd8425bab..9857dee05835a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1515,7 +1515,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assoc_name: ast::Ident, span: Span) -> Result, ErrorReported> - where I: Iterator> + where I: Iterator> { let bound = match bounds.next() { Some(bound) => bound, @@ -1524,8 +1524,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "associated type `{}` not found for `{}`", assoc_name, ty_param_name) - .span_label(span, format!("associated type `{}` not found", assoc_name)) - .emit(); + .span_label(span, format!("associated type `{}` not found", assoc_name)) + .emit(); return Err(ErrorReported); } }; @@ -1544,7 +1544,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item.kind == ty::AssocKind::Type && self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id()) }) - .and_then(|item| self.tcx().hir().span_if_local(item.def_id)); + .and_then(|item| self.tcx().hir().span_if_local(item.def_id)); if let Some(span) = bound_span { err.span_label(span, format!("ambiguous `{}` from `{}`", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e8ff83e7d2b1c..08033b46b8004 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2030,7 +2030,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: & impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx - } + } fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> &'tcx ty::GenericPredicates<'tcx> diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a14040fe59a4e..44f9b82f8cd6e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -226,7 +226,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { self.tcx().mk_projection(item_def_id, trait_ref.substs) } else { - // no late-bound regions, we can just ignore the binder + // There are no late-bound regions; we can just ignore the binder. span_err!( self.tcx().sess, span, @@ -239,17 +239,16 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - // types in item signatures are not normalized, to avoid undue - // dependencies. + // Types in item signatures are not normalized to avoid undue dependencies. ty } fn set_tainted_by_errors(&self) { - // no obvious place to track this, so just let it go + // There's no obvious place to track this, so just let it go. } fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { - // no place to record types from signatures? + // There's no place to record types from signatures? } } @@ -260,8 +259,8 @@ fn type_param_predicates( use rustc::hir::*; // In the AST, bounds can derive from two places. Either - // written inline like `` or in a where clause like - // `where T : Foo`. + // written inline like `` or in a where-clause like + // `where T: Foo`. let param_id = tcx.hir().as_local_hir_id(def_id).unwrap(); let param_owner = tcx.hir().ty_param_owner(param_id); @@ -334,7 +333,7 @@ fn type_param_predicates( impl ItemCtxt<'tcx> { /// Finds bounds from `hir::Generics`. This requires scanning through the /// AST. We do this to avoid having to convert *all* the bounds, which - /// would create artificial cycles. Instead we can only convert the + /// would create artificial cycles. Instead, we can only convert the /// bounds for a type parameter `X` if `X::Foo` is used. fn type_parameter_bounds_in_generics( &self, @@ -2292,7 +2291,7 @@ fn explicit_predicates_of( /// Converts a specific `GenericBound` from the AST into a set of /// predicates that apply to the self type. A vector is returned /// because this can be anywhere from zero predicates (`T: ?Sized` adds no -/// predicates) to one (`T: Foo`) to many (`T: Bar` adds `T: Bar` +/// predicates) to one (`T: Foo`) to many (`T: Bar` adds `T: Bar` /// and `::X == i32`). fn predicates_from_bound<'tcx>( astconv: &dyn AstConv<'tcx>, From 3d9d36b3ffa801543de65c336f02378dbe0bafa4 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 18 Jun 2019 00:02:26 +0100 Subject: [PATCH 2/8] Got rid of concept of 'principal trait' in more places in codebase. --- src/librustc_privacy/lib.rs | 10 ++++-- src/librustc_typeck/astconv.rs | 58 ++++++++++++++++------------------ src/librustc_typeck/collect.rs | 18 +++++------ src/librustc_typeck/lib.rs | 10 +++--- 4 files changed, 47 insertions(+), 49 deletions(-) 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 } From 709b9246434944f5eb7c626d43dbaf6cea00e531 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 17 Jun 2019 23:41:20 +0100 Subject: [PATCH 3/8] Ensure `type_param_predicates` fn only returns predicates for type param with given def-ID. --- src/librustc/ty/mod.rs | 2 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/collect.rs | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c6aadc598b7e1..1eda57608e75b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1649,7 +1649,7 @@ pub struct ParamEnv<'tcx> { /// `Obligation`s that the caller must satisfy. This is basically /// the set of bounds on the in-scope type parameters, translated /// into `Obligation`s, and elaborated and normalized. - pub caller_bounds: &'tcx List<(ty::Predicate<'tcx>, Span)>, + pub caller_bounds: &'tcx List>, /// Typically, this is `Reveal::UserFacing`, but during codegen we /// want `Reveal::All` -- note that this is always paired with an diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 64c0011a7b39c..881f66afc91df 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -806,7 +806,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { binding, bounds, speculative, - &mut dup_bindings + &mut dup_bindings, ); // Okay to ignore `Err` because of `ErrorReported` (see above). } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4056d6f974c5d..357dcd878f515 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -322,9 +322,16 @@ fn type_param_predicates( let icx = ItemCtxt::new(tcx, item_def_id); let mut result = (*result).clone(); result.predicates.extend(extend.into_iter()); - result.predicates - .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, - OnlySelfBounds(true))); + result.predicates.extend( + icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true)) + .into_iter() + .filter(|(predicate, _)| { + match predicate { + ty::Predicate::Trait(ref data) => data.skip_binder().self_ty().is_param(index), + _ => false, + } + }) + ); tcx.arena.alloc(result) } @@ -2300,7 +2307,6 @@ fn predicates_from_bound<'tcx>( tr, param_ty, &mut bounds, - false, ); bounds.predicates(astconv.tcx(), param_ty) } From 63a67a076f134347d9941bb46bdac9bacebe2431 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 12 Jul 2019 06:29:27 -0400 Subject: [PATCH 4/8] useful comments --- src/librustc_typeck/astconv.rs | 13 +++++++++++-- src/librustc_typeck/collect.rs | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 881f66afc91df..7d275e48a294a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -42,8 +42,17 @@ pub struct PathSeg(pub DefId, pub usize); pub trait AstConv<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; - /// Returns the set of bounds in scope for the type parameter with - /// the given id. + /// Returns predicates in scope of the form `X: Foo`, where `X` is + /// a type parameter `X` with the given id `def_id`. This is a + /// subset of the full set of predicates. + /// + /// This is used for one specific purpose: resolving "short-hand" + /// associated type references like `T::Item`. In principle, we + /// would do that by first getting the full set of predicates in + /// scope and then filtering down to find those that apply to `T`, + /// but this can lead to cycle errors. The problem is that we have + /// to do this resolution *in order to create the predicates in + /// the first place*. Hence, we have this "special pass". fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> &'tcx ty::GenericPredicates<'tcx>; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 357dcd878f515..0f0568907c646 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -250,6 +250,8 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } } +/// Returns the predicates defined on `item_def_id` of the form +/// `X: Foo` where `X` is the type parameter `def_id`. fn type_param_predicates( tcx: TyCtxt<'_>, (item_def_id, def_id): (DefId, DefId), From e0712c898e8e180a1a3e1d3497a33078197a64d4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 12 Jul 2019 06:31:42 -0400 Subject: [PATCH 5/8] useful debug --- src/librustc_typeck/astconv.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 7d275e48a294a..25e9355161bcf 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1496,7 +1496,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { let tcx = self.tcx(); + debug!( + "find_bound_for_assoc_item(ty_param_def_id={:?}, assoc_name={:?}, span={:?})", + ty_param_def_id, + assoc_name, + span, + ); + let predicates = &self.get_type_parameter_bounds(span, ty_param_def_id).predicates; + + debug!("find_bound_for_assoc_item: predicates={:#?}", predicates); + let bounds = predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()); // Check that there is exactly one way to find an associated type with the @@ -1535,7 +1545,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }; + debug!("one_bound_for_assoc_type: bound = {:?}", bound); + if let Some(bound2) = bounds.next() { + debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2); + let bounds = iter::once(bound).chain(iter::once(bound2)).chain(bounds); let mut err = struct_span_err!( self.tcx().sess, span, E0221, From 4e0e645dd964920e2a7ea5831ab90dd75c2676ff Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 18 Jun 2019 00:38:29 +0100 Subject: [PATCH 6/8] Added test for issue. --- .../ui/associated-type-bounds/issue-61752.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/ui/associated-type-bounds/issue-61752.rs diff --git a/src/test/ui/associated-type-bounds/issue-61752.rs b/src/test/ui/associated-type-bounds/issue-61752.rs new file mode 100644 index 0000000000000..27c302b793a86 --- /dev/null +++ b/src/test/ui/associated-type-bounds/issue-61752.rs @@ -0,0 +1,24 @@ +// run-pass + +#![feature(associated_type_bounds)] + +trait Foo { + type Bar; +} + +impl Foo for () { + type Bar = (); +} + +fn a() where F::Bar: Copy {} + +fn b() where ::Bar: Copy {} + +// This used to complain about ambiguous associated types. +fn c>() where F::Bar: Copy {} + +fn main() { + a::<()>(); + b::<()>(); + c::<()>(); +} From 0994cf4ab09fd22057308fe43fa2f6be25d74c36 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 5 Aug 2019 15:16:15 +0100 Subject: [PATCH 7/8] Added another test. --- .../ambiguous-associated-type.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/associated-type-bounds/ambiguous-associated-type.rs diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs b/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs new file mode 100644 index 0000000000000..364ead00c557a --- /dev/null +++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(associated_type_bounds)] + +pub struct Flatten +where + I: Iterator, +{ + inner: ::IntoIter, +} + +fn main() {} From 0410e320e28d0d2dfcc99d4d5ffcf7a6e5559b89 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 5 Aug 2019 23:43:26 +0100 Subject: [PATCH 8/8] Changed tests to check-pass. --- src/test/ui/associated-type-bounds/ambiguous-associated-type.rs | 2 +- src/test/ui/associated-type-bounds/issue-61752.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs b/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs index 364ead00c557a..9c47a003dfd09 100644 --- a/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs +++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(associated_type_bounds)] diff --git a/src/test/ui/associated-type-bounds/issue-61752.rs b/src/test/ui/associated-type-bounds/issue-61752.rs index 27c302b793a86..f38ec640e1781 100644 --- a/src/test/ui/associated-type-bounds/issue-61752.rs +++ b/src/test/ui/associated-type-bounds/issue-61752.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(associated_type_bounds)]