about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/traits/coherence.rs39
-rw-r--r--src/librustc/traits/mod.rs3
-rw-r--r--src/librustc/traits/specialize/mod.rs6
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs1
-rw-r--r--src/librustc_typeck/coherence/inherent_impls_overlap.rs4
-rw-r--r--src/test/ui/coherence/coherence-subtyping.stderr2
6 files changed, 48 insertions, 7 deletions
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 980c98d2a2d..b3d732ebcd7 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<IntercrateAmbiguityCause>,
+
+    /// 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<OverlapResult<'tcx>>
-{
+fn overlap<'cx, 'gcx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
+    a_def_id: DefId,
+    b_def_id: DefId,
+) -> Option<OverlapResult<'tcx>> {
     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<OverlapResult<'tcx>> {
     // 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 0377b98d3f8..b42d742b7f8 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 f5d68ddb5bd..63f52a34dfa 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<String>,
     pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
+    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 fd68917e539..db3547b2b74 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 e568320ba8e..8d27a77b29c 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 1f9b2cb6fdf..b29a918f2d9 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