提交 b4def89d 编写于 作者: B bors

Auto merge of #79637 - spastorino:revert-trait-inheritance-self, r=Mark-Simulacrum

Revert "Auto merge of #79209

r? `@nikomatsakis`

This has caused some issues (#79560) so better to revert and try to come up with a proper fix without rush.
use smallvec::smallvec; use smallvec::smallvec;
use crate::traits::{Obligation, ObligationCause, PredicateObligation}; 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::outlives::Component;
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
use rustc_span::symbol::Ident;
pub fn anonymize_predicate<'tcx>( pub fn anonymize_predicate<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
...@@ -288,37 +287,6 @@ pub fn transitive_bounds<'tcx>( ...@@ -288,37 +287,6 @@ pub fn transitive_bounds<'tcx>(
elaborate_trait_refs(tcx, bounds).filter_to_traits() 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<Item = ty::PolyTraitRef<'tcx>>,
assoc_name: Ident,
) -> FxIndexSet<ty::PolyTraitRef<'tcx>> {
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 // Other
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
......
...@@ -433,23 +433,12 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { ...@@ -433,23 +433,12 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
/// full predicates are available (note that supertraits have /// full predicates are available (note that supertraits have
/// additional acyclicity requirements). /// additional acyclicity requirements).
query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) }
}
/// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
/// returns the full set of predicates. If `Some<Ident>`, 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<rustc_span::symbol::Ident>)) -> 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() },
}
} }
/// To avoid cycles within the predicates of a single item we compute /// To avoid cycles within the predicates of a single item we compute
/// per-type-parameter predicates for resolving `T::AssocTy`. /// 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 `{}`", { desc { |tcx| "computing the bounds for type parameter `{}`", {
let id = tcx.hir().local_def_id_to_hir_id(key.1); let id = tcx.hir().local_def_id_to_hir_id(key.1);
tcx.hir().ty_param_name(id) tcx.hir().ty_param_name(id)
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
use rustc_session::lint::{Level, Lint}; use rustc_session::lint::{Level, Lint};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::source_map::MultiSpan; 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_span::{Span, DUMMY_SP};
use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi; use rustc_target::spec::abi;
...@@ -2066,42 +2066,6 @@ pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { ...@@ -2066,42 +2066,6 @@ pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig })) 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<Item = DefId> + 'tcx {
let mut set = FxHashSet::default();
let mut stack = vec![trait_def_id];
set.insert(trait_def_id);
iter::from_fn(move || -> Option<DefId> {
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 /// 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 /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
/// you would get a `fn(u32, i32)`. /// you would get a `fn(u32, i32)`.
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{self, Ty, TyCtxt};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_query_system::query::DefaultCacheSelector; use rustc_query_system::query::DefaultCacheSelector;
use rustc_span::symbol::{Ident, Symbol}; use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
/// The `Key` trait controls what types can legally be used as the key /// The `Key` trait controls what types can legally be used as the key
...@@ -149,28 +149,6 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span { ...@@ -149,28 +149,6 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
} }
} }
impl Key for (DefId, Option<Ident>) {
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) { impl Key for (CrateNum, DefId) {
type CacheSelector = DefaultCacheSelector; type CacheSelector = DefaultCacheSelector;
......
...@@ -65,8 +65,7 @@ ...@@ -65,8 +65,7 @@
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices, get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
}; };
pub use self::util::{ pub use self::util::{
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type, supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
SupertraitDefIds, Supertraits,
}; };
pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext; pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;
......
...@@ -49,10 +49,9 @@ pub trait AstConv<'tcx> { ...@@ -49,10 +49,9 @@ pub trait AstConv<'tcx> {
fn default_constness_for_trait_bounds(&self) -> Constness; fn default_constness_for_trait_bounds(&self) -> Constness;
/// Returns predicates in scope of the form `X: Foo<T>`, where `X` /// Returns predicates in scope of the form `X: Foo`, where `X` is
/// is a type parameter `X` with the given id `def_id` and T /// a type parameter `X` with the given id `def_id`. This is a
/// matches `assoc_name`. This is a subset of the full set of /// subset of the full set of predicates.
/// predicates.
/// ///
/// This is used for one specific purpose: resolving "short-hand" /// This is used for one specific purpose: resolving "short-hand"
/// associated type references like `T::Item`. In principle, we /// associated type references like `T::Item`. In principle, we
...@@ -61,12 +60,7 @@ pub trait AstConv<'tcx> { ...@@ -61,12 +60,7 @@ pub trait AstConv<'tcx> {
/// but this can lead to cycle errors. The problem is that we have /// but this can lead to cycle errors. The problem is that we have
/// to do this resolution *in order to create the predicates in /// to do this resolution *in order to create the predicates in
/// the first place*. Hence, we have this "special pass". /// the first place*. Hence, we have this "special pass".
fn get_type_parameter_bounds( fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>;
&self,
span: Span,
def_id: DefId,
assoc_name: Ident,
) -> ty::GenericPredicates<'tcx>;
/// Returns the lifetime to use when a lifetime is omitted (and not elided). /// Returns the lifetime to use when a lifetime is omitted (and not elided).
fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
...@@ -768,7 +762,7 @@ fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: I ...@@ -768,7 +762,7 @@ fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: I
} }
// Returns `true` if a bounds list includes `?Sized`. // 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(); let tcx = self.tcx();
// Try to find an unbound in bounds. // Try to find an unbound in bounds.
...@@ -826,7 +820,7 @@ pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> b ...@@ -826,7 +820,7 @@ pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> b
fn add_bounds( fn add_bounds(
&self, &self,
param_ty: Ty<'tcx>, param_ty: Ty<'tcx>,
ast_bounds: &[&hir::GenericBound<'_>], ast_bounds: &[hir::GenericBound<'_>],
bounds: &mut Bounds<'tcx>, bounds: &mut Bounds<'tcx>,
) { ) {
let constness = self.default_constness_for_trait_bounds(); let constness = self.default_constness_for_trait_bounds();
...@@ -841,7 +835,7 @@ fn add_bounds( ...@@ -841,7 +835,7 @@ fn add_bounds(
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
.instantiate_lang_item_trait_ref( .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) => { hir::GenericBound::Outlives(ref l) => {
bounds.region_bounds.push((self.ast_region_to_region(l, None), l.span)) bounds.region_bounds.push((self.ast_region_to_region(l, None), l.span))
...@@ -872,42 +866,6 @@ pub fn compute_bounds( ...@@ -872,42 +866,6 @@ pub fn compute_bounds(
ast_bounds: &[hir::GenericBound<'_>], ast_bounds: &[hir::GenericBound<'_>],
sized_by_default: SizedByDefault, sized_by_default: SizedByDefault,
span: Span, 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> { ) -> Bounds<'tcx> {
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
...@@ -1077,8 +1035,7 @@ fn add_predicates_for_ast_type_binding( ...@@ -1077,8 +1035,7 @@ fn add_predicates_for_ast_type_binding(
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
// parameter to have a skipped binder. // parameter to have a skipped binder.
let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs); 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(()) Ok(())
...@@ -1395,9 +1352,8 @@ fn find_bound_for_assoc_item( ...@@ -1395,9 +1352,8 @@ fn find_bound_for_assoc_item(
ty_param_def_id, assoc_name, span, ty_param_def_id, assoc_name, span,
); );
let predicates = &self let predicates =
.get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name) &self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
.predicates;
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates); debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
...@@ -1405,14 +1361,12 @@ fn find_bound_for_assoc_item( ...@@ -1405,14 +1361,12 @@ fn find_bound_for_assoc_item(
let param_name = tcx.hir().ty_param_name(param_hir_id); let param_name = tcx.hir().ty_param_name(param_hir_id);
self.one_bound_for_assoc_type( self.one_bound_for_assoc_type(
|| { || {
traits::transitive_bounds_that_define_assoc_type( traits::transitive_bounds(
tcx, tcx,
predicates.iter().filter_map(|(p, _)| { predicates.iter().filter_map(|(p, _)| {
p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value) p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value)
}), }),
assoc_name,
) )
.into_iter()
}, },
|| param_name.to_string(), || param_name.to_string(),
assoc_name, assoc_name,
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_middle::ty::{self, Const, Ty, TyCtxt};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::{self, Span}; use rustc_span::{self, Span};
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
...@@ -184,12 +183,7 @@ fn default_constness_for_trait_bounds(&self) -> hir::Constness { ...@@ -184,12 +183,7 @@ fn default_constness_for_trait_bounds(&self) -> hir::Constness {
} }
} }
fn get_type_parameter_bounds( fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
&self,
_: Span,
def_id: DefId,
_: Ident,
) -> ty::GenericPredicates<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); 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); let item_id = tcx.hir().ty_param_owner(hir_id);
......
// ignore-tidy-filelength
//! "Collection" is the process of determining the type and other external //! "Collection" is the process of determining the type and other external
//! details of each item in Rust. Collection is specifically concerned //! details of each item in Rust. Collection is specifically concerned
//! with *inter-procedural* things -- for example, for a function //! with *inter-procedural* things -- for example, for a function
...@@ -80,7 +79,6 @@ pub fn provide(providers: &mut Providers) { ...@@ -80,7 +79,6 @@ pub fn provide(providers: &mut Providers) {
projection_ty_from_predicates, projection_ty_from_predicates,
explicit_predicates_of, explicit_predicates_of,
super_predicates_of, super_predicates_of,
super_predicates_that_define_assoc_type,
trait_explicit_predicates_and_bounds, trait_explicit_predicates_and_bounds,
type_param_predicates, type_param_predicates,
trait_def, trait_def,
...@@ -312,17 +310,8 @@ fn default_constness_for_trait_bounds(&self) -> hir::Constness { ...@@ -312,17 +310,8 @@ fn default_constness_for_trait_bounds(&self) -> hir::Constness {
} }
} }
fn get_type_parameter_bounds( fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
&self, self.tcx.at(span).type_param_predicates((self.item_def_id, def_id.expect_local()))
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 re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> { fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
...@@ -503,7 +492,7 @@ fn get_new_lifetime_name<'tcx>( ...@@ -503,7 +492,7 @@ fn get_new_lifetime_name<'tcx>(
/// `X: Foo` where `X` is the type parameter `def_id`. /// `X: Foo` where `X` is the type parameter `def_id`.
fn type_param_predicates( fn type_param_predicates(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
(item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident), (item_def_id, def_id): (DefId, LocalDefId),
) -> ty::GenericPredicates<'_> { ) -> ty::GenericPredicates<'_> {
use rustc_hir::*; use rustc_hir::*;
...@@ -528,7 +517,7 @@ fn type_param_predicates( ...@@ -528,7 +517,7 @@ fn type_param_predicates(
let mut result = parent let mut result = parent
.map(|parent| { .map(|parent| {
let icx = ItemCtxt::new(tcx, 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(); .unwrap_or_default();
let mut extend = None; let mut extend = None;
...@@ -571,18 +560,12 @@ fn type_param_predicates( ...@@ -571,18 +560,12 @@ fn type_param_predicates(
let icx = ItemCtxt::new(tcx, item_def_id); let icx = ItemCtxt::new(tcx, item_def_id);
let extra_predicates = extend.into_iter().chain( let extra_predicates = extend.into_iter().chain(
icx.type_parameter_bounds_in_generics( icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
ast_generics, .into_iter()
param_id, .filter(|(predicate, _)| match predicate.skip_binders() {
ty, ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index),
OnlySelfBounds(true), _ => false,
Some(assoc_name), }),
)
.into_iter()
.filter(|(predicate, _)| match predicate.skip_binders() {
ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index),
_ => false,
}),
); );
result.predicates = result.predicates =
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates)); tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates));
...@@ -600,7 +583,6 @@ fn type_parameter_bounds_in_generics( ...@@ -600,7 +583,6 @@ fn type_parameter_bounds_in_generics(
param_id: hir::HirId, param_id: hir::HirId,
ty: Ty<'tcx>, ty: Ty<'tcx>,
only_self_bounds: OnlySelfBounds, only_self_bounds: OnlySelfBounds,
assoc_name: Option<Ident>,
) -> Vec<(ty::Predicate<'tcx>, Span)> { ) -> Vec<(ty::Predicate<'tcx>, Span)> {
let constness = self.default_constness_for_trait_bounds(); let constness = self.default_constness_for_trait_bounds();
let from_ty_params = ast_generics let from_ty_params = ast_generics
...@@ -611,10 +593,6 @@ fn type_parameter_bounds_in_generics( ...@@ -611,10 +593,6 @@ fn type_parameter_bounds_in_generics(
_ => None, _ => None,
}) })
.flat_map(|bounds| bounds.iter()) .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)); .flat_map(|b| predicates_from_bound(self, ty, b, constness));
let from_where_clauses = ast_generics let from_where_clauses = ast_generics
...@@ -633,34 +611,12 @@ fn type_parameter_bounds_in_generics( ...@@ -633,34 +611,12 @@ fn type_parameter_bounds_in_generics(
} else { } else {
None None
}; };
bp.bounds bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
.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)))
}) })
.flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness)); .flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness));
from_ty_params.chain(from_where_clauses).collect() 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 /// 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 { ...@@ -1029,90 +985,54 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
/// the transitive super-predicates are converted. /// the transitive super-predicates are converted.
fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> { fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> {
debug!("super_predicates(trait_def_id={:?})", trait_def_id); 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<Ident>),
) -> ty::GenericPredicates<'_> {
debug!(
"super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})",
trait_def_id, assoc_name
);
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),
};
let (generics, bounds) = match item.kind { let item = match tcx.hir().get(trait_hir_id) {
hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits), Node::Item(item) => item,
hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), _ => bug!("trait_node_id {} is not an item", trait_hir_id),
_ => 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 (generics, bounds) = match item.kind {
let self_param_ty = tcx.types.self_param; hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
let superbounds1 = if let Some(assoc_name) = assoc_name { hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
AstConv::compute_bounds_that_match_assoc_type( _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
&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); 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<Self>` would include `u32: PartialEq<Self>`
// 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),
);
// Convert any explicit superbounds in the where-clause, // Combine the two lists to form the complete set of superbounds:
// e.g., `trait Foo where Self: Bar`. let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
// In the case of trait aliases, however, we include all bounds in the where-clause,
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
// 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: // Now require that immediate supertraits are converted,
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); // which will, in turn, reach indirect supertraits.
for &(pred, span) in superbounds {
// Now require that immediate supertraits are converted, debug!("superbound: {:?}", pred);
// which will, in turn, reach indirect supertraits. if let ty::PredicateAtom::Trait(bound, _) = pred.skip_binders() {
if assoc_name.is_none() { tcx.at(span).super_predicates_of(bound.def_id());
// 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());
}
}
} }
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 { fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
......
...@@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>( ...@@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>(
let bounds = AstConv::compute_bounds( let bounds = AstConv::compute_bounds(
&ItemCtxt::new(tcx, assoc_item_def_id), &ItemCtxt::new(tcx, assoc_item_def_id),
item_ty, item_ty,
&bounds, bounds,
SizedByDefault::Yes, SizedByDefault::Yes,
span, span,
); );
...@@ -68,7 +68,7 @@ fn opaque_type_bounds<'tcx>( ...@@ -68,7 +68,7 @@ fn opaque_type_bounds<'tcx>(
let bounds = AstConv::compute_bounds( let bounds = AstConv::compute_bounds(
&ItemCtxt::new(tcx, opaque_def_id), &ItemCtxt::new(tcx, opaque_def_id),
item_ty, item_ty,
&bounds, bounds,
SizedByDefault::Yes, SizedByDefault::Yes,
span, span,
) )
......
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
// revisions: rpass1 cfail2 // revisions: rpass1 cfail2
#[cfg(rpass1)] #[cfg(rpass1)]
pub trait T2 {} pub trait T2 { }
#[cfg(cfail2)] #[cfg(cfail2)]
pub trait T2: T1 {} pub trait T2: T1 { }
//[cfail2]~^ ERROR cycle detected when computing the super predicates of `T2` //[cfail2]~^ ERROR cycle detected when computing the supertraits of `T2`
pub trait T1: T2 {} pub trait T1: T2 { }
fn main() {} fn main() { }
// ignore-tidy-linelength
trait Foo {
type Item;
}
trait Bar<T> {
type Item;
}
trait Baz: Foo + Bar<Self::Item> {}
//~^ ERROR cycle detected when computing the super traits of `Baz` with associated type name `Item` [E0391]
fn main() {}
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<Self::Item> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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<Self::Item> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.
// check-pass
trait Foo {
type Item;
}
trait Bar
where
Self: Foo,
{
}
#[allow(dead_code)]
fn foo<M>(_m: M)
where
M: Bar,
M::Item: Send,
{
}
fn main() {}
// check-pass
trait Foo<T> {}
trait Bar {
type A;
type B;
}
trait Baz: Bar<B = u32> + Foo<Self::A> {}
fn main() {}
#[allow(dead_code)]
fn foo<M>(_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() {}
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`.
// check-pass
trait Foo {
type Bar;
}
trait Qux: Foo + AsRef<Self::Bar> {}
trait Foo2 {}
trait Qux2: Foo2 + AsRef<Self::Bar> {
type Bar;
}
fn main() {}
// check-pass
// The goal of this test is to ensure that T: Bar<T::Item>
// in the where clause does not cycle
trait Foo {
type Item;
}
trait Bar<T> {}
fn baz<T>()
where
T: Foo,
T: Bar<T::Item>,
{
}
fn main() {}
// 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<Self::Bar>,
{
}
trait Foo2 {}
trait Qux2
where
Self: Foo2,
Self: AsRef<Self::Bar>,
{
type Bar;
}
fn main() {}
// 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<T>
where T : Trait,
T : Add<T::Item>
//~^ ERROR cycle detected
{
data: T
}
fn main() {
}
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<T::Item>
| ^^^^^^^
|
= 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<T::Item>
| ^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.
error[E0391]: cycle detected when computing the super predicates of `Chromosome` error[E0391]: cycle detected when computing the supertraits of `Chromosome`
--> $DIR/cycle-trait-supertrait-direct.rs:3:1
|
LL | trait Chromosome: Chromosome {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires computing the super traits of `Chromosome`...
--> $DIR/cycle-trait-supertrait-direct.rs:3:19 --> $DIR/cycle-trait-supertrait-direct.rs:3:19
| |
LL | trait Chromosome: Chromosome { 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 note: cycle used when collecting item types in top-level module
--> $DIR/cycle-trait-supertrait-direct.rs:3:1 --> $DIR/cycle-trait-supertrait-direct.rs:3:1
| |
......
error[E0391]: cycle detected when computing the super predicates of `B` error[E0391]: cycle detected when computing the supertraits of `B`
--> $DIR/cycle-trait-supertrait-indirect.rs:7:1
|
LL | trait B: C {
| ^^^^^^^^^^
|
note: ...which requires computing the super traits of `B`...
--> $DIR/cycle-trait-supertrait-indirect.rs:7:10 --> $DIR/cycle-trait-supertrait-indirect.rs:7:10
| |
LL | trait B: C { 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 supertraits of `C`...
| ^^^^^^^^^^
note: ...which requires computing the super traits of `C`...
--> $DIR/cycle-trait-supertrait-indirect.rs:11:10 --> $DIR/cycle-trait-supertrait-indirect.rs:11:10
| |
LL | trait C: B { } LL | trait C: B { }
| ^ | ^
= note: ...which again requires computing the super predicates of `B`, completing the cycle = note: ...which again requires computing the supertraits of `B`, completing the cycle
note: cycle used when computing the super traits of `A` note: cycle used when computing the supertraits of `A`
--> $DIR/cycle-trait-supertrait-indirect.rs:4:10 --> $DIR/cycle-trait-supertrait-indirect.rs:4:10
| |
LL | trait A: B { LL | trait A: B {
......
error[E0391]: cycle detected when computing the super predicates of `T1` error[E0391]: cycle detected when computing the supertraits of `T1`
--> $DIR/issue-12511.rs:1:1
|
LL | trait T1 : T2 {
| ^^^^^^^^^^^^^
|
note: ...which requires computing the super traits of `T1`...
--> $DIR/issue-12511.rs:1:12 --> $DIR/issue-12511.rs:1:12
| |
LL | trait T1 : T2 { 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 supertraits of `T2`...
| ^^^^^^^^^^^^^
note: ...which requires computing the super traits of `T2`...
--> $DIR/issue-12511.rs:5:12 --> $DIR/issue-12511.rs:5:12
| |
LL | trait T2 : T1 { 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 note: cycle used when collecting item types in top-level module
--> $DIR/issue-12511.rs:1:1 --> $DIR/issue-12511.rs:1:1
| |
......
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 --> $DIR/issue-20772.rs:1:1
| |
LL | / trait T : Iterator<Item=Self::Item> LL | / trait T : Iterator<Item=Self::Item>
...@@ -6,8 +6,8 @@ LL | | ...@@ -6,8 +6,8 @@ LL | |
LL | | {} LL | | {}
| |__^ | |__^
| |
= note: ...which again requires computing the super traits of `T` with associated type name `Item`, completing the cycle = note: ...which again requires computing the supertraits of `T`, completing the cycle
note: cycle used when computing the super traits of `T` note: cycle used when collecting item types in top-level module
--> $DIR/issue-20772.rs:1:1 --> $DIR/issue-20772.rs:1:1
| |
LL | / trait T : Iterator<Item=Self::Item> LL | / trait T : Iterator<Item=Self::Item>
......
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 --> $DIR/issue-20825.rs:5:1
| |
LL | pub trait Processor: Subscriber<Input = Self::Input> { LL | pub trait Processor: Subscriber<Input = Self::Input> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: ...which again requires computing the super traits of `Processor` with associated type name `Input`, completing the cycle = note: ...which again requires computing the supertraits of `Processor`, completing the cycle
note: cycle used when computing the super traits of `Processor` note: cycle used when collecting item types in top-level module
--> $DIR/issue-20825.rs:5:1 --> $DIR/issue-20825.rs:5:1
| |
LL | pub trait Processor: Subscriber<Input = Self::Input> { LL | pub trait Processor: Subscriber<Input = Self::Input> {
......
// check-pass trait Expr : PartialEq<Self::Item> {
//~^ ERROR: cycle detected
trait Expr: PartialEq<Self::Item> {
type Item; type Item;
} }
......
error[E0391]: cycle detected when computing the supertraits of `Expr`
--> $DIR/issue-22673.rs:1:1
|
LL | trait Expr : PartialEq<Self::Item> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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<Self::Item> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册