Skip to content

Commit 51adcde

Browse files
committed
Auto merge of #67899 - Marwes:view, r=<try>
perf: Avoid re-interning types in outlives checking In profiling `intern_ty` is a very hot function (9% in the test I used). While there does not seem to be a way to reduce the cost of calling we can avoid the call in some cases. In outlives checking `ParamTy` and `ProjectionTy` are extracted from the `Ty` value that contains them only to later be passed as an argument to `intern_ty` again later. This seems to be happening a lot in my test with `intern_ty` called from outlives is at ~6%. Since all `ParamTy` and `ProjectionTy` are already stored in a `Ty` I had an idea to pass around a `View` type which provides direct access to the specific, inner type without losing the original `Ty` pointer. While the current implementation does so with some unsafe to let the branch be elided on `Deref`, it could be done entirely in safe code as well, either by accepting the (predictable) branch in `Deref` or by storing the inner type in `View` as well as the `Ty`. But considering that the unsafe is trivial to prove and the call sites seem quite hot I opted to show the unsafe approach first. Based on #67840 (since it touches the same file/lines) Commits without #67840 https://github.com/rust-lang/rust/pull/67899/files/77ddc3540e52be4b5bd75cf082c621392acaf81b..b55bab206096c27533120921f6b0c273f115e34a
2 parents 2d8d559 + c243723 commit 51adcde

File tree

11 files changed

+309
-126
lines changed

11 files changed

+309
-126
lines changed

src/librustc/infer/lexical_region_resolve/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
602602
continue;
603603
}
604604

605-
let verify_kind_ty = verify.kind.to_ty(self.tcx());
605+
let verify_kind_ty = verify.kind.as_ty();
606606
if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) {
607607
continue;
608608
}

src/librustc/infer/outlives/obligations.rs

