Skip to content

Commit 043f260

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 2d8d559 commit 043f260

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
@@ -321,7 +321,7 @@ where
321321
&mut self,
322322
origin: infer::SubregionOrigin<'tcx>,
323323
region: ty::Region<'tcx>,
324-
param_ty: ty::ParamTy,
324+
param_ty: ty::View<'tcx, ty::ParamTy>,
325325
) {
326326
debug!(
327327
"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
@@ -2,7 +2,7 @@ use crate::infer::outlives::env::RegionBoundPairs;
22
use crate::infer::{GenericKind, VerifyBound};
33
use crate::traits;
44
use crate::ty::subst::{InternalSubsts, Subst};
5-
use crate::ty::{self, Ty, TyCtxt};
5+
use crate::ty::{self, Ty, TyCtxt, View};
66
use rustc_data_structures::captures::Captures;
77
use rustc_hir::def_id::DefId;
88

@@ -40,13 +40,13 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
4040

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

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

5252
// Start with anything like `T: 'a` we can scrape from the
@@ -161,9 +161,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
161161
/// bounds, but all the bounds it returns can be relied upon.
162162
fn declared_generic_bounds_from_env(
163163
&self,
164-
generic: GenericKind<'tcx>,
164+
generic: View<'tcx, ty::ParamTy>,
165165
) -> Vec<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
166-
let generic_ty = generic.to_ty(self.tcx);
166+
let generic_ty = generic.as_ty();
167167
self.declared_generic_bounds_from_env_with_compare_fn(|ty| ty == generic_ty)
168168
}
169169

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
@@ -91,6 +91,8 @@ pub use self::trait_def::TraitDef;
9191

9292
pub use self::query::queries;
9393

94+
pub use self::view::View;
95+
9496
pub mod adjustment;
9597
pub mod binding;
9698
pub mod cast;
@@ -114,6 +116,7 @@ pub mod steal;
114116
pub mod subst;
115117
pub mod trait_def;
116118
pub mod util;
119+
pub mod view;
117120
pub mod walk;
118121

119122
mod context;

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
@@ -82,8 +82,8 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
8282

8383
// OutlivesTypeParameterEnv -- the actual checking that `X:'a`
8484
// is implied by the environment is done in regionck.
85-
ty::Param(p) => {
86-
out.push(Component::Param(p));
85+
ty::Param(_) => {
86+
out.push(Component::Param(ty::View::new(ty).unwrap()));
8787
}
8888

8989
// 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
@@ -13,6 +13,7 @@ use rustc_index::vec::{Idx, IndexVec};
1313

1414
use smallvec::SmallVec;
1515
use std::fmt;
16+
use std::marker::PhantomData;
1617
use std::rc::Rc;
1718
use std::sync::Arc;
1819

@@ -389,6 +390,13 @@ impl<'tcx, I: Idx, T: Lift<'tcx>> Lift<'tcx> for IndexVec<I, T> {
389390
}
390391
}
391392

393+
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for PhantomData<T> {
394+
type Lifted = PhantomData<T::Lifted>;
395+
fn lift_to_tcx(&self, _tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
396+
Some(PhantomData)
397+
}
398+
}
399+
392400
impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> {
393401
type Lifted = ty::TraitRef<'tcx>;
394402
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
@@ -1067,3 +1075,13 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
10671075
false
10681076
}
10691077
}
1078+
1079+
impl<'tcx, T> TypeFoldable<'tcx> for PhantomData<T> {
1080+
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> Self {
1081+
*self
1082+
}
1083+
1084+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
1085+
false
1086+
}
1087+
}

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)