Revert "Auto merge of #79637 - spastorino:revert-trait-inheritance-self, r=Mark-Simulacrum"
This reverts commitb4def89d76
, reversing changes made to7dc1e852d4
.
This commit is contained in:
parent
23adf9fd84
commit
7aa602b84c
28 changed files with 500 additions and 152 deletions
|
@ -49,9 +49,10 @@ 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`. This is a
|
||||
/// subset of the full set of predicates.
|
||||
/// Returns predicates in scope of the form `X: Foo<T>`, 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.
|
||||
///
|
||||
/// This is used for one specific purpose: resolving "short-hand"
|
||||
/// associated type references like `T::Item`. In principle, we
|
||||
|
@ -60,7 +61,12 @@ 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) -> ty::GenericPredicates<'tcx>;
|
||||
fn get_type_parameter_bounds(
|
||||
&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).
|
||||
fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
|
||||
|
@ -792,7 +798,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.
|
||||
|
@ -850,7 +856,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();
|
||||
|
@ -865,7 +871,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
|
||||
|
@ -896,6 +902,42 @@ 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();
|
||||
|
||||
|
@ -1098,7 +1140,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// parameter to have a skipped binder.
|
||||
let param_ty =
|
||||
tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs);
|
||||
self.add_bounds(param_ty, ast_bounds, bounds);
|
||||
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
|
||||
self.add_bounds(param_ty, &ast_bounds, bounds);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -1413,8 +1456,9 @@ 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()).predicates;
|
||||
let predicates = &self
|
||||
.get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name)
|
||||
.predicates;
|
||||
|
||||
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
|
||||
|
||||
|
@ -1422,12 +1466,14 @@ 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(
|
||||
traits::transitive_bounds_that_define_assoc_type(
|
||||
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,
|
||||
|
|
|
@ -20,6 +20,7 @@ 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};
|
||||
|
||||
|
@ -183,7 +184,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
|
||||
fn get_type_parameter_bounds(
|
||||
&self,
|
||||
_: Span,
|
||||
def_id: DefId,
|
||||
_: Ident,
|
||||
) -> 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);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// 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
|
||||
|
@ -77,6 +78,7 @@ 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,
|
||||
|
@ -308,8 +310,17 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
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 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 re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
|
||||
|
@ -490,7 +501,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): (DefId, LocalDefId),
|
||||
(item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
|
||||
) -> ty::GenericPredicates<'_> {
|
||||
use rustc_hir::*;
|
||||
|
||||
|
@ -515,7 +526,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())
|
||||
icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let mut extend = None;
|
||||
|
@ -558,12 +569,18 @@ 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))
|
||||
.into_iter()
|
||||
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
|
||||
_ => false,
|
||||
}),
|
||||
icx.type_parameter_bounds_in_generics(
|
||||
ast_generics,
|
||||
param_id,
|
||||
ty,
|
||||
OnlySelfBounds(true),
|
||||
Some(assoc_name),
|
||||
)
|
||||
.into_iter()
|
||||
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
|
||||
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));
|
||||
|
@ -581,6 +598,7 @@ impl ItemCtxt<'tcx> {
|
|||
param_id: hir::HirId,
|
||||
ty: Ty<'tcx>,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
assoc_name: Option<Ident>,
|
||||
) -> Vec<(ty::Predicate<'tcx>, Span)> {
|
||||
let constness = self.default_constness_for_trait_bounds();
|
||||
let from_ty_params = ast_generics
|
||||
|
@ -591,6 +609,10 @@ 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
|
||||
|
@ -609,12 +631,34 @@ impl ItemCtxt<'tcx> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
|
||||
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)))
|
||||
})
|
||||
.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
|
||||
|
@ -983,54 +1027,91 @@ 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);
|
||||
let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
|
||||
tcx.super_predicates_that_define_assoc_type((trait_def_id, None))
|
||||
}
|
||||
|
||||
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<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),
|
||||
/// 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());
|
||||
|
||||
// Combine the two lists to form the complete set of superbounds:
|
||||
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
|
||||
let item = match tcx.hir().get(trait_hir_id) {
|
||||
Node::Item(item) => item,
|
||||
_ => bug!("trait_node_id {} is not an item", trait_hir_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::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
|
||||
tcx.at(span).super_predicates_of(bound.def_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 = 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<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:
|
||||
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() {
|
||||
// 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::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
|
||||
tcx.at(span).super_predicates_of(bound.def_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::GenericPredicates { parent: None, predicates: superbounds }
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
@ -69,7 +69,7 @@ fn opaque_type_bounds<'tcx>(
|
|||
let bounds = AstConv::compute_bounds(
|
||||
&ItemCtxt::new(tcx, opaque_def_id),
|
||||
item_ty,
|
||||
bounds,
|
||||
&bounds,
|
||||
SizedByDefault::Yes,
|
||||
span,
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue