From d153ff3f793429e435ca6a3df78db925f2b81816 Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Tue, 1 Aug 2017 10:27:25 +0430 Subject: [PATCH] Print more detailed trait-ref for intercrate ambiguity. --- src/librustc/traits/select.rs | 57 ++++++++++++++----- src/librustc/traits/specialize/mod.rs | 2 +- .../coherence/inherent_impls_overlap.rs | 2 +- .../coherence-overlap-issue-23516-inherent.rs | 2 +- .../coherence-overlap-issue-23516.rs | 2 +- .../coherence-overlap-upstream-inherent.rs | 2 +- .../coherence-overlap-upstream.rs | 2 +- .../overlapping_inherent_impls.stderr | 2 +- 8 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 366bb6aeb5ca..693b9c147c2a 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -96,25 +96,36 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { #[derive(Clone)] pub enum IntercrateAmbiguityCause { - DownstreamCrate(DefId), - UpstreamCrateUpdate(DefId), + DownstreamCrate { + trait_desc: String, + self_desc: Option, + }, + UpstreamCrateUpdate { + trait_desc: String, + self_desc: Option, + }, } impl IntercrateAmbiguityCause { /// Emits notes when the overlap is caused by complex intercrate ambiguities. /// See #23980 for details. pub fn add_intercrate_ambiguity_hint<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, err: &mut ::errors::DiagnosticBuilder) { match self { - &IntercrateAmbiguityCause::DownstreamCrate(def_id) => { - err.note(&format!("downstream crates may implement `{}`", - tcx.item_path_str(def_id))); + &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => { + let self_desc = if let &Some(ref ty) = self_desc { + format!(" for type `{}`", ty) + } else { "".to_string() }; + err.note(&format!("downstream crates may implement trait `{}`{}", + trait_desc, self_desc)); } - &IntercrateAmbiguityCause::UpstreamCrateUpdate(def_id) => { - err.note(&format!("upstream crates may add new impl for `{}` \ + &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => { + let self_desc = if let &Some(ref ty) = self_desc { + format!(" for type `{}`", ty) + } else { "".to_string() }; + err.note(&format!("upstream crates may add new impl of trait `{}`{} \ in future versions", - tcx.item_path_str(def_id))); + trait_desc, self_desc)); } } } @@ -794,9 +805,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Heuristics: show the diagnostics when there are no candidates in crate. if let Ok(candidate_set) = self.assemble_candidates(stack) { if !candidate_set.ambiguous && candidate_set.vec.is_empty() { - let did = stack.fresh_trait_ref.def_id(); - self.intercrate_ambiguity_causes.push( - IntercrateAmbiguityCause::DownstreamCrate(did)); + let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; + let self_ty = trait_ref.self_ty(); + let cause = IntercrateAmbiguityCause::DownstreamCrate { + trait_desc: trait_ref.to_string(), + self_desc: if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }, + }; + self.intercrate_ambiguity_causes.push(cause); } } return EvaluatedToAmbig; @@ -1048,9 +1067,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Heuristics: show the diagnostics when there are no candidates in crate. let candidate_set = self.assemble_candidates(stack)?; if !candidate_set.ambiguous && candidate_set.vec.is_empty() { - let did = stack.obligation.predicate.def_id(); - self.intercrate_ambiguity_causes.push( - IntercrateAmbiguityCause::UpstreamCrateUpdate(did)); + let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; + let self_ty = trait_ref.self_ty(); + let cause = IntercrateAmbiguityCause::UpstreamCrateUpdate { + trait_desc: trait_ref.to_string(), + self_desc: if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }, + }; + self.intercrate_ambiguity_causes.push(cause); } return Ok(None); } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 98d8c64634c6..f9332fc6697e 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -340,7 +340,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx } for cause in &overlap.intercrate_ambiguity_causes { - cause.add_intercrate_ambiguity_hint(tcx, &mut err); + cause.add_intercrate_ambiguity_hint(&mut err); } err.emit(); diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 0fad16c95822..76dcfe36e4fc 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -63,7 +63,7 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { format!("other definition for `{}`", name)); for cause in &overlap.intercrate_ambiguity_causes { - cause.add_intercrate_ambiguity_hint(self.tcx, &mut err); + cause.add_intercrate_ambiguity_hint(&mut err); } err.emit(); diff --git a/src/test/compile-fail/coherence-overlap-issue-23516-inherent.rs b/src/test/compile-fail/coherence-overlap-issue-23516-inherent.rs index dfdcc1bc7cb4..9b8ad51c5ff7 100644 --- a/src/test/compile-fail/coherence-overlap-issue-23516-inherent.rs +++ b/src/test/compile-fail/coherence-overlap-issue-23516-inherent.rs @@ -19,7 +19,7 @@ struct Cake(X); impl Cake { fn dummy(&self) { } } //~^ ERROR E0592 //~| NOTE duplicate definitions for `dummy` -//~| NOTE upstream crates may add new impl for `Sugar` in future versions +//~| NOTE upstream crates may add new impl of trait `Sugar` for type `std::boxed::Box<_>` impl Cake> { fn dummy(&self) { } } //~^ NOTE other definition for `dummy` diff --git a/src/test/compile-fail/coherence-overlap-issue-23516.rs b/src/test/compile-fail/coherence-overlap-issue-23516.rs index ffde4011ee4d..950d1fe29bb9 100644 --- a/src/test/compile-fail/coherence-overlap-issue-23516.rs +++ b/src/test/compile-fail/coherence-overlap-issue-23516.rs @@ -19,6 +19,6 @@ impl Sweet for T { } impl Sweet for Box { } //~^ ERROR E0119 //~| NOTE conflicting implementation for `std::boxed::Box<_>` -//~| NOTE upstream crates may add new impl for `Sugar` in future versions +//~| NOTE upstream crates may add new impl of trait `Sugar` for type `std::boxed::Box<_>` fn main() { } diff --git a/src/test/compile-fail/coherence-overlap-upstream-inherent.rs b/src/test/compile-fail/coherence-overlap-upstream-inherent.rs index 2ec51b1bbe33..1d0c63110cec 100644 --- a/src/test/compile-fail/coherence-overlap-upstream-inherent.rs +++ b/src/test/compile-fail/coherence-overlap-upstream-inherent.rs @@ -21,7 +21,7 @@ struct A(X); impl A where T: Remote { fn dummy(&self) { } } //~^ ERROR E0592 //~| NOTE duplicate definitions for `dummy` -//~| NOTE upstream crates may add new impl for `coherence_lib::Remote` in future versions +//~| NOTE upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` impl A { fn dummy(&self) { } } //~^ NOTE other definition for `dummy` diff --git a/src/test/compile-fail/coherence-overlap-upstream.rs b/src/test/compile-fail/coherence-overlap-upstream.rs index 81c22e068505..e978143a067c 100644 --- a/src/test/compile-fail/coherence-overlap-upstream.rs +++ b/src/test/compile-fail/coherence-overlap-upstream.rs @@ -23,6 +23,6 @@ impl Foo for T where T: Remote {} impl Foo for i16 {} //~^ ERROR E0119 //~| NOTE conflicting implementation for `i16` -//~| NOTE upstream crates may add new impl for `coherence_lib::Remote` in future versions +//~| NOTE upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` fn main() {} diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr index f6ca4f15f9ed..eaf42cde22f7 100644 --- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr +++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr @@ -25,7 +25,7 @@ error[E0592]: duplicate definitions with name `baz` 43 | fn baz(&self) {} | ---------------- other definition for `baz` | - = note: upstream crates may add new impl for `std::marker::Copy` in future versions + = note: upstream crates may add new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions error: aborting due to 3 previous errors