Skip to content

Commit 1214625

Browse files
committed
Specialize Lift and TypeFoldable for View
1 parent 2eb5de7 commit 1214625

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

src/librustc/ty/view.rs

+45-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ use std::{fmt, marker::PhantomData};
33
use syntax::ast;
44

55
use crate::ty::{
6-
self, AdtDef, Binder, BoundTy, ExistentialPredicate, InferTy, List, ParamTy, PolyFnSig,
7-
ProjectionTy, Region, SubstsRef, Ty, TypeAndMut,
6+
self,
7+
context::{Lift, TyCtxt},
8+
fold::{TypeFoldable, TypeFolder, TypeVisitor},
9+
AdtDef, Binder, BoundTy, ExistentialPredicate, InferTy, List, ParamTy, PolyFnSig, ProjectionTy,
10+
Region, SubstsRef, Ty, TypeAndMut,
811
};
912
use rustc_hir::{self as hir, def_id::DefId};
1013

@@ -13,12 +16,39 @@ pub use self::ViewKind::*;
1316
/// `View<'tcx, T>` contains a value of `T` but stores the `Ty<'tcx>` ptr that contains the `T`
1417
/// This allows for cheap access to the `Ty<'tcx>` without needing to ask the type interner or
1518
/// losing the `T` type.
16-
#[derive(TypeFoldable, Eq, PartialEq, Hash, Lift)]
19+
#[derive(Eq, PartialEq, Hash)]
1720
pub struct View<'tcx, T> {
1821
ty: Ty<'tcx>,
1922
_marker: PhantomData<T>,
2023
}
2124

25+
impl<'a, 'tcx, T> Lift<'tcx> for View<'a, T>
26+
where
27+
T: TyDeref<'a> + Lift<'tcx>,
28+
T::Lifted: TyDeref<'tcx>,
29+
{
30+
type Lifted = View<'tcx, T::Lifted>;
31+
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
32+
tcx.lift(&**self).map(|t| View::intern(tcx, t))
33+
}
34+
}
35+
36+
impl<'tcx, T> TypeFoldable<'tcx> for View<'tcx, T>
37+
where
38+
T: TyDeref<'tcx> + TypeFoldable<'tcx> + PartialEq,
39+
{
40+
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
41+
let tcx = folder.tcx();
42+
let old_t = &**self;
43+
let new_t = old_t.super_fold_with(folder);
44+
if *old_t == new_t { *self } else { Self::intern(tcx, new_t) }
45+
}
46+
47+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
48+
(**self).super_visit_with(visitor)
49+
}
50+
}
51+
2252
impl<T> Copy for View<'_, T> {}
2353

2454
impl<T> Clone for View<'_, T> {
@@ -70,6 +100,12 @@ where
70100
T::ty_deref(ty)?;
71101
Some(View { ty, _marker: PhantomData })
72102
}
103+
104+
#[inline]
105+
pub fn intern(tcx: TyCtxt<'tcx>, t: T) -> Self {
106+
let ty = t.intern(tcx);
107+
View { ty, _marker: PhantomData }
108+
}
73109
}
74110

75111
impl<'tcx, T> View<'tcx, T> {
@@ -82,12 +118,18 @@ impl<'tcx, T> View<'tcx, T> {
82118
/// SAFETY If `Some` is returned for `ty` then `Some` must always be returned for any subsequent
83119
/// call with the same `Ty` value
84120
pub unsafe trait TyDeref<'tcx>: Sized + 'tcx {
121+
fn intern(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
85122
fn ty_deref(ty: Ty<'tcx>) -> Option<&'tcx Self>;
86123
}
87124

88125
macro_rules! impl_ty_deref {
89126
($ty: ty, $variant: ident) => {
90127
unsafe impl<'tcx> TyDeref<'tcx> for $ty {
128+
#[inline]
129+
fn intern(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
130+
tcx.mk_ty(ty::$variant(self))
131+
}
132+
91133
#[inline]
92134
fn ty_deref(ty: Ty<'tcx>) -> Option<&'tcx Self> {
93135
match &ty.kind {

0 commit comments

Comments
 (0)