From 4c8fd2e80af577b105428ae5403ba13f289a7cf5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 20 Nov 2018 11:20:05 -0500 Subject: [PATCH] try to detect affected code and direct people to #56105 --- src/librustc/traits/coherence.rs | 39 ++++++++++++++++--- src/librustc/traits/mod.rs | 3 +- src/librustc/traits/specialize/mod.rs | 6 +++ .../traits/specialize/specialization_graph.rs | 1 + .../coherence/inherent_impls_overlap.rs | 4 ++ .../ui/coherence/coherence-subtyping.stderr | 2 + 6 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 980c98d2a2d50..b3d732ebcd7dc 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -4,6 +4,7 @@ //! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html //! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html +use infer::CombinedSnapshot; use hir::def_id::{DefId, LOCAL_CRATE}; use syntax_pos::DUMMY_SP; use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause}; @@ -33,6 +34,17 @@ pub enum Conflict { pub struct OverlapResult<'tcx> { pub impl_header: ty::ImplHeader<'tcx>, pub intercrate_ambiguity_causes: Vec, + + /// True if the overlap might've been permitted before the shift + /// to universes. + pub involves_placeholder: bool, +} + +pub fn add_placeholder_note(err: &mut ::errors::DiagnosticBuilder<'_>) { + err.note(&format!( + "this behavior recently changed as a result of a bug fix; \ + see rust-lang/rust#56105 for details" + )); } /// 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, ' /// Can both impl `a` and impl `b` be satisfied by a common type (including /// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls. -fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, - a_def_id: DefId, - b_def_id: DefId) - -> Option> -{ +fn overlap<'cx, 'gcx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, + a_def_id: DefId, + b_def_id: DefId, +) -> Option> { debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); + selcx.infcx().probe(|snapshot| overlap_within_probe(selcx, a_def_id, b_def_id, snapshot)) +} + +fn overlap_within_probe( + selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, + a_def_id: DefId, + b_def_id: DefId, + snapshot: &CombinedSnapshot<'_, 'tcx>, +) -> Option> { // For the purposes of this check, we don't bring any placeholder // types into scope; instead, we replace the generic types with // 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>, let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); - Some(OverlapResult { impl_header, intercrate_ambiguity_causes }) + + let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) { + Some(true) => true, + _ => false, + }; + + Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder }) } pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 0377b98d3f863..b42d742b7f841 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -43,7 +43,8 @@ pub use self::FulfillmentErrorCode::*; pub use self::Vtable::*; pub use self::ObligationCauseCode::*; -pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult}; +pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; +pub use self::coherence::{OrphanCheckErr, OverlapResult}; pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; pub use self::project::MismatchedProjectionTypes; pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type}; diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index f5d68ddb5bd46..63f52a34dfa70 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -15,6 +15,7 @@ use hir::def_id::DefId; use infer::{InferCtxt, InferOk}; use lint; use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; +use traits::coherence; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax_pos::DUMMY_SP; @@ -32,6 +33,7 @@ pub struct OverlapError { pub trait_desc: String, pub self_desc: Option, pub intercrate_ambiguity_causes: Vec, + pub involves_placeholder: bool, } /// Given a subst for the requested impl, translate it to a subst @@ -370,6 +372,10 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( cause.add_intercrate_ambiguity_hint(&mut err); } + if overlap.involves_placeholder { + coherence::add_placeholder_note(&mut err); + } + err.emit(); } } else { diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index fd68917e53991..db3547b2b7479 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -164,6 +164,7 @@ impl<'a, 'gcx, 'tcx> Children { None }, intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes, + involves_placeholder: overlap.involves_placeholder, } }; diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index e568320ba8e73..8d27a77b29c6c 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -73,6 +73,10 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { cause.add_intercrate_ambiguity_hint(&mut err); } + if overlap.involves_placeholder { + traits::add_placeholder_note(&mut err); + } + err.emit(); } } diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr index 1f9b2cb6fdfa3..b29a918f2d982 100644 --- a/src/test/ui/coherence/coherence-subtyping.stderr +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -6,6 +6,8 @@ LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { ... LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + | + = note: this behavior recently changed as a result of a bug fix; see #XXX for details error: aborting due to previous error