Skip to content

Commit 4ca65af

Browse files
committed
rustc_typeck: rework coherence to be almost completely on-demand.
1 parent c944160 commit 4ca65af

File tree

53 files changed

+824
-670
lines changed

Some content is hidden

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

53 files changed

+824
-670
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub enum DepNode<D: Clone + Debug> {
7070
Resolve,
7171
EntryPoint,
7272
CheckEntryFn,
73+
CoherenceCheckTrait(D),
7374
CoherenceCheckImpl(D),
7475
CoherenceOverlapCheck(D),
7576
CoherenceOverlapCheckSpecial(D),
@@ -241,6 +242,7 @@ impl<D: Clone + Debug> DepNode<D> {
241242
MetaData(ref d) => op(d).map(MetaData),
242243
CollectItem(ref d) => op(d).map(CollectItem),
243244
CollectItemSig(ref d) => op(d).map(CollectItemSig),
245+
CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait),
244246
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
245247
CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
246248
CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),

src/librustc/hir/lowering.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ pub struct LoweringContext<'a> {
8080
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
8181
bodies: FxHashMap<hir::BodyId, hir::Body>,
8282

83+
trait_impls: BTreeMap<DefId, Vec<NodeId>>,
84+
trait_default_impl: BTreeMap<DefId, NodeId>,
85+
8386
loop_scopes: Vec<NodeId>,
8487
is_in_loop_condition: bool,
8588

@@ -116,6 +119,8 @@ pub fn lower_crate(sess: &Session,
116119
trait_items: BTreeMap::new(),
117120
impl_items: BTreeMap::new(),
118121
bodies: FxHashMap(),
122+
trait_impls: BTreeMap::new(),
123+
trait_default_impl: BTreeMap::new(),
119124
loop_scopes: Vec::new(),
120125
is_in_loop_condition: false,
121126
type_def_lifetime_params: DefIdMap(),
@@ -201,6 +206,8 @@ impl<'a> LoweringContext<'a> {
201206
trait_items: self.trait_items,
202207
impl_items: self.impl_items,
203208
bodies: self.bodies,
209+
trait_impls: self.trait_impls,
210+
trait_default_impl: self.trait_default_impl,
204211
}
205212
}
206213

@@ -1089,14 +1096,27 @@ impl<'a> LoweringContext<'a> {
10891096
hir::ItemUnion(vdata, self.lower_generics(generics))
10901097
}
10911098
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
1099+
let trait_ref = self.lower_trait_ref(trait_ref);
1100+
1101+
if let Def::Trait(def_id) = trait_ref.path.def {
1102+
self.trait_default_impl.insert(def_id, id);
1103+
}
1104+
10921105
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
1093-
self.lower_trait_ref(trait_ref))
1106+
trait_ref)
10941107
}
10951108
ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
10961109
let new_impl_items = impl_items.iter()
10971110
.map(|item| self.lower_impl_item_ref(item))
10981111
.collect();
10991112
let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
1113+
1114+
if let Some(ref trait_ref) = ifce {
1115+
if let Def::Trait(def_id) = trait_ref.path.def {
1116+
self.trait_impls.entry(def_id).or_insert(vec![]).push(id);
1117+
}
1118+
}
1119+
11001120
hir::ItemImpl(self.lower_unsafety(unsafety),
11011121
self.lower_impl_polarity(polarity),
11021122
self.lower_generics(generics),

src/librustc/hir/map/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,26 @@ impl<'hir> Map<'hir> {
461461
}
462462
}
463463

464+
pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] {
465+
self.dep_graph.read(DepNode::TraitImpls(trait_did));
466+
467+
// NB: intentionally bypass `self.forest.krate()` so that we
468+
// do not trigger a read of the whole krate here
469+
self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
470+
}
471+
472+
pub fn trait_default_impl(&self, trait_did: DefId) -> Option<NodeId> {
473+
self.dep_graph.read(DepNode::TraitImpls(trait_did));
474+
475+
// NB: intentionally bypass `self.forest.krate()` so that we
476+
// do not trigger a read of the whole krate here
477+
self.forest.krate.trait_default_impl.get(&trait_did).cloned()
478+
}
479+
480+
pub fn trait_is_auto(&self, trait_did: DefId) -> bool {
481+
self.trait_default_impl(trait_did).is_some()
482+
}
483+
464484
/// Get the attributes on the krate. This is preferable to
465485
/// invoking `krate.attrs` because it registers a tighter
466486
/// dep-graph access.

src/librustc/hir/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,9 @@ pub struct Crate {
410410
pub trait_items: BTreeMap<TraitItemId, TraitItem>,
411411
pub impl_items: BTreeMap<ImplItemId, ImplItem>,
412412
pub bodies: FxHashMap<BodyId, Body>,
413+
414+
pub trait_impls: BTreeMap<DefId, Vec<NodeId>>,
415+
pub trait_default_impl: BTreeMap<DefId, NodeId>,
413416
}
414417