+4-4
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={:?})",
@@ -337,7 +337,7 @@ where
337337
&mut self,
338338
origin: infer::SubregionOrigin<'tcx>,
339339
region: ty::Region<'tcx>,
340-
projection_ty: ty::ProjectionTy<'tcx>,
340+
projection_ty: ty::View<'tcx, ty::ProjectionTy<'tcx>>,
341341
) {
342342
debug!(
343343
"projection_must_outlive(region={:?}, projection_ty={:?}, origin={:?})",
@@ -376,8 +376,8 @@ where
376376
// #55756) in cases where you have e.g., `<T as Foo<'a>>::Item:
377377
// 'a` in the environment but `trait Foo<'b> { type Item: 'b
378378
// }` in the trait definition.
379-
approx_env_bounds.retain(|bound| match bound.0.kind {
380-
ty::Projection(projection_ty) => self
379+
approx_env_bounds.retain(|bound| match bound.0.into() {
380+
ty::view::Projection(projection_ty) => self
381381
.verify_bound
382382
.projection_declared_bounds_from_trait(projection_ty)
383383
.all(|r| r != bound.1),

src/librustc/infer/outlives/verify.rs

+19-21
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

@@ -39,22 +39,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
3939
}
4040

4141
fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
42-
match ty.kind {
43-
ty::Param(p) => self.param_bound(p),
44-
ty::Projection(data) => self.projection_bound(data),
42+
match ty.into() {
43+
ty::view::Param(p) => self.param_bound(p),
44+
ty::view::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
5353
// environment
54-
let param_bounds = self
55-
.declared_generic_bounds_from_env(GenericKind::Param(param_ty))
56-
.into_iter()
57-
.map(|outlives| outlives.1);
54+
let param_bounds =
55+
self.declared_generic_bounds_from_env(param_ty).into_iter().map(|outlives| outlives.1);
5856

5957
// Add in the default bound of fn body that applies to all in
6058
// scope type parameters:
@@ -78,9 +76,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
7876
/// this list.
7977
pub fn projection_approx_declared_bounds_from_env(
8078
&self,
81-
projection_ty: ty::ProjectionTy<'tcx>,
79+
projection_ty: ty::View<'tcx, ty::ProjectionTy<'tcx>>,
8280
) -> Vec<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
83-
let projection_ty = GenericKind::Projection(projection_ty).to_ty(self.tcx);
81+
let projection_ty = projection_ty.as_ty();
8482
let erased_projection_ty = self.tcx.erase_regions(&projection_ty);
8583
self.declared_generic_bounds_from_env_with_compare_fn(|ty| {
8684
if let ty::Projection(..) = ty.kind {
@@ -97,16 +95,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
9795
/// exact match.
9896
pub fn projection_declared_bounds_from_trait(
9997
&self,
100-
projection_ty: ty::ProjectionTy<'tcx>,
98+
projection_ty: ty::View<'tcx, ty::ProjectionTy<'tcx>>,
10199
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
102100
self.declared_projection_bounds_from_trait(projection_ty)
103101
}
104102

105-
pub fn projection_bound(&self, projection_ty: ty::ProjectionTy<'tcx>) -> VerifyBound<'tcx> {
103+
pub fn projection_bound(
104+
&self,
105+
projection_ty: ty::View<'tcx, ty::ProjectionTy<'tcx>>,
106+
) -> VerifyBound<'tcx> {
106107
debug!("projection_bound(projection_ty={:?})", projection_ty);
107108

108-
let projection_ty_as_ty =
109-
self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
109+
let projection_ty_as_ty = projection_ty.as_ty();
110110

111111
// Search the env for where clauses like `P: 'a`.
112112
let env_bounds = self
@@ -161,18 +161,16 @@ 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

170170
fn declared_generic_bounds_from_env_with_compare_fn(
171171
&self,
172172
compare_ty: impl Fn(Ty<'tcx>) -> bool,
173173
) -> Vec<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
174-
let tcx = self.tcx;
175-
176174
// To start, collect bounds from user environment. Note that
177175
// parameter environments are already elaborated, so we don't
178176
// have to worry about that. Comparing using `==` is a bit
@@ -198,7 +196,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
198196
"declared_generic_bounds_from_env_with_compare_fn: region_bound_pair = {:?}",
199197
(r, p)
200198
);
201-
let p_ty = p.to_ty(tcx);
199+
let p_ty = p.as_ty();
202200
compare_ty(p_ty).then_some(ty::OutlivesPredicate(p_ty, r))
203201
});
204202

@@ -227,7 +225,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
227225
/// `region_bounds_declared_on_associated_item`.
228226
fn declared_projection_bounds_from_trait(
229227
&self,
230-
projection_ty: ty::ProjectionTy<'tcx>,
228+
projection_ty: ty::View<'tcx, ty::ProjectionTy<'tcx>>,
231229
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
232230
debug!("projection_bounds(projection_ty={:?})", projection_ty);
233231
let tcx = self.tcx;

src/librustc/infer/region_constraints/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ pub struct Verify<'tcx> {
184184

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

191191
/// Describes the things that some `GenericKind` value `G` is known to
@@ -875,10 +875,10 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
875875
}
876876

877877
impl<'tcx> GenericKind<'tcx> {
878-
pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
878+
pub fn as_ty(&self) -> Ty<'tcx> {
879879
match *self {
880-
GenericKind::Param(ref p) => p.to_ty(tcx),
881-
GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
880+
GenericKind::Param(ref p) => p.as_ty(),
881+
GenericKind::Projection(ref p) => p.as_ty(),
882882
}
883883
}
884884
}

src/librustc/traits/query/outlives_bounds.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ 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),
24-
RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
23+
RegionSubParam(ty::Region<'tcx>, ty::View<'tcx, ty::ParamTy>),
24+
RegionSubProjection(ty::Region<'tcx>, ty::View<'tcx, ty::ProjectionTy<'tcx>>),
2525
}
2626

2727
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OutlivesBound<'tcx> {

src/librustc/ty/mod.rs

+3
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;

0 commit comments

Comments
 (0)