mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
even more unify Projection/Opaque in outlives code
This commit is contained in:
parent
65d2f2a5f9
commit
a7a842027c
@ -359,9 +359,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
.insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
|
||||
}
|
||||
|
||||
OutlivesBound::RegionSubAlias(r_a, kind, alias_b) => {
|
||||
OutlivesBound::RegionSubAlias(r_a, alias_b) => {
|
||||
self.region_bound_pairs
|
||||
.insert(ty::OutlivesPredicate(GenericKind::Alias(kind, alias_b), r_a));
|
||||
.insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
|
||||
.or_insert(span);
|
||||
}
|
||||
|
||||
Component::Alias(kind, alias) => {
|
||||
Component::Alias(alias_ty) => {
|
||||
// This would either arise from something like:
|
||||
//
|
||||
// ```
|
||||
@ -99,13 +99,13 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
|
||||
//
|
||||
// Here we want to add an explicit `where <T as Iterator>::Item: 'a`
|
||||
// or `Opaque<T>: 'a` depending on the alias kind.
|
||||
let ty: Ty<'tcx> = tcx.mk_ty(ty::Alias(kind, alias));
|
||||
let ty = alias_ty.to_ty(tcx);
|
||||
required_predicates
|
||||
.entry(ty::OutlivesPredicate(ty.into(), outlived_region))
|
||||
.or_insert(span);
|
||||
}
|
||||
|
||||
Component::EscapingProjection(_) => {
|
||||
Component::EscapingAlias(_) => {
|
||||
// As above, but the projection involves
|
||||
// late-bound regions. Therefore, the WF
|
||||
// requirement is not checked in type definition
|
||||
|
@ -2272,13 +2272,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
|
||||
let labeled_user_string = match bound_kind {
|
||||
GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
|
||||
GenericKind::Alias(ty::Projection, ref p) => format!("the associated type `{}`", p),
|
||||
GenericKind::Alias(ty::Opaque, ref p) => {
|
||||
format!(
|
||||
"the opaque type `{}`",
|
||||
self.tcx.def_path_str_with_substs(p.def_id, p.substs)
|
||||
)
|
||||
}
|
||||
GenericKind::Alias(ref p) => match p.kind(self.tcx) {
|
||||
ty::AliasKind::Projection => format!("the associated type `{}`", p),
|
||||
ty::AliasKind::Opaque => format!("the opaque type `{}`", p),
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(SubregionOrigin::CompareImplItemObligation {
|
||||
|
@ -22,7 +22,7 @@ pub enum Component<'tcx> {
|
||||
// is not in a position to judge which is the best technique, so
|
||||
// we just product the projection as a component and leave it to
|
||||
// the consumer to decide (but see `EscapingProjection` below).
|
||||
Alias(ty::AliasKind, ty::AliasTy<'tcx>),
|
||||
Alias(ty::AliasTy<'tcx>),
|
||||
|
||||
// In the case where a projection has escaping regions -- meaning
|
||||
// regions bound within the type itself -- we always use
|
||||
@ -44,7 +44,7 @@ pub enum Component<'tcx> {
|
||||
// projection, so that implied bounds code can avoid relying on
|
||||
// them. This gives us room to improve the regionck reasoning in
|
||||
// the future without breaking backwards compat.
|
||||
EscapingProjection(Vec<Component<'tcx>>),
|
||||
EscapingAlias(Vec<Component<'tcx>>),
|
||||
}
|
||||
|
||||
/// Push onto `out` all the things that must outlive `'a` for the condition
|
||||
@ -120,17 +120,6 @@ fn compute_components<'tcx>(
|
||||
out.push(Component::Param(p));
|
||||
}
|
||||
|
||||
// Ignore lifetimes found in opaque types. Opaque types can
|
||||
// have lifetimes in their substs which their hidden type doesn't
|
||||
// actually use. If we inferred that an opaque type is outlived by
|
||||
// its parameter lifetimes, then we could prove that any lifetime
|
||||
// outlives any other lifetime, which is unsound.
|
||||
// See https://github.com/rust-lang/rust/issues/84305 for
|
||||
// more details.
|
||||
ty::Alias(ty::Opaque, data) => {
|
||||
out.push(Component::Alias(ty::Opaque, data));
|
||||
},
|
||||
|
||||
// For projections, we prefer to generate an obligation like
|
||||
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
|
||||
// regionck more ways to prove that it holds. However,
|
||||
@ -139,15 +128,15 @@ fn compute_components<'tcx>(
|
||||
// trait-ref. Therefore, if we see any higher-ranked regions,
|
||||
// we simply fallback to the most restrictive rule, which
|
||||
// requires that `Pi: 'a` for all `i`.
|
||||
ty::Alias(ty::Projection, data) => {
|
||||
if !data.has_escaping_bound_vars() {
|
||||
ty::Alias(_, alias_ty) => {
|
||||
if !alias_ty.has_escaping_bound_vars() {
|
||||
// best case: no escaping regions, so push the
|
||||
// projection and skip the subtree (thus generating no
|
||||
// constraints for Pi). This defers the choice between
|
||||
// the rules OutlivesProjectionEnv,
|
||||
// OutlivesProjectionTraitDef, and
|
||||
// OutlivesProjectionComponents to regionck.
|
||||
out.push(Component::Alias(ty::Projection, data));
|
||||
out.push(Component::Alias(alias_ty));
|
||||
} else {
|
||||
// fallback case: hard code
|
||||
// OutlivesProjectionComponents. Continue walking
|
||||
@ -155,7 +144,7 @@ fn compute_components<'tcx>(
|
||||
let mut subcomponents = smallvec![];
|
||||
let mut subvisited = SsoHashSet::new();
|
||||
compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
|
||||
out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
|
||||
out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,9 +138,9 @@ impl<'tcx> OutlivesEnvironmentBuilder<'tcx> {
|
||||
self.region_bound_pairs
|
||||
.insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
|
||||
}
|
||||
OutlivesBound::RegionSubAlias(r_a, kind, projection_b) => {
|
||||
OutlivesBound::RegionSubAlias(r_a, alias_b) => {
|
||||
self.region_bound_pairs
|
||||
.insert(ty::OutlivesPredicate(GenericKind::Alias(kind, projection_b), r_a));
|
||||
.insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
|
||||
}
|
||||
OutlivesBound::RegionSubRegion(r_a, r_b) => {
|
||||
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {
|
||||
|
@ -67,7 +67,6 @@ use crate::infer::{
|
||||
};
|
||||
use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable};
|
||||
@ -266,10 +265,8 @@ where
|
||||
Component::Param(param_ty) => {
|
||||
self.param_ty_must_outlive(origin, region, *param_ty);
|
||||
}
|
||||
Component::Alias(kind, data) => {
|
||||
self.alias_must_outlive(*kind, *data, origin, region)
|
||||
}
|
||||
Component::EscapingProjection(subcomponents) => {
|
||||
Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty),
|
||||
Component::EscapingAlias(subcomponents) => {
|
||||
self.components_must_outlive(origin, &subcomponents, region, category);
|
||||
}
|
||||
Component::UnresolvedInferenceVariable(v) => {
|
||||
@ -285,61 +282,26 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn param_ty_must_outlive(
|
||||
&mut self,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
param_ty: ty::ParamTy,
|
||||
) {
|
||||
debug!(
|
||||
"param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})",
|
||||
region, param_ty, origin
|
||||
);
|
||||
|
||||
let generic = GenericKind::Param(param_ty);
|
||||
let verify_bound = self.verify_bound.param_bound(param_ty);
|
||||
self.delegate.push_verify(origin, generic, region, verify_bound);
|
||||
self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound);
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn alias_must_outlive(
|
||||
&mut self,
|
||||
kind: ty::AliasKind,
|
||||
data: ty::AliasTy<'tcx>,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
) {
|
||||
self.generic_must_outlive(
|
||||
origin,
|
||||
region,
|
||||
GenericKind::Alias(kind, data),
|
||||
data.def_id,
|
||||
data.substs,
|
||||
kind == ty::Opaque,
|
||||
|ty| match *ty.kind() {
|
||||
ty::Alias(filter_kind, ty::AliasTy { def_id, substs, .. })
|
||||
if kind == filter_kind =>
|
||||
{
|
||||
(def_id, substs)
|
||||
}
|
||||
_ => bug!("expected only projection types from env, not {:?}", ty),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, filter))]
|
||||
fn generic_must_outlive(
|
||||
fn alias_ty_must_outlive(
|
||||
&mut self,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
generic: GenericKind<'tcx>,
|
||||
def_id: DefId,
|
||||
substs: SubstsRef<'tcx>,
|
||||
is_opaque: bool,
|
||||
filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>),
|
||||
alias_ty: ty::AliasTy<'tcx>,
|
||||
) {
|
||||
// An optimization for a common case with opaque types.
|
||||
if substs.is_empty() {
|
||||
if alias_ty.substs.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -361,14 +323,14 @@ where
|
||||
// These are guaranteed to apply, no matter the inference
|
||||
// results.
|
||||
let trait_bounds: Vec<_> =
|
||||
self.verify_bound.declared_region_bounds(def_id, substs).collect();
|
||||
self.verify_bound.declared_bounds_from_definition(alias_ty).collect();
|
||||
|
||||
debug!(?trait_bounds);
|
||||
|
||||
// Compute the bounds we can derive from the environment. This
|
||||
// is an "approximate" match -- in some cases, these bounds
|
||||
// may not apply.
|
||||
let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(generic);
|
||||
let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty);
|
||||
debug!(?approx_env_bounds);
|
||||
|
||||
// Remove outlives bounds that we get from the environment but
|
||||
@ -383,8 +345,8 @@ where
|
||||
// If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait`
|
||||
// will be invoked with `['b => ^1]` and so we will get `^1` returned.
|
||||
let bound = bound_outlives.skip_binder();
|
||||
let (def_id, substs) = filter(bound.0);
|
||||
self.verify_bound.declared_region_bounds(def_id, substs).all(|r| r != bound.1)
|
||||
let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") };
|
||||
self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1)
|
||||
});
|
||||
|
||||
// If declared bounds list is empty, the only applicable rule is
|
||||
@ -401,12 +363,12 @@ where
|
||||
// the problem is to add `T: 'r`, which isn't true. So, if there are no
|
||||
// inference variables, we use a verify constraint instead of adding
|
||||
// edges, which winds up enforcing the same condition.
|
||||
let needs_infer = substs.needs_infer();
|
||||
if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) {
|
||||
if approx_env_bounds.is_empty()
|
||||
&& trait_bounds.is_empty()
|
||||
&& (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
|
||||
{
|
||||
debug!("no declared bounds");
|
||||
|
||||
self.substs_must_outlive(substs, origin, region);
|
||||
|
||||
self.substs_must_outlive(alias_ty.substs, origin, region);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -447,14 +409,9 @@ where
|
||||
// projection outlive; in some cases, this may add insufficient
|
||||
// edges into the inference graph, leading to inference failures
|
||||
// even though a satisfactory solution exists.
|
||||
let verify_bound = self.verify_bound.projection_opaque_bounds(
|
||||
generic,
|
||||
def_id,
|
||||
substs,
|
||||
&mut Default::default(),
|
||||
);
|
||||
debug!("projection_must_outlive: pushing {:?}", verify_bound);
|
||||
self.delegate.push_verify(origin, generic, region, verify_bound);
|
||||
let verify_bound = self.verify_bound.alias_bound(alias_ty, &mut Default::default());
|
||||
debug!("alias_must_outlive: pushing {:?}", verify_bound);
|
||||
self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
|
||||
}
|
||||
|
||||
fn substs_must_outlive(
|
||||
|
@ -1,11 +1,10 @@
|
||||
use crate::infer::outlives::components::{compute_components_recursive, Component};
|
||||
use crate::infer::outlives::env::RegionBoundPairs;
|
||||
use crate::infer::region_constraints::VerifyIfEq;
|
||||
use crate::infer::{GenericKind, VerifyBound};
|
||||
use crate::infer::VerifyBound;
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::GenericArg;
|
||||
use rustc_middle::ty::{self, OutlivesPredicate, SubstsRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
|
||||
|
||||
use smallvec::smallvec;
|
||||
|
||||
@ -94,29 +93,26 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||
/// this list.
|
||||
pub fn approx_declared_bounds_from_env(
|
||||
&self,
|
||||
generic: GenericKind<'tcx>,
|
||||
alias_ty: ty::AliasTy<'tcx>,
|
||||
) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
|
||||
let projection_ty = generic.to_ty(self.tcx);
|
||||
let erased_projection_ty = self.tcx.erase_regions(projection_ty);
|
||||
self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty)
|
||||
let erased_alias_ty = self.tcx.erase_regions(alias_ty.to_ty(self.tcx));
|
||||
self.declared_generic_bounds_from_env_for_erased_ty(erased_alias_ty)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, visited))]
|
||||
pub fn projection_opaque_bounds(
|
||||
pub fn alias_bound(
|
||||
&self,
|
||||
generic: GenericKind<'tcx>,
|
||||
def_id: DefId,
|
||||
substs: SubstsRef<'tcx>,
|
||||
alias_ty: ty::AliasTy<'tcx>,
|
||||
visited: &mut SsoHashSet<GenericArg<'tcx>>,
|
||||
) -> VerifyBound<'tcx> {
|
||||
let generic_ty = generic.to_ty(self.tcx);
|
||||
let alias_ty_as_ty = alias_ty.to_ty(self.tcx);
|
||||
|
||||
// Search the env for where clauses like `P: 'a`.
|
||||
let projection_opaque_bounds = self
|
||||
.approx_declared_bounds_from_env(generic)
|
||||
let env_bounds = self
|
||||
.approx_declared_bounds_from_env(alias_ty)
|
||||
.into_iter()
|
||||
.map(|binder| {
|
||||
if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == generic_ty {
|
||||
if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == alias_ty_as_ty {
|
||||
// Micro-optimize if this is an exact match (this
|
||||
// occurs often when there are no region variables
|
||||
// involved).
|
||||
@ -126,19 +122,19 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||
VerifyBound::IfEq(verify_if_eq_b)
|
||||
}
|
||||
});
|
||||
// Extend with bounds that we can find from the trait.
|
||||
let trait_bounds =
|
||||
self.declared_region_bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r));
|
||||
|
||||
// Extend with bounds that we can find from the definition.
|
||||
let definition_bounds =
|
||||
self.declared_bounds_from_definition(alias_ty).map(|r| VerifyBound::OutlivedBy(r));
|
||||
|
||||
// see the extensive comment in projection_must_outlive
|
||||
let recursive_bound = {
|
||||
let mut components = smallvec![];
|
||||
compute_components_recursive(self.tcx, generic_ty.into(), &mut components, visited);
|
||||
compute_components_recursive(self.tcx, alias_ty_as_ty.into(), &mut components, visited);
|
||||
self.bound_from_components(&components, visited)
|
||||
};
|
||||
|
||||
VerifyBound::AnyBound(projection_opaque_bounds.chain(trait_bounds).collect())
|
||||
.or(recursive_bound)
|
||||
VerifyBound::AnyBound(env_bounds.chain(definition_bounds).collect()).or(recursive_bound)
|
||||
}
|
||||
|
||||
fn bound_from_components(
|
||||
@ -149,10 +145,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||
let mut bounds = components
|
||||
.iter()
|
||||
.map(|component| self.bound_from_single_component(component, visited))
|
||||
.filter(|bound| {
|
||||
// Remove bounds that must hold, since they are not interesting.
|
||||
!bound.must_hold()
|
||||
});
|
||||
// Remove bounds that must hold, since they are not interesting.
|
||||
.filter(|bound| !bound.must_hold());
|
||||
|
||||
match (bounds.next(), bounds.next()) {
|
||||
(Some(first), None) => first,
|
||||
@ -170,13 +164,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||
match *component {
|
||||
Component::Region(lt) => VerifyBound::OutlivedBy(lt),
|
||||
Component::Param(param_ty) => self.param_bound(param_ty),
|
||||
Component::Alias(kind, data) => self.projection_opaque_bounds(
|
||||
GenericKind::Alias(kind, data),
|
||||
data.def_id,
|
||||
data.substs,
|
||||
visited,
|
||||
),
|
||||
Component::EscapingProjection(ref components) => {
|
||||
Component::Alias(alias_ty) => self.alias_bound(alias_ty, visited),
|
||||
Component::EscapingAlias(ref components) => {
|
||||
self.bound_from_components(components, visited)
|
||||
}
|
||||
Component::UnresolvedInferenceVariable(v) => {
|
||||
@ -292,16 +281,15 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||
///
|
||||
/// This is for simplicity, and because we are not really smart
|
||||
/// enough to cope with such bounds anywhere.
|
||||
pub fn declared_region_bounds(
|
||||
pub fn declared_bounds_from_definition(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
substs: SubstsRef<'tcx>,
|
||||
alias_ty: ty::AliasTy<'tcx>,
|
||||
) -> impl Iterator<Item = ty::Region<'tcx>> {
|
||||
let tcx = self.tcx;
|
||||
let bounds = tcx.item_bounds(def_id);
|
||||
let bounds = tcx.item_bounds(alias_ty.def_id);
|
||||
trace!("{:#?}", bounds.0);
|
||||
bounds
|
||||
.subst_iter(tcx, substs)
|
||||
.subst_iter(tcx, alias_ty.substs)
|
||||
.filter_map(|p| p.to_opt_type_outlives())
|
||||
.filter_map(|p| p.no_bound_vars())
|
||||
.map(|OutlivesPredicate(_, r)| r)
|
||||
|
@ -167,7 +167,7 @@ pub struct Verify<'tcx> {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
|
||||
pub enum GenericKind<'tcx> {
|
||||
Param(ty::ParamTy),
|
||||
Alias(ty::AliasKind, ty::AliasTy<'tcx>),
|
||||
Alias(ty::AliasTy<'tcx>),
|
||||
}
|
||||
|
||||
/// Describes the things that some `GenericKind` value `G` is known to
|
||||
@ -746,10 +746,7 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
GenericKind::Param(ref p) => write!(f, "{:?}", p),
|
||||
GenericKind::Alias(ty::Projection, ref p) => write!(f, "{:?}", p),
|
||||
GenericKind::Alias(ty::Opaque, ref p) => ty::tls::with(|tcx| {
|
||||
write!(f, "{}", tcx.def_path_str_with_substs(p.def_id, tcx.lift(p.substs).unwrap()))
|
||||
}),
|
||||
GenericKind::Alias(ref p) => write!(f, "{:?}", p),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -758,10 +755,7 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
GenericKind::Param(ref p) => write!(f, "{}", p),
|
||||
GenericKind::Alias(ty::Projection, ref p) => write!(f, "{}", p),
|
||||
GenericKind::Alias(ty::Opaque, ref p) => ty::tls::with(|tcx| {
|
||||
write!(f, "{}", tcx.def_path_str_with_substs(p.def_id, tcx.lift(p.substs).unwrap()))
|
||||
}),
|
||||
GenericKind::Alias(ref p) => write!(f, "{}", p),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -770,7 +764,7 @@ impl<'tcx> GenericKind<'tcx> {
|
||||
pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
match *self {
|
||||
GenericKind::Param(ref p) => p.to_ty(tcx),
|
||||
GenericKind::Alias(kind, data) => tcx.mk_ty(ty::Alias(kind, data)),
|
||||
GenericKind::Alias(ref p) => p.to_ty(tcx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -261,14 +261,15 @@ impl<'tcx> Elaborator<'tcx> {
|
||||
|
||||
Component::UnresolvedInferenceVariable(_) => None,
|
||||
|
||||
Component::Alias(kind, data) => {
|
||||
let ty = tcx.mk_ty(ty::Alias(kind, data));
|
||||
Component::Alias(alias_ty) => {
|
||||
// We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
|
||||
// With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
|
||||
Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
|
||||
ty::OutlivesPredicate(ty, r_min),
|
||||
ty::OutlivesPredicate(alias_ty.to_ty(tcx), r_min),
|
||||
)))
|
||||
}
|
||||
|
||||
Component::EscapingProjection(_) => {
|
||||
Component::EscapingAlias(_) => {
|
||||
// We might be able to do more here, but we don't
|
||||
// want to deal with escaping vars right now.
|
||||
None
|
||||
|
@ -213,5 +213,5 @@ pub struct NormalizationResult<'tcx> {
|
||||
pub enum OutlivesBound<'tcx> {
|
||||
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
|
||||
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
|
||||
RegionSubAlias(ty::Region<'tcx>, ty::AliasKind, ty::AliasTy<'tcx>),
|
||||
RegionSubAlias(ty::Region<'tcx>, ty::AliasTy<'tcx>),
|
||||
}
|
||||
|
@ -1245,11 +1245,26 @@ pub struct AliasTy<'tcx> {
|
||||
/// aka. `tcx.parent(def_id)`.
|
||||
pub def_id: DefId,
|
||||
|
||||
/// This field exists to prevent the creation of `ProjectionTy` without using
|
||||
/// This field exists to prevent the creation of `AliasTy` without using
|
||||
/// [TyCtxt::mk_alias_ty].
|
||||
pub(super) _use_mk_alias_ty_instead: (),
|
||||
}
|
||||
|
||||
impl<'tcx> AliasTy<'tcx> {
|
||||
pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
|
||||
match tcx.def_kind(self.def_id) {
|
||||
DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
|
||||
DefKind::OpaqueTy => ty::Opaque,
|
||||
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
tcx.mk_ty(ty::Alias(self.kind(tcx), self))
|
||||
}
|
||||
}
|
||||
|
||||
/// The following methods work only with associated type projections.
|
||||
impl<'tcx> AliasTy<'tcx> {
|
||||
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
match tcx.def_kind(self.def_id) {
|
||||
@ -1257,7 +1272,7 @@ impl<'tcx> AliasTy<'tcx> {
|
||||
DefKind::ImplTraitPlaceholder => {
|
||||
tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
|
||||
}
|
||||
kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
|
||||
kind => bug!("expected a projection AliasTy; found {kind:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,10 +154,8 @@ fn implied_bounds_from_components<'tcx>(
|
||||
match component {
|
||||
Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
|
||||
Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
|
||||
Component::Alias(kind, p) => {
|
||||
Some(OutlivesBound::RegionSubAlias(sub_region, kind, p))
|
||||
}
|
||||
Component::EscapingProjection(_) =>
|
||||
Component::Alias(p) => Some(OutlivesBound::RegionSubAlias(sub_region, p)),
|
||||
Component::EscapingAlias(_) =>
|
||||
// If the projection has escaping regions, don't
|
||||
// try to infer any implied bounds even for its
|
||||
// free components. This is conservative, because
|
||||
|
Loading…
Reference in New Issue
Block a user