-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add version mismatch help message for unimplemented trait
Issue #22750 The error reporting for E0277 (the trait `X` is not implemented for `Foo`) now checks whether `Foo` implements a trait with the same path as `X`, which probably means that the programmer wanted to actually use only one version of the trait `X` instead of the two.
- Loading branch information
1 parent
b56b239
commit dffdf37
Showing
5 changed files
with
87 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ use std::fmt; | |
use syntax::ast; | ||
use syntax::symbol::{sym, kw}; | ||
use syntax_pos::{DUMMY_SP, Span, ExpnKind, MultiSpan}; | ||
use rustc::hir::def_id::LOCAL_CRATE; | ||
|
||
use rustc_error_codes::*; | ||
|
||
|
@@ -799,6 +800,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg); | ||
self.suggest_remove_reference(&obligation, &mut err, &trait_ref); | ||
self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); | ||
self.note_version_mismatch(&mut err, &trait_ref); | ||
|
||
// Try to report a help message | ||
if !trait_ref.has_infer_types() && | ||
|
@@ -1050,6 +1052,43 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
err.emit(); | ||
} | ||
|
||
/// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait | ||
/// with the same path as `trait_ref`, a help message about | ||
/// a probable version mismatch is added to `err` | ||
fn note_version_mismatch( | ||
&self, | ||
err: &mut DiagnosticBuilder<'_>, | ||
trait_ref: &ty::PolyTraitRef<'tcx>, | ||
) { | ||
let get_trait_impl = |trait_def_id| { | ||
let mut trait_impl = None; | ||
self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| { | ||
if trait_impl.is_none() { | ||
trait_impl = Some(impl_def_id); | ||
} | ||
}); | ||
trait_impl | ||
}; | ||
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); | ||
let all_traits = self.tcx.all_traits(LOCAL_CRATE); | ||
let traits_with_same_path: std::collections::BTreeSet<_> = all_traits | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
TimoFreiberg
Author
Contributor
|
||
.iter() | ||
.filter(|trait_def_id| **trait_def_id != trait_ref.def_id()) | ||
.filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path) | ||
.collect(); | ||
for trait_with_same_path in traits_with_same_path { | ||
if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) { | ||
let impl_span = self.tcx.def_span(impl_def_id); | ||
err.span_help(impl_span, "Trait impl with same name found"); | ||
let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); | ||
let crate_msg = format!( | ||
"Perhaps two different versions of crate `{}` are being used?", | ||
trait_crate | ||
); | ||
err.note(&crate_msg); | ||
} | ||
} | ||
} | ||
fn suggest_restricting_param_bound( | ||
&self, | ||
err: &mut DiagnosticBuilder<'_>, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pub struct Foo; | ||
|
||
pub trait Bar{} | ||
|
||
impl Bar for Foo {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// aux-build:crate_a1.rs | ||
// aux-build:crate_a2.rs | ||
|
||
// Issue 22750 | ||
// This tests the extra help message reported when a trait bound | ||
// is not met but the struct implements a trait with the same path. | ||
|
||
fn main() { | ||
let foo2 = { | ||
extern crate crate_a2 as a; | ||
a::Foo | ||
}; | ||
|
||
{ | ||
extern crate crate_a1 as a; | ||
a::try_foo(foo2); | ||
//~^ ERROR E0277 | ||
//~| Trait impl with same name found | ||
//~| Perhaps two different versions of crate `crate_a2` | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
error[E0277]: the trait bound `main::a::Foo: main::a::Bar` is not satisfied | ||
--> $DIR/trait-bounds-same-crate-name.rs:16:20 | ||
| | ||
LL | a::try_foo(foo2); | ||
| ^^^^ the trait `main::a::Bar` is not implemented for `main::a::Foo` | ||
| | ||
::: $DIR/auxiliary/crate_a1.rs:5:24 | ||
| | ||
LL | pub fn try_foo(x: impl Bar){} | ||
| --- required by this bound in `main::a::try_foo` | ||
| | ||
help: Trait impl with same name found | ||
--> $DIR/auxiliary/crate_a2.rs:5:1 | ||
| | ||
LL | impl Bar for Foo {} | ||
| ^^^^^^^^^^^^^^^^^^^ | ||
= note: Perhaps two different versions of crate `crate_a2` are being used? | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0277`. |
What's the reason to collecting in BTreeSet here? I can't see where it is used later, having just iterator seems to be enough.