diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 93863ef1d50..8273c2d291d 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -1,10 +1,9 @@ use smallvec::smallvec; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::outlives::Component; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; -use rustc_span::symbol::Ident; pub fn anonymize_predicate<'tcx>( tcx: TyCtxt<'tcx>, @@ -288,37 +287,6 @@ pub fn transitive_bounds<'tcx>( elaborate_trait_refs(tcx, bounds).filter_to_traits() } -/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may -/// define the given associated type `assoc_name`. It uses the -/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that -/// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or -/// `T::Item` and helps to avoid cycle errors (see e.g. #35237). -pub fn transitive_bounds_that_define_assoc_type<'tcx>( - tcx: TyCtxt<'tcx>, - bounds: impl Iterator>, - assoc_name: Ident, -) -> FxIndexSet> { - let mut stack: Vec<_> = bounds.collect(); - let mut trait_refs = FxIndexSet::default(); - - while let Some(trait_ref) = stack.pop() { - if trait_refs.insert(trait_ref) { - let super_predicates = - tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), Some(assoc_name))); - for (super_predicate, _) in super_predicates.predicates { - let bound_predicate = super_predicate.bound_atom(); - let subst_predicate = super_predicate - .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder())); - if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() { - stack.push(binder.value); - } - } - } - } - - trait_refs -} - /////////////////////////////////////////////////////////////////////////// // Other /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b516810205f..7822ecc2c1f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -433,23 +433,12 @@ rustc_queries! { /// full predicates are available (note that supertraits have /// additional acyclicity requirements). query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } - } - - /// The `Option` is the name of an associated type. If it is `None`, then this query - /// returns the full set of predicates. If `Some`, then the query returns only the - /// subset of super-predicates that reference traits that define the given associated type. - /// This is used to avoid cycles in resolving types like `T::Item`. - query super_predicates_that_define_assoc_type(key: (DefId, Option)) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing the super traits of `{}`{}", - tcx.def_path_str(key.0), - if let Some(assoc_name) = key.1 { format!(" with associated type name `{}`", assoc_name) } else { "".to_string() }, - } + desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) } } /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. - query type_param_predicates(key: (DefId, LocalDefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> { + query type_param_predicates(key: (DefId, LocalDefId)) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing the bounds for type parameter `{}`", { let id = tcx.hir().local_def_id_to_hir_id(key.1); tcx.hir().ty_param_name(id) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 744aa39b96c..7207e5a179e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -51,7 +51,7 @@ use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; use rustc_session::lint::{Level, Lint}; use rustc_session::Session; use rustc_span::source_map::MultiSpan; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; @@ -2085,42 +2085,6 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig })) } - /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name` - /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`. - pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool { - self.super_traits_of(trait_def_id).any(|trait_did| { - self.associated_items(trait_did) - .find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did) - .is_some() - }) - } - - /// Computes the def-ids of the transitive super-traits of `trait_def_id`. This (intentionally) - /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used - /// to identify which traits may define a given associated type to help avoid cycle errors. - /// Returns a `DefId` iterator. - fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator + 'tcx { - let mut set = FxHashSet::default(); - let mut stack = vec![trait_def_id]; - - set.insert(trait_def_id); - - iter::from_fn(move || -> Option { - let trait_did = stack.pop()?; - let generic_predicates = self.super_predicates_of(trait_did); - - for (predicate, _) in generic_predicates.predicates { - if let ty::PredicateAtom::Trait(data, _) = predicate.skip_binders() { - if set.insert(data.def_id()) { - stack.push(data.def_id()); - } - } - } - - Some(trait_did) - }) - } - /// Given a closure signature, returns an equivalent fn signature. Detuples /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then /// you would get a `fn(u32, i32)`. diff --git a/compiler/rustc_middle/src/ty/query/keys.rs b/compiler/rustc_middle/src/ty/query/keys.rs index 3949c303f72..a005990264c 100644 --- a/compiler/rustc_middle/src/ty/query/keys.rs +++ b/compiler/rustc_middle/src/ty/query/keys.rs @@ -7,7 +7,7 @@ use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_query_system::query::DefaultCacheSelector; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; /// The `Key` trait controls what types can legally be used as the key @@ -149,28 +149,6 @@ impl Key for (LocalDefId, DefId) { } } -impl Key for (DefId, Option) { - type CacheSelector = DefaultCacheSelector; - - fn query_crate(&self) -> CrateNum { - self.0.krate - } - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - tcx.def_span(self.0) - } -} - -impl Key for (DefId, LocalDefId, Ident) { - type CacheSelector = DefaultCacheSelector; - - fn query_crate(&self) -> CrateNum { - self.0.krate - } - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - self.1.default_span(tcx) - } -} - impl Key for (CrateNum, DefId) { type CacheSelector = DefaultCacheSelector; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d6048d092b1..2fb9b3cd5d3 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -65,8 +65,7 @@ pub use self::util::{ get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices, }; pub use self::util::{ - supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type, - SupertraitDefIds, Supertraits, + supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits, }; pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext; diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 915a15fd245..7888cb1b9f5 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -49,10 +49,9 @@ pub trait AstConv<'tcx> { fn default_constness_for_trait_bounds(&self) -> Constness; - /// Returns predicates in scope of the form `X: Foo`, where `X` - /// is a type parameter `X` with the given id `def_id` and T - /// matches `assoc_name`. This is a subset of the full set of - /// predicates. + /// 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 @@ -61,12 +60,7 @@ pub trait AstConv<'tcx> { /// 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, - assoc_name: Ident, - ) -> ty::GenericPredicates<'tcx>; + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>; /// Returns the lifetime to use when a lifetime is omitted (and not elided). fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) @@ -768,7 +762,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Returns `true` if a bounds list includes `?Sized`. - pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> bool { + pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool { let tcx = self.tcx(); // Try to find an unbound in bounds. @@ -826,7 +820,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn add_bounds( &self, param_ty: Ty<'tcx>, - ast_bounds: &[&hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'_>], bounds: &mut Bounds<'tcx>, ) { let constness = self.default_constness_for_trait_bounds(); @@ -841,7 +835,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self .instantiate_lang_item_trait_ref( - *lang_item, *span, *hir_id, args, param_ty, bounds, + lang_item, span, hir_id, args, param_ty, bounds, ), hir::GenericBound::Outlives(ref l) => { bounds.region_bounds.push((self.ast_region_to_region(l, None), l.span)) @@ -872,42 +866,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ast_bounds: &[hir::GenericBound<'_>], sized_by_default: SizedByDefault, span: Span, - ) -> Bounds<'tcx> { - let ast_bounds: Vec<_> = ast_bounds.iter().collect(); - self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span) - } - - /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type - /// named `assoc_name` into ty::Bounds. Ignore the rest. - pub fn compute_bounds_that_match_assoc_type( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], - sized_by_default: SizedByDefault, - span: Span, - assoc_name: Ident, - ) -> Bounds<'tcx> { - let mut result = Vec::new(); - - for ast_bound in ast_bounds { - if let Some(trait_ref) = ast_bound.trait_ref() { - if let Some(trait_did) = trait_ref.trait_def_id() { - if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) { - result.push(ast_bound); - } - } - } - } - - self.compute_bounds_inner(param_ty, &result, sized_by_default, span) - } - - fn compute_bounds_inner( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[&hir::GenericBound<'_>], - sized_by_default: SizedByDefault, - span: Span, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); @@ -1077,8 +1035,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); - let ast_bounds: Vec<_> = ast_bounds.iter().collect(); - self.add_bounds(param_ty, &ast_bounds, bounds); + self.add_bounds(param_ty, ast_bounds, bounds); } } Ok(()) @@ -1395,9 +1352,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty_param_def_id, assoc_name, span, ); - let predicates = &self - .get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name) - .predicates; + let predicates = + &self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates; debug!("find_bound_for_assoc_item: predicates={:#?}", predicates); @@ -1405,14 +1361,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let param_name = tcx.hir().ty_param_name(param_hir_id); self.one_bound_for_assoc_type( || { - traits::transitive_bounds_that_define_assoc_type( + traits::transitive_bounds( tcx, predicates.iter().filter_map(|(p, _)| { p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value) }), - assoc_name, ) - .into_iter() }, || param_name.to_string(), assoc_name, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 20c639a0031..f635e0b6f93 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -20,7 +20,6 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_session::Session; -use rustc_span::symbol::Ident; use rustc_span::{self, Span}; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; @@ -184,12 +183,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { } } - fn get_type_parameter_bounds( - &self, - _: Span, - def_id: DefId, - _: Ident, - ) -> ty::GenericPredicates<'tcx> { + fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { let tcx = self.tcx; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let item_id = tcx.hir().ty_param_owner(hir_id); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index f8b7ccb2cd6..0ff10abb60a 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1,4 +1,3 @@ -// ignore-tidy-filelength //! "Collection" is the process of determining the type and other external //! details of each item in Rust. Collection is specifically concerned //! with *inter-procedural* things -- for example, for a function @@ -80,7 +79,6 @@ pub fn provide(providers: &mut Providers) { projection_ty_from_predicates, explicit_predicates_of, super_predicates_of, - super_predicates_that_define_assoc_type, trait_explicit_predicates_and_bounds, type_param_predicates, trait_def, @@ -312,17 +310,8 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } } - fn get_type_parameter_bounds( - &self, - span: Span, - def_id: DefId, - assoc_name: Ident, - ) -> ty::GenericPredicates<'tcx> { - self.tcx.at(span).type_param_predicates(( - self.item_def_id, - def_id.expect_local(), - assoc_name, - )) + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { + self.tcx.at(span).type_param_predicates((self.item_def_id, def_id.expect_local())) } fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option> { @@ -503,7 +492,7 @@ fn get_new_lifetime_name<'tcx>( /// `X: Foo` where `X` is the type parameter `def_id`. fn type_param_predicates( tcx: TyCtxt<'_>, - (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident), + (item_def_id, def_id): (DefId, LocalDefId), ) -> ty::GenericPredicates<'_> { use rustc_hir::*; @@ -528,7 +517,7 @@ fn type_param_predicates( let mut result = parent .map(|parent| { let icx = ItemCtxt::new(tcx, parent); - icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name) + icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id()) }) .unwrap_or_default(); let mut extend = None; @@ -571,18 +560,12 @@ fn type_param_predicates( let icx = ItemCtxt::new(tcx, item_def_id); let extra_predicates = extend.into_iter().chain( - icx.type_parameter_bounds_in_generics( - ast_generics, - param_id, - ty, - OnlySelfBounds(true), - Some(assoc_name), - ) - .into_iter() - .filter(|(predicate, _)| match predicate.skip_binders() { - ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index), - _ => false, - }), + icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true)) + .into_iter() + .filter(|(predicate, _)| match predicate.skip_binders() { + ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index), + _ => false, + }), ); result.predicates = tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates)); @@ -600,7 +583,6 @@ impl ItemCtxt<'tcx> { param_id: hir::HirId, ty: Ty<'tcx>, only_self_bounds: OnlySelfBounds, - assoc_name: Option, ) -> Vec<(ty::Predicate<'tcx>, Span)> { let constness = self.default_constness_for_trait_bounds(); let from_ty_params = ast_generics @@ -611,10 +593,6 @@ impl ItemCtxt<'tcx> { _ => None, }) .flat_map(|bounds| bounds.iter()) - .filter(|b| match assoc_name { - Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), - None => true, - }) .flat_map(|b| predicates_from_bound(self, ty, b, constness)); let from_where_clauses = ast_generics @@ -633,34 +611,12 @@ impl ItemCtxt<'tcx> { } else { None }; - bp.bounds - .iter() - .filter(|b| match assoc_name { - Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), - None => true, - }) - .filter_map(move |b| bt.map(|bt| (bt, b))) + bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b))) }) .flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness)); from_ty_params.chain(from_where_clauses).collect() } - - fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool { - debug!("bound_defines_assoc_item(b={:?}, assoc_name={:?})", b, assoc_name); - - match b { - hir::GenericBound::Trait(poly_trait_ref, _) => { - let trait_ref = &poly_trait_ref.trait_ref; - if let Some(trait_did) = trait_ref.trait_def_id() { - self.tcx.trait_may_define_assoc_type(trait_did, assoc_name) - } else { - false - } - } - _ => false, - } - } } /// Tests whether this is the AST for a reference to the type @@ -1029,90 +985,54 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { /// the transitive super-predicates are converted. fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); - tcx.super_predicates_that_define_assoc_type((trait_def_id, None)) -} + let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); -/// Ensures that the super-predicates of the trait with a `DefId` -/// of `trait_def_id` are converted and stored. This also ensures that -/// the transitive super-predicates are converted. -fn super_predicates_that_define_assoc_type( - tcx: TyCtxt<'_>, - (trait_def_id, assoc_name): (DefId, Option), -) -> ty::GenericPredicates<'_> { - debug!( - "super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})", - trait_def_id, assoc_name + let item = match tcx.hir().get(trait_hir_id) { + Node::Item(item) => item, + _ => bug!("trait_node_id {} is not an item", trait_hir_id), + }; + + let (generics, bounds) = match item.kind { + hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), + hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), + _ => span_bug!(item.span, "super_predicates invoked on non-trait"), + }; + + let icx = ItemCtxt::new(tcx, trait_def_id); + + // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. + let self_param_ty = tcx.types.self_param; + let superbounds1 = + AstConv::compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); + + let superbounds1 = superbounds1.predicates(tcx, self_param_ty); + + // Convert any explicit superbounds in the where-clause, + // e.g., `trait Foo where Self: Bar`. + // In the case of trait aliases, however, we include all bounds in the where-clause, + // so e.g., `trait Foo = where u32: PartialEq` would include `u32: PartialEq` + // as one of its "superpredicates". + let is_trait_alias = tcx.is_trait_alias(trait_def_id); + let superbounds2 = icx.type_parameter_bounds_in_generics( + generics, + item.hir_id, + self_param_ty, + OnlySelfBounds(!is_trait_alias), ); - if trait_def_id.is_local() { - debug!("super_predicates_that_define_assoc_type: local trait_def_id={:?}", trait_def_id); - let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); - let item = match tcx.hir().get(trait_hir_id) { - Node::Item(item) => item, - _ => bug!("trait_node_id {} is not an item", trait_hir_id), - }; + // Combine the two lists to form the complete set of superbounds: + let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); - let (generics, bounds) = match item.kind { - hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), - _ => span_bug!(item.span, "super_predicates invoked on non-trait"), - }; - - let icx = ItemCtxt::new(tcx, trait_def_id); - - // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. - let self_param_ty = tcx.types.self_param; - let superbounds1 = if let Some(assoc_name) = assoc_name { - AstConv::compute_bounds_that_match_assoc_type( - &icx, - self_param_ty, - &bounds, - SizedByDefault::No, - item.span, - assoc_name, - ) - } else { - AstConv::compute_bounds(&icx, self_param_ty, &bounds, SizedByDefault::No, item.span) - }; - - let superbounds1 = superbounds1.predicates(tcx, self_param_ty); - - // Convert any explicit superbounds in the where-clause, - // e.g., `trait Foo where Self: Bar`. - // In the case of trait aliases, however, we include all bounds in the where-clause, - // so e.g., `trait Foo = where u32: PartialEq` would include `u32: PartialEq` - // as one of its "superpredicates". - let is_trait_alias = tcx.is_trait_alias(trait_def_id); - let superbounds2 = icx.type_parameter_bounds_in_generics( - generics, - item.hir_id, - self_param_ty, - OnlySelfBounds(!is_trait_alias), - assoc_name, - ); - - // Combine the two lists to form the complete set of superbounds: - let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); - - // Now require that immediate supertraits are converted, - // which will, in turn, reach indirect supertraits. - if assoc_name.is_none() { - // FIXME: move this into the `super_predicates_of` query - for &(pred, span) in superbounds { - debug!("superbound: {:?}", pred); - if let ty::PredicateAtom::Trait(bound, _) = pred.skip_binders() { - tcx.at(span).super_predicates_of(bound.def_id()); - } - } + // Now require that immediate supertraits are converted, + // which will, in turn, reach indirect supertraits. + for &(pred, span) in superbounds { + debug!("superbound: {:?}", pred); + if let ty::PredicateAtom::Trait(bound, _) = pred.skip_binders() { + tcx.at(span).super_predicates_of(bound.def_id()); } - - ty::GenericPredicates { parent: None, predicates: superbounds } - } else { - // if `assoc_name` is None, then the query should've been redirected to an - // external provider - assert!(assoc_name.is_some()); - tcx.super_predicates_of(trait_def_id) } + + ty::GenericPredicates { parent: None, predicates: superbounds } } fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index dd1da7d9cff..e596dd1a396 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>( let bounds = AstConv::compute_bounds( &ItemCtxt::new(tcx, assoc_item_def_id), item_ty, - &bounds, + bounds, SizedByDefault::Yes, span, ); @@ -68,7 +68,7 @@ fn opaque_type_bounds<'tcx>( let bounds = AstConv::compute_bounds( &ItemCtxt::new(tcx, opaque_def_id), item_ty, - &bounds, + bounds, SizedByDefault::Yes, span, ) diff --git a/src/test/incremental/cyclic-trait-hierarchy.rs b/src/test/incremental/cyclic-trait-hierarchy.rs index b502e7207d5..03bb5eea765 100644 --- a/src/test/incremental/cyclic-trait-hierarchy.rs +++ b/src/test/incremental/cyclic-trait-hierarchy.rs @@ -3,11 +3,11 @@ // revisions: rpass1 cfail2 #[cfg(rpass1)] -pub trait T2 {} +pub trait T2 { } #[cfg(cfail2)] -pub trait T2: T1 {} -//[cfail2]~^ ERROR cycle detected when computing the super predicates of `T2` +pub trait T2: T1 { } +//[cfail2]~^ ERROR cycle detected when computing the supertraits of `T2` -pub trait T1: T2 {} +pub trait T1: T2 { } -fn main() {} +fn main() { } diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs deleted file mode 100644 index 1b6d6d0ff59..00000000000 --- a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs +++ /dev/null @@ -1,12 +0,0 @@ -// ignore-tidy-linelength - -trait Foo { - type Item; -} -trait Bar { - type Item; -} -trait Baz: Foo + Bar {} -//~^ ERROR cycle detected when computing the super traits of `Baz` with associated type name `Item` [E0391] - -fn main() {} diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr deleted file mode 100644 index bda1debeac0..00000000000 --- a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0391]: cycle detected when computing the super traits of `Baz` with associated type name `Item` - --> $DIR/ambiguous-associated-type2.rs:9:1 - | -LL | trait Baz: Foo + Bar {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: ...which again requires computing the super traits of `Baz` with associated type name `Item`, completing the cycle -note: cycle used when computing the super traits of `Baz` - --> $DIR/ambiguous-associated-type2.rs:9:1 - | -LL | trait Baz: Foo + Bar {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs b/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs deleted file mode 100644 index 3eb50ab5547..00000000000 --- a/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs +++ /dev/null @@ -1,21 +0,0 @@ -// check-pass - -trait Foo { - type Item; -} - -trait Bar -where - Self: Foo, -{ -} - -#[allow(dead_code)] -fn foo(_m: M) -where - M: Bar, - M::Item: Send, -{ -} - -fn main() {} diff --git a/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs b/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs deleted file mode 100644 index b1e54ec0449..00000000000 --- a/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs +++ /dev/null @@ -1,10 +0,0 @@ -// check-pass - -trait Foo {} -trait Bar { - type A; - type B; -} -trait Baz: Bar + Foo {} - -fn main() {} diff --git a/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs deleted file mode 100644 index 07d0f8f8769..00000000000 --- a/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[allow(dead_code)] -fn foo(_m: M) -where - M::Item: Temp, - //~^ ERROR cannot find trait `Temp` in this scope [E0405] - //~| ERROR associated type `Item` not found for `M` [E0220] -{ -} - -fn main() {} diff --git a/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr deleted file mode 100644 index bc2807b0396..00000000000 --- a/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0405]: cannot find trait `Temp` in this scope - --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:14 - | -LL | M::Item: Temp, - | ^^^^ not found in this scope - -error[E0220]: associated type `Item` not found for `M` - --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8 - | -LL | M::Item: Temp, - | ^^^^ associated type `Item` not found - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0220, E0405. -For more information about an error, try `rustc --explain E0220`. diff --git a/src/test/ui/associated-type-bounds/super-trait-referencing-self.rs b/src/test/ui/associated-type-bounds/super-trait-referencing-self.rs deleted file mode 100644 index c82ec01f4d6..00000000000 --- a/src/test/ui/associated-type-bounds/super-trait-referencing-self.rs +++ /dev/null @@ -1,12 +0,0 @@ -// check-pass -trait Foo { - type Bar; -} -trait Qux: Foo + AsRef {} -trait Foo2 {} - -trait Qux2: Foo2 + AsRef { - type Bar; -} - -fn main() {} diff --git a/src/test/ui/associated-type-bounds/super-trait-referencing.rs b/src/test/ui/associated-type-bounds/super-trait-referencing.rs deleted file mode 100644 index 2e97535157f..00000000000 --- a/src/test/ui/associated-type-bounds/super-trait-referencing.rs +++ /dev/null @@ -1,19 +0,0 @@ -// check-pass - -// The goal of this test is to ensure that T: Bar -// in the where clause does not cycle - -trait Foo { - type Item; -} - -trait Bar {} - -fn baz() -where - T: Foo, - T: Bar, -{ -} - -fn main() {} diff --git a/src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs b/src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs deleted file mode 100644 index 72a6be9ffc3..00000000000 --- a/src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs +++ /dev/null @@ -1,27 +0,0 @@ -// check-pass - -// Test that we do not get a cycle due to -// resolving `Self::Bar` in the where clauses -// on a trait definition (in particular, in -// a where clause that is defining a superpredicate). - -trait Foo { - type Bar; -} -trait Qux -where - Self: Foo, - Self: AsRef, -{ -} -trait Foo2 {} - -trait Qux2 -where - Self: Foo2, - Self: AsRef, -{ - type Bar; -} - -fn main() {} diff --git a/src/test/ui/cycle-projection-based-on-where-clause.rs b/src/test/ui/cycle-projection-based-on-where-clause.rs new file mode 100644 index 00000000000..d3609acfdff --- /dev/null +++ b/src/test/ui/cycle-projection-based-on-where-clause.rs @@ -0,0 +1,24 @@ +// Example cycle where a bound on `T` uses a shorthand for `T`. This +// creates a cycle because we have to know the bounds on `T` to figure +// out what trait defines `Item`, but we can't know the bounds on `T` +// without knowing how to handle `T::Item`. +// +// Note that in the future cases like this could perhaps become legal, +// if we got more fine-grained about our cycle detection or changed +// how we handle `T::Item` resolution. + +use std::ops::Add; + +// Preamble. +trait Trait { type Item; } + +struct A + where T : Trait, + T : Add + //~^ ERROR cycle detected +{ + data: T +} + +fn main() { +} diff --git a/src/test/ui/cycle-projection-based-on-where-clause.stderr b/src/test/ui/cycle-projection-based-on-where-clause.stderr new file mode 100644 index 00000000000..2c337cc6bf9 --- /dev/null +++ b/src/test/ui/cycle-projection-based-on-where-clause.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing the bounds for type parameter `T` + --> $DIR/cycle-projection-based-on-where-clause.rs:17:19 + | +LL | T : Add + | ^^^^^^^ + | + = note: ...which again requires computing the bounds for type parameter `T`, completing the cycle +note: cycle used when computing explicit predicates of `A` + --> $DIR/cycle-projection-based-on-where-clause.rs:17:19 + | +LL | T : Add + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr index ee54b2fd151..8aa3ac8abf5 100644 --- a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr +++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr @@ -1,15 +1,10 @@ -error[E0391]: cycle detected when computing the super predicates of `Chromosome` - --> $DIR/cycle-trait-supertrait-direct.rs:3:1 - | -LL | trait Chromosome: Chromosome { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires computing the super traits of `Chromosome`... +error[E0391]: cycle detected when computing the supertraits of `Chromosome` --> $DIR/cycle-trait-supertrait-direct.rs:3:19 | LL | trait Chromosome: Chromosome { | ^^^^^^^^^^ - = note: ...which again requires computing the super predicates of `Chromosome`, completing the cycle + | + = note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle note: cycle used when collecting item types in top-level module --> $DIR/cycle-trait-supertrait-direct.rs:3:1 | diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr index 0a2284e0efb..9740f43a4ba 100644 --- a/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr +++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr @@ -1,26 +1,16 @@ -error[E0391]: cycle detected when computing the super predicates of `B` - --> $DIR/cycle-trait-supertrait-indirect.rs:7:1 - | -LL | trait B: C { - | ^^^^^^^^^^ - | -note: ...which requires computing the super traits of `B`... +error[E0391]: cycle detected when computing the supertraits of `B` --> $DIR/cycle-trait-supertrait-indirect.rs:7:10 | LL | trait B: C { | ^ -note: ...which requires computing the super predicates of `C`... - --> $DIR/cycle-trait-supertrait-indirect.rs:11:1 | -LL | trait C: B { } - | ^^^^^^^^^^ -note: ...which requires computing the super traits of `C`... +note: ...which requires computing the supertraits of `C`... --> $DIR/cycle-trait-supertrait-indirect.rs:11:10 | LL | trait C: B { } | ^ - = note: ...which again requires computing the super predicates of `B`, completing the cycle -note: cycle used when computing the super traits of `A` + = note: ...which again requires computing the supertraits of `B`, completing the cycle +note: cycle used when computing the supertraits of `A` --> $DIR/cycle-trait-supertrait-indirect.rs:4:10 | LL | trait A: B { diff --git a/src/test/ui/issues/issue-12511.stderr b/src/test/ui/issues/issue-12511.stderr index 5f2b98c5237..37e38ff60ae 100644 --- a/src/test/ui/issues/issue-12511.stderr +++ b/src/test/ui/issues/issue-12511.stderr @@ -1,25 +1,15 @@ -error[E0391]: cycle detected when computing the super predicates of `T1` - --> $DIR/issue-12511.rs:1:1 - | -LL | trait T1 : T2 { - | ^^^^^^^^^^^^^ - | -note: ...which requires computing the super traits of `T1`... +error[E0391]: cycle detected when computing the supertraits of `T1` --> $DIR/issue-12511.rs:1:12 | LL | trait T1 : T2 { | ^^ -note: ...which requires computing the super predicates of `T2`... - --> $DIR/issue-12511.rs:5:1 | -LL | trait T2 : T1 { - | ^^^^^^^^^^^^^ -note: ...which requires computing the super traits of `T2`... +note: ...which requires computing the supertraits of `T2`... --> $DIR/issue-12511.rs:5:12 | LL | trait T2 : T1 { | ^^ - = note: ...which again requires computing the super predicates of `T1`, completing the cycle + = note: ...which again requires computing the supertraits of `T1`, completing the cycle note: cycle used when collecting item types in top-level module --> $DIR/issue-12511.rs:1:1 | diff --git a/src/test/ui/issues/issue-20772.stderr b/src/test/ui/issues/issue-20772.stderr index 4aecc7eab46..d64636310a3 100644 --- a/src/test/ui/issues/issue-20772.stderr +++ b/src/test/ui/issues/issue-20772.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when computing the super traits of `T` with associated type name `Item` +error[E0391]: cycle detected when computing the supertraits of `T` --> $DIR/issue-20772.rs:1:1 | LL | / trait T : Iterator @@ -6,8 +6,8 @@ LL | | LL | | {} | |__^ | - = note: ...which again requires computing the super traits of `T` with associated type name `Item`, completing the cycle -note: cycle used when computing the super traits of `T` + = note: ...which again requires computing the supertraits of `T`, completing the cycle +note: cycle used when collecting item types in top-level module --> $DIR/issue-20772.rs:1:1 | LL | / trait T : Iterator diff --git a/src/test/ui/issues/issue-20825.stderr b/src/test/ui/issues/issue-20825.stderr index ccbe06d9c0d..5f9709d1c64 100644 --- a/src/test/ui/issues/issue-20825.stderr +++ b/src/test/ui/issues/issue-20825.stderr @@ -1,11 +1,11 @@ -error[E0391]: cycle detected when computing the super traits of `Processor` with associated type name `Input` +error[E0391]: cycle detected when computing the supertraits of `Processor` --> $DIR/issue-20825.rs:5:1 | LL | pub trait Processor: Subscriber { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...which again requires computing the super traits of `Processor` with associated type name `Input`, completing the cycle -note: cycle used when computing the super traits of `Processor` + = note: ...which again requires computing the supertraits of `Processor`, completing the cycle +note: cycle used when collecting item types in top-level module --> $DIR/issue-20825.rs:5:1 | LL | pub trait Processor: Subscriber { diff --git a/src/test/ui/issues/issue-22673.rs b/src/test/ui/issues/issue-22673.rs index 4b9b4d6b23d..ba8057b684d 100644 --- a/src/test/ui/issues/issue-22673.rs +++ b/src/test/ui/issues/issue-22673.rs @@ -1,6 +1,5 @@ -// check-pass - -trait Expr: PartialEq { +trait Expr : PartialEq { + //~^ ERROR: cycle detected type Item; } diff --git a/src/test/ui/issues/issue-22673.stderr b/src/test/ui/issues/issue-22673.stderr new file mode 100644 index 00000000000..9e7e4b218b1 --- /dev/null +++ b/src/test/ui/issues/issue-22673.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing the supertraits of `Expr` + --> $DIR/issue-22673.rs:1:1 + | +LL | trait Expr : PartialEq { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which again requires computing the supertraits of `Expr`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-22673.rs:1:1 + | +LL | trait Expr : PartialEq { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`.