Skip to content

Commit 4ca65af

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

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

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

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

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

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

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

-2
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

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

+4-33
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

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

+1-1
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);

src/librustc/ty/contents.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
219219
res = res - TC::OwnsDtor;
220220
}
221221

222-
if def.has_dtor() {
222+
if def.has_dtor(tcx) {
223223
res = res | TC::OwnsDtor;
224224
}
225225

src/librustc/ty/maps.rs

+49
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ trait Key {
2424
fn default_span(&self, tcx: TyCtxt) -> Span;
2525
}
2626

27+
impl Key for CrateNum {
28+
fn map_crate(&self) -> CrateNum {
29+
*self
30+
}
31+
fn default_span(&self, _: TyCtxt) -> Span {
32+
DUMMY_SP
33+
}
34+
}
35+
2736
impl Key for DefId {
2837
fn map_crate(&self) -> CrateNum {
2938
self.krate
@@ -42,6 +51,15 @@ impl Key for (DefId, DefId) {
4251
}
4352
}
4453

54+
impl Key for (CrateNum, DefId) {
55+
fn map_crate(&self) -> CrateNum {
56+
self.0
57+
}
58+
fn default_span(&self, tcx: TyCtxt) -> Span {
59+
self.1.default_span(tcx)
60+
}
61+
}
62+
4563
trait Value<'tcx>: Sized {
4664
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
4765
}
@@ -141,6 +159,19 @@ impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> {
141159
}
142160
}
143161

162+
impl<'tcx> QueryDescription for queries::coherent_trait<'tcx> {
163+
fn describe(tcx: TyCtxt, (_, def_id): (CrateNum, DefId)) -> String {
164+
format!("coherence checking all impls of trait `{}`",
165+
tcx.item_path_str(def_id))
166+
}
167+
}
168+
169+
impl<'tcx> QueryDescription for queries::coherent_inherent_impls<'tcx> {
170+
fn describe(_: TyCtxt, _: CrateNum) -> String {
171+
format!("coherence checking all inherent impls")
172+
}
173+
}
174+
144175
macro_rules! define_maps {
145176
(<$tcx:tt>
146177
$($(#[$attr:meta])*
@@ -238,6 +269,12 @@ macro_rules! define_maps {
238269
}
239270

240271
pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
272+
// FIXME(eddyb) Move away from using `DepTrackingMap`
273+
// so we don't have to explicitly ignore a false edge:
274+
// we can't observe a value dependency, only side-effects,
275+
// through `force`, and once everything has been updated,
276+
// perhaps only diagnostics, if those, will remain.
277+
let _ignore = tcx.dep_graph.in_ignore();
241278
match Self::try_get_with(tcx, span, key, |_| ()) {
242279
Ok(()) => {}
243280
Err(e) => tcx.report_cycle(e)
@@ -338,7 +375,19 @@ define_maps! { <'tcx>
338375

339376
pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
340377

378+
pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
379+
380+
pub coherent_inherent_impls: coherent_inherent_impls_dep_node(CrateNum) -> (),
381+
341382
/// Results of evaluating monomorphic constants embedded in
342383
/// other items, such as enum variant explicit discriminants.
343384
pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal, ()>
344385
}
386+
387+
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
388+
DepNode::CoherenceCheckTrait(def_id)
389+
}
390+
391+
fn coherent_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
392+
DepNode::Coherence
393+
}

0 commit comments

Comments
 (0)