Skip to content

Commit

Permalink
Auto merge of #48411 - nikomatsakis:chalkify-canonical-query-mir, r=<…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
bors committed Feb 24, 2018
2 parents 063deba + 41d762f commit 251f865
Show file tree
Hide file tree
Showing 104 changed files with 3,440 additions and 1,671 deletions.
18 changes: 18 additions & 0 deletions src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 32 additions & 27 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,17 @@
//! user of the `DepNode` API of having to know how to compute the expected
//! fingerprint for a given set of node parameters.

use ich::{Fingerprint, StableHashingContext};
use infer::canonical::Canonical;
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
use hir::map::DefPathHash;
use hir::{HirId, ItemLocalId};

use ich::Fingerprint;
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
use ty::subst::Substs;
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
use ich::StableHashingContext;
use std::fmt;
use std::hash::Hash;
use syntax_pos::symbol::InternedString;
use ty::{self, TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
use ty::subst::Substs;

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

macro_rules! replace {
($x:tt with $($y:tt)*) => ($($y)*)
}

macro_rules! is_anon_attr {
(anon) => (true);
($attr:ident) => (false);
Expand Down Expand Up @@ -111,7 +114,7 @@ macro_rules! define_dep_nodes {
(<$tcx:tt>
$(
[$($attr:ident),* ]
$variant:ident $(( $($tuple_arg:tt),* ))*
$variant:ident $(( $tuple_arg_ty:ty $(,)* ))*
$({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })*
,)*
) => (
Expand All @@ -134,7 +137,7 @@ macro_rules! define_dep_nodes {

// tuple args
$({
return <( $($tuple_arg,)* ) as DepNodeParams>
return <$tuple_arg_ty as DepNodeParams>
::CAN_RECONSTRUCT_QUERY_KEY;
})*

Expand Down Expand Up @@ -186,7 +189,7 @@ macro_rules! define_dep_nodes {
DepKind :: $variant => {
// tuple args
$({
$(erase!($tuple_arg);)*
erase!($tuple_arg_ty);
return true;
})*

Expand All @@ -205,7 +208,7 @@ macro_rules! define_dep_nodes {

pub enum DepConstructor<$tcx> {
$(
$variant $(( $($tuple_arg),* ))*
$variant $(( $tuple_arg_ty ))*
$({ $($struct_arg_name : $struct_arg_ty),* })*
),*
}
Expand All @@ -227,15 +230,14 @@ macro_rules! define_dep_nodes {
{
match dep {
$(
DepConstructor :: $variant $(( $($tuple_arg),* ))*
DepConstructor :: $variant $(( replace!(($tuple_arg_ty) with arg) ))*
$({ $($struct_arg_name),* })*
=>
{
// tuple args
$({
let tupled_args = ( $($tuple_arg,)* );
let hash = DepNodeParams::to_fingerprint(&tupled_args,
tcx);
erase!($tuple_arg_ty);
let hash = DepNodeParams::to_fingerprint(&arg, tcx);
let dep_node = DepNode {
kind: DepKind::$variant,
hash
Expand All @@ -247,7 +249,7 @@ macro_rules! define_dep_nodes {
tcx.sess.opts.debugging_opts.query_dep_graph)
{
tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
tupled_args.to_debug_str(tcx)
arg.to_debug_str(tcx)
});
}

Expand Down Expand Up @@ -629,7 +631,10 @@ define_dep_nodes!( <'tcx>
[] CodegenUnit(InternedString),
[] CompileCodegenUnit(InternedString),
[input] OutputFilenames,
[anon] NormalizeTy,
[] NormalizeProjectionTy(&'tcx Canonical<ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>),
[] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
[] DropckOutlives(&'tcx Canonical<ParamEnvAnd<'tcx, Ty<'tcx>>>),

// We use this for most things when incr. comp. is turned off.
[] Null,

Expand Down Expand Up @@ -679,43 +684,43 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
}
}

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

fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
tcx.def_path_hash(self.0).0
tcx.def_path_hash(*self).0
}

fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
tcx.item_path_str(self.0)
tcx.item_path_str(*self)
}
}

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

fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
tcx.hir.definitions().def_path_hash(self.0).0
tcx.hir.definitions().def_path_hash(*self).0
}

fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
tcx.item_path_str(DefId::local(self.0))
tcx.item_path_str(DefId::local(*self))
}
}

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

fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
let def_id = DefId {
krate: self.0,
krate: *self,
index: CRATE_DEF_INDEX,
};
tcx.def_path_hash(def_id).0
}

fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
tcx.crate_name(self.0).as_str().to_string()
tcx.crate_name(*self).as_str().to_string()
}
}

Expand Down Expand Up @@ -743,17 +748,17 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, De
}
}

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

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

let def_path_hash = tcx.def_path_hash(DefId::local(owner));
let local_id = Fingerprint::from_smaller_hash(local_id as u64);
Expand Down
75 changes: 69 additions & 6 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use std::cell::RefCell;
use std::hash as std_hash;
use std::mem;
use middle::region;
use infer::{self, canonical};
use traits;
use ty;

Expand Down Expand Up @@ -73,6 +74,9 @@ for ty::RegionKind {
ty::ReEmpty => {
// No variant fields to hash for these ...
}
ty::ReCanonical(c) => {
c.hash_stable(hcx, hasher);
}
ty::ReLateBound(db, ty::BrAnon(i)) => {
db.depth.hash_stable(hcx, hasher);
i.hash_stable(hcx, hasher);
Expand Down Expand Up @@ -118,6 +122,16 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::RegionVid {
}
}

impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CanonicalVar {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
use rustc_data_structures::indexed_vec::Idx;
self.index().hash_stable(hcx, hasher);
}
}

impl<'gcx> HashStable<StableHashingContext<'gcx>>
for ty::adjustment::AutoBorrow<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
Expand Down Expand Up @@ -804,12 +818,6 @@ impl_stable_hash_for!(struct ty::Destructor {
did
});

impl_stable_hash_for!(struct ty::DtorckConstraint<'tcx> {
outlives,
dtorck_types
});


impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CrateVariancesMap {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
Expand Down Expand Up @@ -1028,3 +1036,58 @@ for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContex
nested.hash_stable(hcx, hasher);
}
}

impl<'gcx, V> HashStable<StableHashingContext<'gcx>>
for canonical::Canonical<V> where V: HashStable<StableHashingContext<'gcx>> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
let canonical::Canonical {
variables,
value,
} = self;
variables.hash_stable(hcx, hasher);
value.hash_stable(hcx, hasher);
}
}

