Skip to content

Commit 8c4ff22

Browse files
committed
Auto merge of #48411 - nikomatsakis:chalkify-canonical-query-mir, r=eddyb
introduce canonical queries, use for normalization and dropck-outlives This branch adds in the concept of a **canonicalized trait query** and uses it for three specific operations: - `infcx.at(cause, param_env).normalize(type_foldable)` - normalizes all associated types in `type_foldable` - `tcx.normalize_erasing_regions(param_env, type_foldable)` - like normalize, but erases regions first and in the result; this leads to better caching - `infcx.at(cause, param_env).dropck_outlives(ty)` - produces the set of types that must be live when a value of type `ty` is dropped - used from dropck but also NLL outlives This is a kind of "first step" towards a more Chalk-ified approach. It leads to a **big** speedup for NLL, which is basically dominated by the dropck-outlives computation. Here are some timing measurements for the `syn` crate (pre-branch measurements coming soon): | Commit | NLL disabled | NLL enabled | | ------- | --- | --- | | Before my branch | 5.43s | 8.99s | | After my branch | 5.36s | 7.25s | (Note that NLL enabled still does *all the work* that NLL disabled does, so this is not really a way to compare the performance of NLL versus the AST-based borrow checker directly.) Since this affects all codepaths, I'd like to do a full perf run before we land anything. Also, this is not the "final point" for canonicalization etc. I think canonicalization can be made substantially faster, for one thing. But it seems like a reasonable starting point for a branch that's gotten a bit larger than I would have liked. **Commit convention:** First of all, this entire branch ought to be a "pure refactoring", I believe, not changing anything about external behavior. Second, I've tagged the most important commits with `[VIC]` (very important commit), so you can scan for those. =) r? @eddyb
2 parents e65547d + 17c4103 commit 8c4ff22

File tree

109 files changed

+3783
-1706
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+3783
-1706
lines changed

src/Cargo.lock

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/librustc/dep_graph/dep_node.rs

+30-24
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,12 @@ use hir::{HirId, ItemLocalId};
6767

6868
use ich::{Fingerprint, StableHashingContext};
6969
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
70-
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
71-
use ty::subst::Substs;
7270
use std::fmt;
7371
use std::hash::Hash;
7472
use syntax_pos::symbol::InternedString;
73+
use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
74+
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
75+
use ty::subst::Substs;
7576

7677
// erase!() just makes tokens go away. It's used to specify which macro argument
7778
// is repeated (i.e. which sub-expression of the macro we are in) but don't need
@@ -80,6 +81,10 @@ macro_rules! erase {
8081
($x:tt) => ({})
8182
}
8283