415418
impl Crate {

src/librustc/infer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
505505
evaluation_cache: traits::EvaluationCache::new(),
506506
projection_cache: RefCell::new(traits::ProjectionCache::new()),
507507
reported_trait_errors: RefCell::new(FxHashSet()),
508-
projection_mode: Reveal::NotSpecializable,
508+
projection_mode: Reveal::UserFacing,
509509
tainted_by_errors_flag: Cell::new(false),
510510
err_count_on_creation: self.sess.err_count(),
511511
obligations_in_snapshot: Cell::new(false),

src/librustc/middle/cstore.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ pub trait CrateStore {
191191

192192
// flags
193193
fn is_const_fn(&self, did: DefId) -> bool;
194-
fn is_defaulted_trait(&self, did: DefId) -> bool;
195194
fn is_default_impl(&self, impl_did: DefId) -> bool;
196195
fn is_foreign_item(&self, did: DefId) -> bool;
197196
fn is_dllimport_foreign_item(&self, def: DefId) -> bool;
@@ -327,7 +326,6 @@ impl CrateStore for DummyCrateStore {
327326

328327
// flags
329328
fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
330-
fn is_defaulted_trait(&self, did: DefId) -> bool { bug!("is_defaulted_trait") }
331329
fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
332330
fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") }
333331
fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false }

src/librustc/traits/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
473473

474474
let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
475475

476-
tcx.infer_ctxt(elaborated_env, Reveal::NotSpecializable).enter(|infcx| {
476+
tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
477477
let predicates = match fully_normalize(&infcx, cause,
478478
&infcx.parameter_environment.caller_bounds) {
479479
Ok(predicates) => predicates,

src/librustc/traits/project.rs

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -38,36 +38,6 @@ use util::common::FN_OUTPUT_NAME;
3838
/// more or less conservative.
3939
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4040
pub enum Reveal {
41-
/// FIXME (#32205)
42-
/// At coherence-checking time, we're still constructing the
43-
/// specialization graph, and thus we only project
44-
/// non-`default` associated types that are defined directly in
45-
/// the applicable impl. (This behavior should be improved over
46-
/// time, to allow for successful projections modulo cycles
47-
/// between different impls).
48-
///
49-
/// Here's an example that will fail due to the restriction:
50-
///
51-
/// ```
52-
/// trait Assoc {
53-
/// type Output;
54-
/// }
55-
///
56-
/// impl<T> Assoc for T {
57-
/// type Output = bool;
58-
/// }
59-
///
60-
/// impl Assoc for u8 {} // <- inherits the non-default type from above
61-
///
62-
/// trait Foo {}
63-
/// impl Foo for u32 {}
64-
/// impl Foo for <u8 as Assoc>::Output {} // <- this projection will fail
65-
/// ```
66-
///
67-
/// The projection would succeed if `Output` had been defined
68-
/// directly in the impl for `u8`.
69-
ExactMatch,
70-
7141
/// At type-checking time, we refuse to project any associated
7242
/// type that is marked `default`. Non-`default` ("final") types
7343
/// are always projected. This is necessary in general for
@@ -90,7 +60,7 @@ pub enum Reveal {
9060
/// fn main() {
9161
/// let <() as Assoc>::Output = true;
9262
/// }
93-
NotSpecializable,
63+
UserFacing,
9464

9565
/// At trans time, all monomorphic projections will succeed.
9666
/// Also, `impl Trait` is normalized to the concrete type,
@@ -1347,8 +1317,9 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
13471317
-> Option<specialization_graph::NodeItem<ty::AssociatedItem>>
13481318
{
13491319
let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id;
1320+
let trait_def = selcx.tcx().lookup_trait_def(trait_def_id);
13501321

1351-
if selcx.projection_mode() == Reveal::ExactMatch {
1322+
if !trait_def.is_complete(selcx.tcx()) {
13521323
let impl_node = specialization_graph::Node::Impl(impl_def_id);
13531324
for item in impl_node.items(selcx.tcx()) {
13541325
if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
@@ -1360,7 +1331,7 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
13601331
}
13611332
None
13621333
} else {
1363-
selcx.tcx().lookup_trait_def(trait_def_id)
1334+
trait_def
13641335
.ancestors(impl_def_id)
13651336
.defs(selcx.tcx(), assoc_ty_name, ty::AssociatedKind::Type)
13661337
.next()

src/librustc/traits/specialize/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
189189
.subst(tcx, &penv.free_substs);
190190

191191
// Create a infcx, taking the predicates of impl1 as assumptions:
192-
let result = tcx.infer_ctxt(penv, Reveal::ExactMatch).enter(|infcx| {
192+
let result = tcx.infer_ctxt(penv, Reveal::UserFacing).enter(|infcx| {
193193
// Normalize the trait reference. The WF rules ought to ensure
194194
// that this always succeeds.
195195
let impl1_trait_ref =

src/librustc/traits/specialize/specialization_graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> Children {
108108
let possible_sibling = *slot;
109109

110110
let tcx = tcx.global_tcx();
111-
let (le, ge) = tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| {
111+
let (le, ge) = tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
112112
let overlap = traits::overlapping_impls(&infcx,
113113
possible_sibling,
114114
impl_def_id);

0 commit comments

Comments
 (0)