Skip to content

Commit f17caab

Browse files
nikomatsakisJohnHeitmann
authored andcommitted
try to detect affected code and direct people to rust-lang#56105
1 parent 0c81a2f commit f17caab

File tree

6 files changed

+48
-7
lines changed

6 files changed

+48
-7
lines changed

src/librustc/traits/coherence.rs

+33-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
55
//! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
66
7+
use infer::CombinedSnapshot;
78
use hir::def_id::{DefId, LOCAL_CRATE};
89
use syntax_pos::DUMMY_SP;
910
use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause};
@@ -33,6 +34,17 @@ pub enum Conflict {
3334
pub struct OverlapResult<'tcx> {
3435
pub impl_header: ty::ImplHeader<'tcx>,
3536
pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
37+
38+
/// True if the overlap might've been permitted before the shift
39+
/// to universes.
40+
pub involves_placeholder: bool,
41+
}
42+
43+
pub fn add_placeholder_note(err: &mut ::errors::DiagnosticBuilder<'_>) {
44+
err.note(&format!(
45+
"this behavior recently changed as a result of a bug fix; \
46+
see rust-lang/rust#56105 for details"
47+
));
3648
}
3749

3850
/// If there are types that satisfy both impls, invokes `on_overlap`
@@ -104,13 +116,22 @@ fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, '
104116

105117
/// Can both impl `a` and impl `b` be satisfied by a common type (including
106118
/// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls.
107-
fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
108-
a_def_id: DefId,
109-
b_def_id: DefId)
110-
-> Option<OverlapResult<'tcx>>
111-
{
119+
fn overlap<'cx, 'gcx, 'tcx>(
120+
selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
121+
a_def_id: DefId,
122+
b_def_id: DefId,
123+
) -> Option<OverlapResult<'tcx>> {
112124
debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
113125

126+
selcx.infcx().probe(|snapshot| overlap_within_probe(selcx, a_def_id, b_def_id, snapshot))
127+
}
128+
129+
fn overlap_within_probe(
130+
selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
131+
a_def_id: DefId,
132+
b_def_id: DefId,
133+
snapshot: &CombinedSnapshot<'_, 'tcx>,
134+
) -> Option<OverlapResult<'tcx>> {
114135
// For the purposes of this check, we don't bring any placeholder
115136
// types into scope; instead, we replace the generic types with
116137
// fresh type variables, and hence we do our evaluations in an
@@ -158,7 +179,13 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
158179
let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
159180
let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
160181
debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
161-
Some(OverlapResult { impl_header, intercrate_ambiguity_causes })
182+
183+
let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) {
184+
Some(true) => true,
185+
_ => false,
186+
};
187+
188+
Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
162189
}
163190

164191
pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,

src/librustc/traits/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ pub use self::FulfillmentErrorCode::*;
4343
pub use self::Vtable::*;
4444
pub use self::ObligationCauseCode::*;
4545

46-
pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult};
46+
pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
47+
pub use self::coherence::{OrphanCheckErr, OverlapResult};
4748
pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
4849
pub use self::project::MismatchedProjectionTypes;
4950
pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type};

src/librustc/traits/specialize/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use hir::def_id::DefId;
1515
use infer::{InferCtxt, InferOk};
1616
use lint;
1717
use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
18+
use traits::coherence;
1819
use rustc_data_structures::fx::FxHashSet;
1920
use rustc_data_structures::sync::Lrc;
2021
use syntax_pos::DUMMY_SP;
@@ -32,6 +33,7 @@ pub struct OverlapError {
3233
pub trait_desc: String,
3334
pub self_desc: Option<String>,
3435
pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
36+
pub involves_placeholder: bool,
3537
}
3638

3739
/// Given a subst for the requested impl, translate it to a subst
@@ -370,6 +372,10 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
370372
cause.add_intercrate_ambiguity_hint(&mut err);
371373
}
372374

375+
if overlap.involves_placeholder {
376+
coherence::add_placeholder_note(&mut err);
377+
}
378+
373379
err.emit();
374380
}
375381
} else {

src/librustc/traits/specialize/specialization_graph.rs

+1
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ impl<'a, 'gcx, 'tcx> Children {
164164
None
165165
},
166166
intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
167+
involves_placeholder: overlap.involves_placeholder,
167168
}
168169
};
169170

src/librustc_typeck/coherence/inherent_impls_overlap.rs

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
7373
cause.add_intercrate_ambiguity_hint(&mut err);
7474
}
7575

76+
if overlap.involves_placeholder {
77+
traits::add_placeholder_note(&mut err);
78+
}
79+
7680
err.emit();
7781
}
7882
}

src/test/ui/coherence/coherence-subtyping.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 {
66
...
77
LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 {
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
9+
|
10+
= note: this behavior recently changed as a result of a bug fix; see #XXX for details
911

1012
error: aborting due to previous error
1113

0 commit comments

Comments
 (0)