Print more detailed trait-ref for intercrate ambiguity.
This commit is contained in:
parent
84bfc33fac
commit
d153ff3f79
@ -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<String>,
|
||||
},
|
||||
UpstreamCrateUpdate {
|
||||
trait_desc: String,
|
||||
self_desc: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -19,7 +19,7 @@ struct Cake<X>(X);
|
||||
impl<T:Sugar> Cake<T> { 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<U:Sugar> Cake<Box<U>> { fn dummy(&self) { } }
|
||||
//~^ NOTE other definition for `dummy`
|
||||
|
||||
|
@ -19,6 +19,6 @@ impl<T:Sugar> Sweet for T { }
|
||||
impl<U:Sugar> Sweet for Box<U> { }
|
||||
//~^ 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() { }
|
||||
|
@ -21,7 +21,7 @@ struct A<X>(X);
|
||||
impl<T> A<T> 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<i16> { fn dummy(&self) { } }
|
||||
//~^ NOTE other definition for `dummy`
|
||||
|
||||
|
@ -23,6 +23,6 @@ impl<T> 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() {}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user