Introduce expand_weak_alias_tys
This commit is contained in:
parent
05ce209d20
commit
515d805a0e
13 changed files with 165 additions and 41 deletions
|
@ -181,9 +181,10 @@ impl FlagComputation {
|
|||
|
||||
&ty::Alias(kind, data) => {
|
||||
self.add_flags(match kind {
|
||||
ty::Weak | ty::Projection => TypeFlags::HAS_TY_PROJECTION,
|
||||
ty::Inherent => TypeFlags::HAS_TY_INHERENT,
|
||||
ty::Projection => TypeFlags::HAS_TY_PROJECTION,
|
||||
ty::Weak => TypeFlags::HAS_TY_WEAK,
|
||||
ty::Opaque => TypeFlags::HAS_TY_OPAQUE,
|
||||
ty::Inherent => TypeFlags::HAS_TY_INHERENT,
|
||||
});
|
||||
|
||||
self.add_alias_ty(data);
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::ty::{GenericArgKind, GenericArgsRef};
|
|||
use rustc_apfloat::Float as _;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
|
@ -867,6 +868,30 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
self.mk_args_from_iter(args.into_iter().map(|arg| arg.into()).chain(opt_const_param))
|
||||
}
|
||||
|
||||
/// Expand any [weak alias types][weak] contained within the given `value`.
|
||||
///
|
||||
/// This should be used over other normalization routines in situations where
|
||||
/// it's important not to normalize other alias types and where the predicates
|
||||
/// on the corresponding type alias shouldn't be taken into consideration.
|
||||
///
|
||||
/// Whenever possible **prefer not to use this function**! Instead, use standard
|
||||
/// normalization routines or if feasible don't normalize at all.
|
||||
///
|
||||
/// This function comes in handy if you want to mimic the behavior of eager
|
||||
/// type alias expansion in a localized manner.
|
||||
///
|
||||
/// <div class="warning">
|
||||
/// This delays a bug on overflow! Therefore you need to be certain that the
|
||||
/// contained types get fully normalized at a later stage. Note that even on
|
||||
/// overflow all well-behaved weak alias types get expanded correctly, so the
|
||||
/// result is still useful.
|
||||
/// </div>
|
||||
///
|
||||
/// [weak]: ty::Weak
|
||||
pub fn expand_weak_alias_tys<T: TypeFoldable<TyCtxt<'tcx>>>(self, value: T) -> T {
|
||||
value.fold_with(&mut WeakAliasTypeExpander { tcx: self, depth: 0 })
|
||||
}
|
||||
}
|
||||
|
||||
struct OpaqueTypeExpander<'tcx> {
|
||||
|
@ -1002,6 +1027,42 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct WeakAliasTypeExpander<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
depth: usize,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for WeakAliasTypeExpander<'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !ty.has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
|
||||
return ty;
|
||||
}
|
||||
let ty::Alias(ty::Weak, alias) = ty.kind() else {
|
||||
return ty.super_fold_with(self);
|
||||
};
|
||||
if !self.tcx.recursion_limit().value_within_limit(self.depth) {
|
||||
let guar = self.tcx.dcx().delayed_bug("overflow expanding weak alias type");
|
||||
return Ty::new_error(self.tcx, guar);
|
||||
}
|
||||
|
||||
self.depth += 1;
|
||||
ensure_sufficient_stack(|| {
|
||||
self.tcx.type_of(alias.def_id).instantiate(self.tcx, alias.args).fold_with(self)
|
||||
})
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
if !ct.ty().has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
|
||||
return ct;
|
||||
}
|
||||
ct.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Ty<'tcx> {
|
||||
/// Returns the `Size` for primitive types (bool, uint, int, char, float).
|
||||
pub fn primitive_size(self, tcx: TyCtxt<'tcx>) -> Size {
|
||||
|
|
|
@ -131,12 +131,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
fn collect_late_bound_regions<T>(
|
||||
self,
|
||||
value: &Binder<'tcx, T>,
|
||||
just_constraint: bool,
|
||||
just_constrained: bool,
|
||||
) -> FxHashSet<ty::BoundRegionKind>
|
||||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let mut collector = LateBoundRegionsCollector::new(just_constraint);
|
||||
let mut collector = LateBoundRegionsCollector::new(self, just_constrained);
|
||||
let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value };
|
||||
let result = value.as_ref().skip_binder().visit_with(&mut collector);
|
||||
assert!(result.is_continue()); // should never have stopped early
|
||||
collector.regions
|
||||
|
@ -258,11 +259,7 @@ struct LateBoundRegionsCollector {
|
|||
|
||||
impl LateBoundRegionsCollector {
|
||||
fn new(just_constrained: bool) -> Self {
|
||||
LateBoundRegionsCollector {
|
||||
current_index: ty::INNERMOST,
|
||||
regions: Default::default(),
|
||||
just_constrained,
|
||||
}
|
||||
Self { current_index: ty::INNERMOST, regions: Default::default(), just_constrained }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,12 +275,16 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
|
|||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// if we are only looking for "constrained" region, we have to
|
||||
// ignore the inputs to a projection, as they may not appear
|
||||
// in the normalized form
|
||||
if self.just_constrained {
|
||||
if let ty::Alias(..) = t.kind() {
|
||||
return ControlFlow::Continue(());
|
||||
match t.kind() {
|
||||
// If we are only looking for "constrained" regions, we have to ignore the
|
||||
// inputs to a projection as they may not appear in the normalized form.
|
||||
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
// All weak alias types should've been expanded beforehand.
|
||||
ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue