From a7a842027cfdd7ede4d44349d4c15a6b71935fa0 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sun, 15 Jan 2023 19:38:31 +0300 Subject: [PATCH 1/2] even more unify Projection/Opaque in outlives code --- .../src/type_check/free_region_relations.rs | 4 +- .../rustc_hir_analysis/src/outlives/utils.rs | 6 +- .../src/infer/error_reporting/mod.rs | 11 +-- .../src/infer/outlives/components.rs | 23 ++---- .../rustc_infer/src/infer/outlives/env.rs | 4 +- .../src/infer/outlives/obligations.rs | 81 +++++-------------- .../rustc_infer/src/infer/outlives/verify.rs | 62 ++++++-------- .../src/infer/region_constraints/mod.rs | 14 +--- compiler/rustc_infer/src/traits/util.rs | 9 ++- compiler/rustc_middle/src/traits/query.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 19 ++++- .../src/implied_outlives_bounds.rs | 6 +- 12 files changed, 90 insertions(+), 151 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 9cf4d8cdf7db4..82ff862479e81 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -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)); } } } diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index 3f691beec3116..9459c5f54abbf 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -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 ::Item: 'a` // or `Opaque: '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 diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 9c38eb6163f56..28fd03b878b2b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -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 { diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 37907d289a84e..3d86279b03cc6 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -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>), + EscapingAlias(Vec>), } /// 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 // `>::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())); } } diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 52c3d97f24111..24e3c34dd94fc 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -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()) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 77de335e7f547..0194549a8868d 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -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( + fn alias_ty_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( - &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( diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 56695a87b7c05..94de9bc2d0228 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -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::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>, ) -> 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> { 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) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index fda5ffe784678..0428481b7ff02 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -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), } } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 4ada7b22d084c..cd5bde2a79130 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -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<::Assoc>: 'a`. + // With this, we can deduce that `::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 diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 2a68315fefc56..615154a55e586 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -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>), } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index a128e9025fd69..6a7b23e40a779 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -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:?}"), } } diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index d457a4a2beaf5..7d2d8433c932d 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -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 From e40567b2cf50c4694c75b1ac34aff6108e529700 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Mon, 16 Jan 2023 01:35:51 +0300 Subject: [PATCH 2/2] add test for ICE fix --- .../outlives-bound-var.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/outlives-bound-var.rs diff --git a/tests/ui/type-alias-impl-trait/outlives-bound-var.rs b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs new file mode 100644 index 0000000000000..b8fac45b76db7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs @@ -0,0 +1,18 @@ +// Here we process outlive obligations involving +// opaque types with bound vars in substs. +// This was an ICE. +// +// check-pass +#![feature(type_alias_impl_trait)] + +type Ty<'a> = impl Sized + 'a; +fn define<'a>() -> Ty<'a> {} + +// Ty<'^0>: 'static +fn test1(_: &'static fn(Ty<'_>)) {} + +fn test2() { + None::<&fn(Ty<'_>)>; +} + +fn main() { }