Skip to content

Commit a5c707a

Browse files
committed
intersection impls
1 parent 5ee891c commit a5c707a

File tree

7 files changed

+423
-127
lines changed

7 files changed

+423
-127
lines changed

src/librustc/traits/coherence.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! See rustc guide chapters on [trait-resolution] and [trait-specialization] for more info on how
12-
//! this works.
13-
//!
14-
//! [trait-resolution]: https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html
15-
//! [trait-specialization]: https://rust-lang-nursery.github.io/rustc-guide/trait-specialization.html
11+
//! See `README.md` for high-level documentation
1612
1713
use hir::def_id::{DefId, LOCAL_CRATE};
1814
use syntax_pos::DUMMY_SP;
19-
use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause};
15+
use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause, Reveal};
2016
use traits::IntercrateMode;
2117
use traits::select::IntercrateAmbiguityCause;
2218
use ty::{self, Ty, TyCtxt};
@@ -123,7 +119,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
123119
// types into scope; instead, we replace the generic types with
124120
// fresh type variables, and hence we do our evaluations in an
125121
// empty environment.
126-
let param_env = ty::ParamEnv::empty();
122+
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
127123

128124
let a_impl_header = with_fresh_ty_vars(selcx, param_env, a_def_id);
129125
let b_impl_header = with_fresh_ty_vars(selcx, param_env, b_def_id);
@@ -140,7 +136,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
140136
Err(_) => return None
141137
};
142138

143-
debug!("overlap: unification check succeeded");
139+
debug!("overlap: unification check succeeded {:?}", obligations);
144140

145141
// Are any of the obligations unsatisfiable? If so, no overlap.
146142
let infcx = selcx.infcx();
@@ -281,7 +277,7 @@ pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
281277
/// is bad, because the only local type with `T` as a subtree is
282278
/// `LocalType<T>`, and `Vec<->` is between it and the type parameter.
283279
/// - similarly, `FundamentalPair<LocalType<T>, T>` is bad, because
284-
/// the second occurrence of `T` is not a subtree of *any* local type.
280+
/// the second occurence of `T` is not a subtree of *any* local type.
285281
/// - however, `LocalType<Vec<T>>` is OK, because `T` is a subtree of
286282
/// `LocalType<Vec<T>>`, which is local and has no types between it and
287283
/// the type parameter.

src/librustc/traits/specialize/mod.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub struct OverlapError {
4242
pub trait_desc: String,
4343
pub self_desc: Option<String>,
4444
pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
45+
pub used_to_be_allowed: bool,
4546
}
4647

4748
/// Given a subst for the requested impl, translate it to a subst
@@ -324,29 +325,48 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
324325
def_id.index.as_array_index())
325326
});
326327

328+
let mut overlaps = Vec::new();
329+
327330
for impl_def_id in trait_impls {
328331
if impl_def_id.is_local() {
329-
// This is where impl overlap checking happens:
330332
let insert_result = sg.insert(tcx, impl_def_id);
331-
// Report error if there was one.
332-
let (overlap, used_to_be_allowed) = match insert_result {
333-
Err(overlap) => (Some(overlap), false),
334-
Ok(opt_overlap) => (opt_overlap, true)
333+
match insert_result {
334+
Ok(Some(mut opt_overlaps)) => {
335+
// record any overlap that occurs between two impl
336+
// later those recordings are processed to establish
337+
// if an intersection impl is present between two overlapping impls
338+
// if no an overlap error is emitted
339+
for opt_overlap in opt_overlaps {
340+
overlaps.push((impl_def_id, opt_overlap));
341+
}
342+
},
343+
_ => {},
335344
};
336345

337-
if let Some(overlap) = overlap {
346+
} else {
347+
let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
348+
sg.record_impl_from_cstore(tcx, parent, impl_def_id)
349+
}
350+
}
351+
352+
if overlaps.len() > 0 {
353+
// Build the graph only if there is at least an overlap
354+
let (graph, nodes_idx) = sg.build_graph();
355+
for (impl_def_id, overlap) in overlaps {
356+
if !sg.check_overlap(&graph, &nodes_idx, impl_def_id, overlap.with_impl) {
357+
338358
let msg = format!("conflicting implementations of trait `{}`{}:{}",
339359
overlap.trait_desc,
340360
overlap.self_desc.clone().map_or(
341361
String::new(), |ty| {
342362
format!(" for type `{}`", ty)
343363
}),
344-
if used_to_be_allowed { " (E0119)" } else { "" }
364+
if overlap.used_to_be_allowed { " (E0119)" } else { "" }
345365
);
346366
let impl_span = tcx.sess.codemap().def_span(
347367
tcx.span_of_impl(impl_def_id).unwrap()
348368
);
349-
let mut err = if used_to_be_allowed {
369+
let mut err = if overlap.used_to_be_allowed {
350370
tcx.struct_span_lint_node(
351371
lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
352372
tcx.hir.as_local_node_id(impl_def_id).unwrap(),
@@ -386,9 +406,6 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
386406

387407
err.emit();
388408
}
389-
} else {
390-
let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
391-
sg.record_impl_from_cstore(tcx, parent, impl_def_id)
392409
}
393410
}
394411

0 commit comments

Comments
 (0)