84+
macro_rules! replace {
85+
($x:tt with $($y:tt)*) => ($($y)*)
86+
}
87+
8388
macro_rules! is_anon_attr {
8489
(anon) => (true);
8590
($attr:ident) => (false);
@@ -111,7 +116,7 @@ macro_rules! define_dep_nodes {
111116
(<$tcx:tt>
112117
$(
113118
[$($attr:ident),* ]
114-
$variant:ident $(( $($tuple_arg:tt),* ))*
119+
$variant:ident $(( $tuple_arg_ty:ty $(,)* ))*
115120
$({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })*
116121
,)*
117122
) => (
@@ -134,7 +139,7 @@ macro_rules! define_dep_nodes {
134139

135140
// tuple args
136141
$({
137-
return <( $($tuple_arg,)* ) as DepNodeParams>
142+
return <$tuple_arg_ty as DepNodeParams>
138143
::CAN_RECONSTRUCT_QUERY_KEY;
139144
})*
140145

@@ -186,7 +191,7 @@ macro_rules! define_dep_nodes {
186191
DepKind :: $variant => {
187192
// tuple args
188193
$({
189-
$(erase!($tuple_arg);)*
194+
erase!($tuple_arg_ty);
190195
return true;
191196
})*
192197

@@ -205,7 +210,7 @@ macro_rules! define_dep_nodes {
205210

206211
pub enum DepConstructor<$tcx> {
207212
$(
208-
$variant $(( $($tuple_arg),* ))*
213+
$variant $(( $tuple_arg_ty ))*
209214
$({ $($struct_arg_name : $struct_arg_ty),* })*
210215
),*
211216
}
@@ -227,15 +232,14 @@ macro_rules! define_dep_nodes {
227232
{
228233
match dep {
229234
$(
230-
DepConstructor :: $variant $(( $($tuple_arg),* ))*
235+
DepConstructor :: $variant $(( replace!(($tuple_arg_ty) with arg) ))*
231236
$({ $($struct_arg_name),* })*
232237
=>
233238
{
234239
// tuple args
235240
$({
236-
let tupled_args = ( $($tuple_arg,)* );
237-
let hash = DepNodeParams::to_fingerprint(&tupled_args,
238-
tcx);
241+
erase!($tuple_arg_ty);
242+
let hash = DepNodeParams::to_fingerprint(&arg, tcx);
239243
let dep_node = DepNode {
240244
kind: DepKind::$variant,
241245
hash
@@ -247,7 +251,7 @@ macro_rules! define_dep_nodes {
247251
tcx.sess.opts.debugging_opts.query_dep_graph)
248252
{
249253
tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
250-
tupled_args.to_debug_str(tcx)
254+
arg.to_debug_str(tcx)
251255
});
252256
}
253257

@@ -631,7 +635,9 @@ define_dep_nodes!( <'tcx>
631635
[] CodegenUnit(InternedString),
632636
[] CompileCodegenUnit(InternedString),
633637
[input] OutputFilenames,
634-
[anon] NormalizeTy,
638+
[] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>),
639+
[] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
640+
[] DropckOutlives(CanonicalTyGoal<'tcx>),
635641

636642
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
637643

@@ -679,43 +685,43 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
679685
}
680686
}
681687

682-
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) {
688+
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefId {
683689
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
684690

685691
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
686-
tcx.def_path_hash(self.0).0
692+
tcx.def_path_hash(*self).0
687693
}
688694

689695
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
690-
tcx.item_path_str(self.0)
696+
tcx.item_path_str(*self)
691697
}
692698
}
693699

694-
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIndex,) {
700+
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefIndex {
695701
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
696702

697703
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
698-
tcx.hir.definitions().def_path_hash(self.0).0
704+
tcx.hir.definitions().def_path_hash(*self).0
699705
}
700706

701707
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
702-
tcx.item_path_str(DefId::local(self.0))
708+
tcx.item_path_str(DefId::local(*self))
703709
}
704710
}
705711

706-
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (CrateNum,) {
712+
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for CrateNum {
707713
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
708714

709715
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
710716
let def_id = DefId {
711-
krate: self.0,
717+
krate: *self,
712718
index: CRATE_DEF_INDEX,
713719
};
714720
tcx.def_path_hash(def_id).0
715721
}
716722

717723
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
718-
tcx.crate_name(self.0).as_str().to_string()
724+
tcx.crate_name(*self).as_str().to_string()
719725
}
720726
}
721727

@@ -743,17 +749,17 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, De
743749
}
744750
}
745751

746-
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (HirId,) {
752+
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for HirId {
747753
const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
748754

749755
// We actually would not need to specialize the implementation of this
750756
// method but it's faster to combine the hashes than to instantiate a full
751757
// hashing context and stable-hashing state.
752758
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
753-
let (HirId {
759+
let HirId {
754760
owner,
755761
local_id: ItemLocalId(local_id),
756-
},) = *self;
762+
} = *self;
757763

758764
let def_path_hash = tcx.def_path_hash(DefId::local(owner));
759765
let local_id = Fingerprint::from_smaller_hash(local_id as u64);

src/librustc/ich/impls_ty.rs

+57-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use std::cell::RefCell;
1919
use std::hash as std_hash;
2020
use std::mem;
2121
use middle::region;
22+
use infer;
2223
use traits;
2324
use ty;
2425
use mir;
@@ -85,6 +86,9 @@ for ty::RegionKind {
8586
ty::ReEmpty => {
8687
// No variant fields to hash for these ...
8788
}
89+
ty::ReCanonical(c) => {
90+
c.hash_stable(hcx, hasher);
91+
}
8892
ty::ReLateBound(db, ty::BrAnon(i)) => {
8993
db.depth.hash_stable(hcx, hasher);
9094
i.hash_stable(hcx, hasher);
@@ -130,6 +134,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
130134
}
131135
}
132136

137+
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CanonicalVar {
138+
#[inline]
139+
fn hash_stable<W: StableHasherResult>(&self,
140+
hcx: &mut StableHashingContext<'gcx>,
141+
hasher: &mut StableHasher<W>) {
142+
use rustc_data_structures::indexed_vec::Idx;
143+
self.index().hash_stable(hcx, hasher);
144+
}
145+
}
146+
133147
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
134148
for ty::adjustment::AutoBorrow<'gcx> {
135149
fn hash_stable<W: StableHasherResult>(&self,
@@ -1003,12 +1017,6 @@ impl_stable_hash_for!(struct ty::Destructor {
10031017
did
10041018
});
10051019

1006-
impl_stable_hash_for!(struct ty::DtorckConstraint<'tcx> {
1007-
outlives,
1008-
dtorck_types
1009-
});
1010-
1011-
10121020
impl<'a> HashStable<StableHashingContext<'a>> for ty::CrateVariancesMap {
10131021
fn hash_stable<W: StableHasherResult>(&self,
10141022
hcx: &mut StableHashingContext<'a>,
@@ -1229,11 +1237,52 @@ for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContex
12291237
}
12301238
}
12311239

1232-
impl<'gcx> HashStable<StableHashingContext<'gcx>>
1240+
impl<'a> HashStable<StableHashingContext<'a>>
12331241
for ty::UniverseIndex {
12341242
fn hash_stable<W: StableHasherResult>(&self,
1235-
hcx: &mut StableHashingContext<'gcx>,
1243+
hcx: &mut StableHashingContext<'a>,
12361244
hasher: &mut StableHasher<W>) {
12371245
self.depth().hash_stable(hcx, hasher);
12381246
}
12391247
}
1248+
1249+
impl_stable_hash_for!(
1250+
impl<'tcx, V> for struct infer::canonical::Canonical<'tcx, V> {
1251+
variables, value
1252+
}
1253+
);
1254+
1255+
impl_stable_hash_for!(
1256+
impl<'tcx> for struct infer::canonical::CanonicalVarValues<'tcx> {
1257+
var_values
1258+
}
1259+
);
1260+
1261+
impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo {
1262+
kind
1263+
});
1264+
1265+
impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
1266+
Ty(k),
1267+
Region
1268+
});
1269+
1270+
impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
1271+
General,
1272+
Int,
1273+
Float
1274+
});
1275+
1276+
impl_stable_hash_for!(
1277+
impl<'tcx, R> for struct infer::canonical::QueryResult<'tcx, R> {
1278+
var_values, region_constraints, certainty, value
1279+
}
1280+
);
1281+
1282+
impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> {
1283+
region_outlives, ty_outlives
1284+
});
1285+
1286+
impl_stable_hash_for!(enum infer::canonical::Certainty {
1287+
Proven, Ambiguous
1288+
});

src/librustc/infer/at.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ use super::*;
4040
use ty::relate::{Relate, TypeRelation};
4141

4242
pub struct At<'a, 'gcx: 'tcx, 'tcx: 'a> {
43-
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
44-
cause: &'a ObligationCause<'tcx>,
45-
param_env: ty::ParamEnv<'tcx>,
43+
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
44+
pub cause: &'a ObligationCause<'tcx>,
45+
pub param_env: ty::ParamEnv<'tcx>,
4646
}
4747

4848
pub struct Trace<'a, 'gcx: 'tcx, 'tcx: 'a> {
@@ -281,6 +281,20 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
281281
}
282282
}
283283

284+
impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
285+
fn to_trace(cause: &ObligationCause<'tcx>,
286+
a_is_expected: bool,
287+
a: Self,
288+
b: Self)
289+
-> TypeTrace<'tcx>
290+
{
291+
TypeTrace {
292+
cause: cause.clone(),
293+
values: Regions(ExpectedFound::new(a_is_expected, a, b))
294+
}
295+
}
296+
}
297+
284298
impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
285299
fn to_trace(cause: &ObligationCause<'tcx>,
286300
a_is_expected: bool,

0 commit comments

Comments
 (0)