impl<'gcx> HashStable<StableHashingContext<'gcx>>
for canonical::CanonicalVarValues<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
let canonical::CanonicalVarValues {
var_values,
} = self;
var_values.hash_stable(hcx, hasher);
}
}

impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo {
kind
});

impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
Ty(k),
Region
});

impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
General,
Int,
Float
});

impl_stable_hash_for!(
impl<'tcx, R> for struct infer::canonical::QueryResult<'tcx, R> {
var_values, region_constraints, certainty, value
}
);

impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> {
region_outlives, ty_outlives
});

impl_stable_hash_for!(enum infer::canonical::Certainty {
Proven, Ambiguous
});
20 changes: 17 additions & 3 deletions src/librustc/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ use super::*;
use ty::relate::{Relate, TypeRelation};

pub struct At<'a, 'gcx: 'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
cause: &'a ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
pub cause: &'a ObligationCause<'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
}

pub struct Trace<'a, 'gcx: 'tcx, 'tcx: 'a> {
Expand Down Expand Up @@ -281,6 +281,20 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
}
}

impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>,
a_is_expected: bool,
a: Self,
b: Self)
-> TypeTrace<'tcx>
{
TypeTrace {
cause: cause.clone(),
values: Regions(ExpectedFound::new(a_is_expected, a, b))
}
}
}

impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>,
a_is_expected: bool,
Expand Down
Loading

0 comments on commit 251f865

Please sign in to comment.