Skip to content

Commit d153ff3

Browse files
qnighynikomatsakis
authored andcommitted
Print more detailed trait-ref for intercrate ambiguity.
1 parent 84bfc33 commit d153ff3

File tree

8 files changed

+50
-23
lines changed

8 files changed

+50
-23
lines changed

src/librustc/traits/select.rs

+43-16
Original file line numberDiff line numberDiff line change
@@ -96,25 +96,36 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
9696

9797
#[derive(Clone)]
9898
pub enum IntercrateAmbiguityCause {
99-
DownstreamCrate(DefId),
100-
UpstreamCrateUpdate(DefId),
99+
DownstreamCrate {
100+
trait_desc: String,
101+
self_desc: Option<String>,
102+
},
103+
UpstreamCrateUpdate {
104+
trait_desc: String,
105+
self_desc: Option<String>,
106+
},
101107
}
102108

103109
impl IntercrateAmbiguityCause {
104110
/// Emits notes when the overlap is caused by complex intercrate ambiguities.
105111
/// See #23980 for details.
106112
pub fn add_intercrate_ambiguity_hint<'a, 'tcx>(&self,
107-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
108113
err: &mut ::errors::DiagnosticBuilder) {
109114
match self {
110-
&IntercrateAmbiguityCause::DownstreamCrate(def_id) => {
111-
err.note(&format!("downstream crates may implement `{}`",
112-
tcx.item_path_str(def_id)));
113-
}
114-
&IntercrateAmbiguityCause::UpstreamCrateUpdate(def_id) => {
115-
err.note(&format!("upstream crates may add new impl for `{}` \
115+
&IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
116+
let self_desc = if let &Some(ref ty) = self_desc {
117+
format!(" for type `{}`", ty)
118+
} else { "".to_string() };
119+
err.note(&format!("downstream crates may implement trait `{}`{}",
120+
trait_desc, self_desc));
121+
}
122+
&IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
123+
let self_desc = if let &Some(ref ty) = self_desc {
124+
format!(" for type `{}`", ty)
125+
} else { "".to_string() };
126+
err.note(&format!("upstream crates may add new impl of trait `{}`{} \
116127
in future versions",
117-
tcx.item_path_str(def_id)));
128+
trait_desc, self_desc));
118129
}
119130
}
120131
}
@@ -794,9 +805,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
794805
// Heuristics: show the diagnostics when there are no candidates in crate.
795806
if let Ok(candidate_set) = self.assemble_candidates(stack) {
796807
if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
797-
let did = stack.fresh_trait_ref.def_id();
798-
self.intercrate_ambiguity_causes.push(
799-
IntercrateAmbiguityCause::DownstreamCrate(did));
808+
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
809+
let self_ty = trait_ref.self_ty();
810+
let cause = IntercrateAmbiguityCause::DownstreamCrate {
811+
trait_desc: trait_ref.to_string(),
812+
self_desc: if self_ty.has_concrete_skeleton() {
813+
Some(self_ty.to_string())
814+
} else {
815+
None
816+
},
817+
};
818+
self.intercrate_ambiguity_causes.push(cause);
800819
}
801820
}
802821
return EvaluatedToAmbig;
@@ -1048,9 +1067,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10481067
// Heuristics: show the diagnostics when there are no candidates in crate.
10491068
let candidate_set = self.assemble_candidates(stack)?;
10501069
if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
1051-
let did = stack.obligation.predicate.def_id();
1052-
self.intercrate_ambiguity_causes.push(
1053-
IntercrateAmbiguityCause::UpstreamCrateUpdate(did));
1070+
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
1071+
let self_ty = trait_ref.self_ty();
1072+
let cause = IntercrateAmbiguityCause::UpstreamCrateUpdate {
1073+
trait_desc: trait_ref.to_string(),
1074+
self_desc: if self_ty.has_concrete_skeleton() {
1075+
Some(self_ty.to_string())
1076+
} else {
1077+
None
1078+
},
1079+
};
1080+
self.intercrate_ambiguity_causes.push(cause);
10541081
}
10551082
return Ok(None);
10561083
}

src/librustc/traits/specialize/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
340340
}
341341

342342
for cause in &overlap.intercrate_ambiguity_causes {
343-
cause.add_intercrate_ambiguity_hint(tcx, &mut err);
343+
cause.add_intercrate_ambiguity_hint(&mut err);
344344
}
345345

346346
err.emit();

src/librustc_typeck/coherence/inherent_impls_overlap.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
6363
format!("other definition for `{}`", name));
6464

6565
for cause in &overlap.intercrate_ambiguity_causes {
66-
cause.add_intercrate_ambiguity_hint(self.tcx, &mut err);
66+
cause.add_intercrate_ambiguity_hint(&mut err);
6767
}
6868

6969
err.emit();

src/test/compile-fail/coherence-overlap-issue-23516-inherent.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct Cake<X>(X);
1919
impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
2020
//~^ ERROR E0592
2121
//~| NOTE duplicate definitions for `dummy`
22-
//~| NOTE upstream crates may add new impl for `Sugar` in future versions
22+
//~| NOTE upstream crates may add new impl of trait `Sugar` for type `std::boxed::Box<_>`
2323
impl<U:Sugar> Cake<Box<U>> { fn dummy(&self) { } }
2424
//~^ NOTE other definition for `dummy`
2525

src/test/compile-fail/coherence-overlap-issue-23516.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ impl<T:Sugar> Sweet for T { }
1919
impl<U:Sugar> Sweet for Box<U> { }
2020
//~^ ERROR E0119
2121
//~| NOTE conflicting implementation for `std::boxed::Box<_>`
22-
//~| NOTE upstream crates may add new impl for `Sugar` in future versions
22+
//~| NOTE upstream crates may add new impl of trait `Sugar` for type `std::boxed::Box<_>`
2323

2424
fn main() { }

src/test/compile-fail/coherence-overlap-upstream-inherent.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct A<X>(X);
2121
impl<T> A<T> where T: Remote { fn dummy(&self) { } }
2222
//~^ ERROR E0592
2323
//~| NOTE duplicate definitions for `dummy`
24-
//~| NOTE upstream crates may add new impl for `coherence_lib::Remote` in future versions
24+
//~| NOTE upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16`
2525
impl A<i16> { fn dummy(&self) { } }
2626
//~^ NOTE other definition for `dummy`
2727

src/test/compile-fail/coherence-overlap-upstream.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ impl<T> Foo for T where T: Remote {}
2323
impl Foo for i16 {}
2424
//~^ ERROR E0119
2525
//~| NOTE conflicting implementation for `i16`
26-
//~| NOTE upstream crates may add new impl for `coherence_lib::Remote` in future versions
26+
//~| NOTE upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16`
2727

2828
fn main() {}

src/test/ui/codemap_tests/overlapping_inherent_impls.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ error[E0592]: duplicate definitions with name `baz`
2525
43 | fn baz(&self) {}
2626
| ---------------- other definition for `baz`
2727
|
28-
= note: upstream crates may add new impl for `std::marker::Copy` in future versions
28+
= note: upstream crates may add new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions
2929

3030
error: aborting due to 3 previous errors
3131

0 commit comments

Comments
 (0)