Skip to content

Commit d9bbf2a

Browse files
committed
feat: Add a ty::View
`ty::View<'tcx, T>` acts like a `T` but internally stores a `Ty<'tcx>` pointer. Thanks to this, it is possible to retrieve the original `Ty` value without needing to ask the interner for it. Looking up the already created type (`T`) takes a good chunk of the time in `infer/outlives/verify.rs` so this should be a good speedup. It may be applicable in other places as well, but those are far lower when profiling.
1 parent 77ddc35 commit d9bbf2a

File tree

8 files changed

+214
-11
lines changed

8 files changed

+214
-11
lines changed

src/librustc/infer/outlives/obligations.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ where
332332
&mut self,
333333
origin: infer::SubregionOrigin<'tcx>,
334334
region: ty::Region<'tcx>,
335-
param_ty: ty::ParamTy,
335+
param_ty: ty::View<'tcx, ty::ParamTy>,
336336
) {
337337
debug!(
338338
"param_ty_must_outlive(region={:?}, param_ty={:?}, origin={:?})",

src/librustc/infer/outlives/verify.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::infer::outlives::env::RegionBoundPairs;
33
use crate::infer::{GenericKind, VerifyBound};
44
use crate::traits;
55
use crate::ty::subst::{InternalSubsts, Subst};
6-
use crate::ty::{self, Ty, TyCtxt};
6+
use crate::ty::{self, Ty, TyCtxt, View};
77
use crate::util::captures::{Captures, Captures2, Captures3};
88

99
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
@@ -42,13 +42,13 @@ impl<'cx, 'tcx, 'e> VerifyBoundCx<'cx, 'tcx, 'e> {
4242

4343
fn type_bound(&mut self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
4444
match ty.kind {
45-
ty::Param(p) => self.param_bound(p),
45+
ty::Param(_) => self.param_bound(View::new(ty).unwrap()),
4646
ty::Projection(data) => self.projection_bound(data),
4747
_ => self.recursive_type_bound(ty),
4848
}
4949
}
5050

51-
fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
51+
fn param_bound(&self, param_ty: View<'tcx, ty::ParamTy>) -> VerifyBound<'tcx> {
5252
debug!("param_bound(param_ty={:?})", param_ty);
5353

5454
// Start with anything like `T: 'a` we can scrape from the
@@ -166,10 +166,10 @@ impl<'cx, 'tcx, 'e> VerifyBoundCx<'cx, 'tcx, 'e> {
166166
/// bounds, but all the bounds it returns can be relied upon.
167167
fn declared_generic_bounds_from_env(
168168
&self,
169-
generic: ty::ParamTy,
169+
generic: View<'tcx, ty::ParamTy>,
170170
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + Captures2<'cx, 'tcx>
171171
{
172-
let generic_ty = generic.to_ty(self.tcx);
172+
let generic_ty = generic.as_ty();
173173
self.declared_generic_bounds_from_env_with_compare_fn(move |ty| ty == generic_ty)
174174
}
175175

src/librustc/infer/region_constraints/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ pub struct Verify<'tcx> {
184184

185185
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable)]
186186
pub enum GenericKind<'tcx> {
187-
Param(ty::ParamTy),
187+
Param(ty::View<'tcx, ty::ParamTy>),
188188
Projection(ty::ProjectionTy<'tcx>),
189189
}
190190

src/librustc/traits/query/outlives_bounds.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::mem;
2020
#[derive(Clone, Debug, TypeFoldable, Lift)]
2121
pub enum OutlivesBound<'tcx> {
2222
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
23-
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
23+
RegionSubParam(ty::Region<'tcx>, ty::View<'tcx, ty::ParamTy>),
2424
RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
2525
}
2626

src/librustc/ty/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ pub use self::trait_def::TraitDef;
9797

9898
pub use self::query::queries;
9999

100+
pub use self::view::View;
101+
100102
pub mod adjustment;
101103
pub mod binding;
102104
pub mod cast;
@@ -119,6 +121,7 @@ pub mod steal;
119121
pub mod subst;
120122
pub mod trait_def;
121123
pub mod util;
124+
pub mod view;
122125
pub mod walk;
123126
pub mod wf;
124127

src/librustc/ty/outlives.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use smallvec::SmallVec;
88
#[derive(Debug)]
99
pub enum Component<'tcx> {
1010
Region(ty::Region<'tcx>),
11-
Param(ty::ParamTy),
11+
Param(ty::View<'tcx, ty::ParamTy>),
1212
UnresolvedInferenceVariable(ty::InferTy),
1313

1414
// Projections like `T::Foo` are tricky because a constraint like
@@ -85,8 +85,8 @@ impl<'tcx> TyCtxt<'tcx> {
8585

8686
// OutlivesTypeParameterEnv -- the actual checking that `X:'a`
8787
// is implied by the environment is done in regionck.
88-
ty::Param(p) => {
89-
out.push(Component::Param(p));
88+
ty::Param(_) => {
89+
out.push(Component::Param(ty::View::new(ty).unwrap()));
9090
}
9191

9292
// For projections, we prefer to generate an obligation like

src/librustc/ty/structural_impls.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_index::vec::{Idx, IndexVec};
1414
use smallvec::SmallVec;
1515

1616
use std::fmt;
17+
use std::marker::PhantomData;
1718
use std::rc::Rc;
1819
use std::sync::Arc;
1920

@@ -396,6 +397,13 @@ impl<'tcx, I: Idx, T: Lift<'tcx>> Lift<'tcx> for IndexVec<I, T> {
396397
}
397398
}
398399

400+
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for PhantomData<T> {
401+
type Lifted = PhantomData<T::Lifted>;
402+
fn lift_to_tcx(&self, _tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
403+
Some(PhantomData)
404+
}
405+
}
406+
399407
impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> {
400408
type Lifted = ty::TraitRef<'tcx>;
401409
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
@@ -1074,3 +1082,13 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
10741082
false
10751083
}
10761084
}
1085+
1086+
impl<'tcx, T> TypeFoldable<'tcx> for PhantomData<T> {
1087+
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> Self {
1088+
*self
1089+
}
1090+
1091+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
1092+
false
1093+
}
1094+
}

src/librustc/ty/view.rs

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
use std::{fmt, marker::PhantomData};
2+
3+
use syntax::ast;
4+
5+
use crate::{
6+
hir::{self, def_id::DefId},
7+
ty::{
8+
self, AdtDef, Binder, BoundTy, ExistentialPredicate, InferTy, List, ParamTy, PolyFnSig,
9+
ProjectionTy, Region, SubstsRef, Ty, TypeAndMut,
10+
},
11+
};
12+
13+
pub use self::ViewKind::*;
14+
15+
// TODO Forward eq/hash?
16+
#[derive(Eq, PartialEq, Hash, TypeFoldable, Lift)]
17+
pub struct View<'tcx, T> {
18+
ty: Ty<'tcx>,
19+
_marker: PhantomData<T>,
20+
}
21+
22+
impl<T> Copy for View<'_, T> {}
23+
impl<T> Clone for View<'_, T> {
24+
fn clone(&self) -> Self {
25+
View { ty: self.ty, _marker: PhantomData }
26+
}
27+
}
28+
29+
impl<'tcx, T> fmt::Debug for View<'tcx, T>
30+
where
31+
T: fmt::Debug,
32+
{
33+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34+
self.ty.fmt(f)
35+
}
36+
}
37+
38+
impl<'tcx, T> fmt::Display for View<'tcx, T>
39+
where
40+
T: fmt::Display + TyDeref<'tcx> + 'tcx,
41+
{
42+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43+
(**self).fmt(f)
44+
}
45+
}
46+
impl<'tcx, T> std::ops::Deref for View<'tcx, T>
47+
where
48+
T: TyDeref<'tcx> + 'tcx,
49+
{
50+
type Target = T;
51+
fn deref(&self) -> &Self::Target {
52+
match T::ty_deref(self.ty) {
53+
Some(t) => t,
54+
// SAFETY verified by `View::new`
55+
None => unsafe { std::hint::unreachable_unchecked() },
56+
}
57+
}
58+
}
59+
60+
impl<'tcx, T> View<'tcx, T>
61+
where
62+
T: TyDeref<'tcx> + 'tcx,
63+
{
64+
pub fn new(ty: Ty<'tcx>) -> Option<Self> {
65+
T::ty_deref(ty)?;
66+
Some(View { ty, _marker: PhantomData })
67+
}
68+
}
69+
70+
impl<'tcx, T> View<'tcx, T> {
71+
pub fn as_ty(&self) -> Ty<'tcx> {
72+
self.ty
73+
}
74+
}
75+
76+
/// SAFETY If `Some` is returned for `ty` then `Some` must always be returned for any subsequent
77+
/// call with the same `Ty` value
78+
pub unsafe trait TyDeref<'tcx>: Sized {
79+
fn ty_deref(ty: Ty<'tcx>) -> Option<&'tcx Self>;
80+
}
81+
82+
unsafe impl<'tcx> TyDeref<'tcx> for ty::ParamTy {
83+
fn ty_deref(ty: Ty<'tcx>) -> Option<&'tcx Self> {
84+
match &ty.kind {
85+
ty::Param(p) => Some(p),
86+
_ => None,
87+
}
88+
}
89+
}
90+
91+
pub enum ViewKind<'tcx> {
92+
Bool,
93+
94+
Char,
95+
96+
Int(ast::IntTy),
97+
98+
Uint(ast::UintTy),
99+
100+
Float(ast::FloatTy),
101+
102+
Adt(&'tcx AdtDef, SubstsRef<'tcx>),
103+
104+
Foreign(DefId),
105+
106+
Str,
107+
108+
Array(Ty<'tcx>, &'tcx ty::Const<'tcx>),
109+
110+
Slice(Ty<'tcx>),
111+
112+
RawPtr(TypeAndMut<'tcx>),
113+
114+
Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability),
115+
116+
FnDef(DefId, SubstsRef<'tcx>),
117+
118+
FnPtr(PolyFnSig<'tcx>),
119+
120+
Dynamic(Binder<&'tcx List<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
121+
122+
Closure(DefId, SubstsRef<'tcx>),
123+
124+
Generator(DefId, SubstsRef<'tcx>, hir::Movability),
125+
126+
GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>),
127+
128+
Never,
129+
130+
Tuple(SubstsRef<'tcx>),
131+
132+
Projection(ProjectionTy<'tcx>),
133+
134+
UnnormalizedProjection(ProjectionTy<'tcx>),
135+
136+
Opaque(DefId, SubstsRef<'tcx>),
137+
138+
Param(View<'tcx, ParamTy>),
139+
140+
Bound(ty::DebruijnIndex, BoundTy),
141+
142+
Placeholder(ty::PlaceholderType),
143+
144+
Infer(InferTy),
145+
146+
Error,
147+
}
148+
149+
impl<'tcx> From<Ty<'tcx>> for ViewKind<'tcx> {
150+
fn from(ty: Ty<'tcx>) -> Self {
151+
match ty.kind {
152+
ty::RawPtr(tm) => Self::RawPtr(tm),
153+
ty::Array(typ, sz) => Self::Array(typ, sz),
154+
ty::Slice(typ) => Self::Slice(typ),
155+
ty::Adt(tid, substs) => Self::Adt(tid, substs),
156+
ty::Dynamic(trait_ty, region) => Self::Dynamic(trait_ty, region),
157+
ty::Tuple(ts) => Self::Tuple(ts),
158+
ty::FnDef(def_id, substs) => Self::FnDef(def_id, substs),
159+
ty::FnPtr(f) => Self::FnPtr(f),
160+
ty::Ref(r, ty, mutbl) => Self::Ref(r, ty, mutbl),
161+
ty::Generator(did, substs, movability) => Self::Generator(did, substs, movability),
162+
ty::GeneratorWitness(types) => Self::GeneratorWitness(types),
163+
ty::Closure(did, substs) => Self::Closure(did, substs),
164+
ty::Projection(data) => Self::Projection(data),
165+
ty::UnnormalizedProjection(data) => Self::UnnormalizedProjection(data),
166+
ty::Opaque(did, substs) => Self::Opaque(did, substs),
167+
ty::Bool => Self::Bool,
168+
ty::Char => Self::Char,
169+
ty::Str => Self::Str,
170+
ty::Int(i) => Self::Int(i),
171+
ty::Uint(i) => Self::Uint(i),
172+
ty::Float(f) => Self::Float(f),
173+
ty::Error => Self::Error,
174+
ty::Infer(i) => Self::Infer(i),
175+
ty::Param(_) => Self::Param(View::new(ty).unwrap()),
176+
ty::Bound(b, c) => Self::Bound(b, c),
177+
ty::Placeholder(p) => Self::Placeholder(p),
178+
ty::Never => Self::Never,
179+
ty::Foreign(f) => Self::Foreign(f),
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)