Skip to content

Commit 251f865

Browse files
committed
Auto merge of #48411 - nikomatsakis:chalkify-canonical-query-mir, r=<try>
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 063deba + 41d762f commit 251f865

File tree

104 files changed

+3440
-1671
lines changed

Some content is hidden

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

104 files changed

+3440
-1671
lines changed

src/Cargo.lock

+18
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

+32-27
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,17 @@
6060
//! user of the `DepNode` API of having to know how to compute the expected
6161
//! fingerprint for a given set of node parameters.
6262
63+
use ich::{Fingerprint, StableHashingContext};
64+
use infer::canonical::Canonical;
6365
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
6466
use hir::map::DefPathHash;
6567
use hir::{HirId, ItemLocalId};
66-
67-
use ich::Fingerprint;
68-
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
69-
use ty::subst::Substs;
7068
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
71-
use ich::StableHashingContext;
7269
use std::fmt;
7370
use std::hash::Hash;
7471
use syntax_pos::symbol::InternedString;
72+
use ty::{self, TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
73+
use ty::subst::Substs;
7574

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

82+
macro_rules! replace {
83+
($x:tt with $($y:tt)*) => ($($y)*)
84+
}
85+
8386
macro_rules! is_anon_attr {
8487
(anon) => (true);
8588
($attr:ident) => (false);
@@ -111,7 +114,7 @@ macro_rules! define_dep_nodes {
111114
(<$tcx:tt>
112115
$(
113116
[$($attr:ident),* ]
114-
$variant:ident $(( $($tuple_arg:tt),* ))*
117+
$variant:ident $(( $tuple_arg_ty:ty $(,)* ))*
115118
$({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })*
116119
,)*
117120
) => (
@@ -134,7 +137,7 @@ macro_rules! define_dep_nodes {
134137

135138
// tuple args
136139
$({
137-
return <( $($tuple_arg,)* ) as DepNodeParams>
140+
return <$tuple_arg_ty as DepNodeParams>
138141
::CAN_RECONSTRUCT_QUERY_KEY;
139142
})*
140143

@@ -186,7 +189,7 @@ macro_rules! define_dep_nodes {
186189
DepKind :: $variant => {
187190
// tuple args
188191
$({
189-
$(erase!($tuple_arg);)*
192+
erase!($tuple_arg_ty);
190193
return true;
191194
})*
192195

@@ -205,7 +208,7 @@ macro_rules! define_dep_nodes {
205208

206209
pub enum DepConstructor<$tcx> {
207210
$(
208-
$variant $(( $($tuple_arg),* ))*
211+
$variant $(( $tuple_arg_ty ))*
209212
$({ $($struct_arg_name : $struct_arg_ty),* })*
210213
),*
211214
}
@@ -227,15 +230,14 @@ macro_rules! define_dep_nodes {
227230
{
228231
match dep {
229232
$(
230-
DepConstructor :: $variant $(( $($tuple_arg),* ))*
233+
DepConstructor :: $variant $(( replace!(($tuple_arg_ty) with arg) ))*
231234
$({ $($struct_arg_name),* })*
232235
=>
233236
{
234237
// tuple args
235238
$({
236-
let tupled_args = ( $($tuple_arg,)* );
237-
let hash = DepNodeParams::to_fingerprint(&tupled_args,
238-
tcx);
239+
erase!($tuple_arg_ty);
240+
let hash = DepNodeParams::to_fingerprint(&arg, tcx);
239241
let dep_node = DepNode {
240242
kind: DepKind::$variant,
241243
hash
@@ -247,7 +249,7 @@ macro_rules! define_dep_nodes {
247249
tcx.sess.opts.debugging_opts.query_dep_graph)
248250
{
249251
tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
250-
tupled_args.to_debug_str(tcx)
252+
arg.to_debug_str(tcx)
251253
});
252254
}
253255

@@ -629,7 +631,10 @@ define_dep_nodes!( <'tcx>
629631
[] CodegenUnit(InternedString),
630632
[] CompileCodegenUnit(InternedString),
631633
[input] OutputFilenames,
632-
[anon] NormalizeTy,
634+
[] NormalizeProjectionTy(&'tcx Canonical<ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>),
635+
[] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
636+
[] DropckOutlives(&'tcx Canonical<ParamEnvAnd<'tcx, Ty<'tcx>>>),
637+
633638
// We use this for most things when incr. comp. is turned off.
634639
[] Null,
635640

@@ -679,43 +684,43 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
679684
}
680685
}
681686

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

685690
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
686-
tcx.def_path_hash(self.0).0
691+
tcx.def_path_hash(*self).0
687692
}
688693

689694
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
690-
tcx.item_path_str(self.0)
695+
tcx.item_path_str(*self)
691696
}
692697
}
693698

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

697702
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
698-
tcx.hir.definitions().def_path_hash(self.0).0
703+
tcx.hir.definitions().def_path_hash(*self).0
699704
}
700705

701706
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
702-
tcx.item_path_str(DefId::local(self.0))
707+
tcx.item_path_str(DefId::local(*self))
703708
}
704709
}
705710

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

709714
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
710715
let def_id = DefId {
711-
krate: self.0,
716+
krate: *self,
712717
index: CRATE_DEF_INDEX,
713718
};
714719
tcx.def_path_hash(def_id).0
715720
}
716721

717722
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
718-
tcx.crate_name(self.0).as_str().to_string()
723+
tcx.crate_name(*self).as_str().to_string()
719724
}
720725
}
721726

@@ -743,17 +748,17 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, De
743748
}
744749
}
745750

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

749754
// We actually would not need to specialize the implementation of this
750755
// method but it's faster to combine the hashes than to instantiate a full
751756
// hashing context and stable-hashing state.
752757
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
753-
let (HirId {
758+
let HirId {
754759
owner,
755760
local_id: ItemLocalId(local_id),
756-
},) = *self;
761+
} = *self;
757762

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

src/librustc/ich/impls_ty.rs

+69-6
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::{self, canonical};
2223
use traits;
2324
use ty;
2425

@@ -73,6 +74,9 @@ for ty::RegionKind {
7374
ty::ReEmpty => {
7475
// No variant fields to hash for these ...
7576
}
77+
ty::ReCanonical(c) => {
78+
c.hash_stable(hcx, hasher);
79+
}
7680
ty::ReLateBound(db, ty::BrAnon(i)) => {
7781
db.depth.hash_stable(hcx, hasher);
7882
i.hash_stable(hcx, hasher);
@@ -118,6 +122,16 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::RegionVid {
118122
}
119123
}
120124

125+
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CanonicalVar {
126+
#[inline]
127+
fn hash_stable<W: StableHasherResult>(&self,
128+
hcx: &mut StableHashingContext<'gcx>,
129+
hasher: &mut StableHasher<W>) {
130+
use rustc_data_structures::indexed_vec::Idx;
131+
self.index().hash_stable(hcx, hasher);
132+
}
133+
}
134+
121135
impl<'gcx> HashStable<StableHashingContext<'gcx>>
122136
for ty::adjustment::AutoBorrow<'gcx> {
123137
fn hash_stable<W: StableHasherResult>(&self,
@@ -804,12 +818,6 @@ impl_stable_hash_for!(struct ty::Destructor {
804818
did
805819
});
806820

807-
impl_stable_hash_for!(struct ty::DtorckConstraint<'tcx> {
808-
outlives,
809-
dtorck_types
810-
});
811-
812-
813821
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CrateVariancesMap {
814822
fn hash_stable<W: StableHasherResult>(&self,
815823
hcx: &mut StableHashingContext<'gcx>,
@@ -1028,3 +1036,58 @@ for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContex
10281036
nested.hash_stable(hcx, hasher);
10291037
}
10301038
}
1039+
1040+
impl<'gcx, V> HashStable<StableHashingContext<'gcx>>
1041+
for canonical::Canonical<V> where V: HashStable<StableHashingContext<'gcx>> {
1042+
fn hash_stable<W: StableHasherResult>(&self,
1043+
hcx: &mut StableHashingContext<'gcx>,
1044+
hasher: &mut StableHasher<W>) {
1045+
let canonical::Canonical {
1046+
variables,
1047+
value,
1048+
} = self;
1049+
variables.hash_stable(hcx, hasher);
1050+
value.hash_stable(hcx, hasher);
1051+
}
1052+
}
1053+
1054+
impl<'gcx> HashStable<StableHashingContext<'gcx>>
1055+
for canonical::CanonicalVarValues<'gcx> {
1056+
fn hash_stable<W: StableHasherResult>(&self,
1057+
hcx: &mut StableHashingContext<'gcx>,
1058+
hasher: &mut StableHasher<W>) {
1059+
let canonical::CanonicalVarValues {
1060+
var_values,
1061+
} = self;
1062+
var_values.hash_stable(hcx, hasher);
1063+
}
1064+
}
1065+
1066+
impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo {
1067+
kind
1068+
});
1069+
1070+
impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
1071+
Ty(k),
1072+
Region
1073+
});
1074+
1075+
impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
1076+
General,
1077+
Int,
1078+
Float
1079+
});
1080+
1081+
impl_stable_hash_for!(
1082+
impl<'tcx, R> for struct infer::canonical::QueryResult<'tcx, R> {
1083+
var_values, region_constraints, certainty, value
1084+
}
1085+
);
1086+
1087+
impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> {
1088+
region_outlives, ty_outlives
1089+
});
1090+
1091+
impl_stable_hash_for!(enum infer::canonical::Certainty {
1092+
Proven, Ambiguous
1093+
});

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)