-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Add a diagnostic for similarly named traits #144674
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add a diagnostic for similarly named traits #144674
Conversation
This comment has been minimized.
This comment has been minimized.
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
ff869dc
to
abdb087
Compare
This PR modifies cc @jieyouxu |
Fixed by using predicate_must_hold_modulo_regions |
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
The current version is the following. I no longer browse the impls, so it is no longer per impl. It's mostly working (other::Trait or other::Trait<T> are working), however I still get weird behaviours with super traits and the GenericArgs . That's why I did not push the commit yet, some tests are broken, I am investigating. UPDATE: switch to the last commit directly and see update below regarding generics and ICE pub(crate) fn suggest_impl_similarly_named_trait(
&self,
err: &mut Diag<'_>,
obligation: &PredicateObligation<'tcx>,
trait_predicate: ty::PolyTraitPredicate<'tcx>,
) {
let trait_def_id = trait_predicate.def_id();
let trait_name = self.tcx.item_name(trait_def_id);
if let Some(other_trait_def_id) = self.tcx.all_traits_including_private().find(|def_id| {
if trait_def_id != *def_id && trait_name == self.tcx.item_name(def_id) {
if let Some(pred) = self.tcx.predicates_of(*def_id).instantiate(self.tcx, trait_predicate.skip_binder().trait_ref.args).predicates.iter().find(|clause| {
clause.as_trait_clause().map_or(false, |trait_clause| trait_clause.def_id() == *def_id)
})
{
let pred = pred.as_trait_clause().unwrap();
self.predicate_must_hold_modulo_regions(&Obligation::new(
self.tcx,
obligation.cause.clone(),
obligation.param_env,
pred,
))
} else {
false
}
} else {
false
}
}) {
err.note(format!(
"`{}` implements similarly named `{}`, but not `{}`",
trait_predicate.self_ty(),
self.tcx.def_path_str(other_trait_def_id),
trait_predicate.print_modifiers_and_trait_path()
));
}
()
} |
abdb087
to
532c561
Compare
This is another proposal, feedbacks are welcomed. I am not convinced about the part regarding the generic args. The idea being that you cannot select a similarly named trait with different generics (or different constraints), it does not makes sense and might cause ICE. |
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
532c561
to
3fcbf63
Compare
This is another proposal, I have simplified the code. This is to show you the code before I merge it with the other suggestion. I have to analyze the other suggestion you were talking about and try to merge my code with it now. |
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the impl lgtm now, I don't think we should have these two similar suggestions however (similarly named trait vs similarly named trait from different crate version), and believe they should be merged into 1
OK, thanks for your feedbacks. I will merge with the other suggestion and fix param.kind during the weekend |
3fcbf63
to
a6853be
Compare
Merged into the suggestion we have discussed above. I have kept each note/notice independent, because I have the feeling that the three notes/notices might still be emitted independently when you think about it. You might have similarly named traits within the same crate but also in different crates. You might have cases when similarly named traits are found but not traits with the same path (this is typically the case in some ui tests) |
@rustbot author |
Reminder, once the PR becomes ready for a review, use |
@lcnr I am a bit confused because we have:
and
which one are we talking about ? both ? Because currently my suggestion in the note_version_mismatch() function (into rustc_trait_selection). I can easily be exclusive with the second one (as I am in the same function), the first suggestion being inside another compiler crate. There is way to know that a suggestion was already emitted from another compiler crate ? (rustc_hir_typeck in our case) |
a6853be
to
d513dc2
Compare
This comment has been minimized.
This comment has been minimized.
@rustbot ready |
This comment has been minimized.
This comment has been minimized.
d513dc2
to
66cc4f4
Compare
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
This comment was marked as outdated.
This comment was marked as outdated.
compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
Show resolved
Hide resolved
.is_some() | ||
{ | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this prevent duplicate diagnostics? and if so, in which test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it does, It is convered by :
tests/ui/traits/bound/same-crate-name.stderr
for "perhaps two different versions of crate {trait_crate} are being used?"
andtests/run-make/crate-loading/multiple-dep-versions.stderr
for "there are multiple different versions of crate {krate} in the dependency graph".
Originally these tests were updated, but it is no longer the case, which means that there are no longer duplicate diagnostics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don#t get what you mean? 🤔
Originally these tests were updated, but it is no longer the case,
you mean that even if you remove this early return, the tests still don't have redundant diagnostics?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant, initially both diagnostics were emitted ("multiple different crates versions" and "similarly named trait") , this if
prevents this. Removing this if
will break tests/run-make .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the if suggested
prevents "perhaps two different versions of crate {trait_crate} are being used?" from being emitted , the ìf
that checks for differents crates prevents "there are multiple different versions of crate {krate} in the dependency graph" from being emitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if we understood each other, does it reply to your question ?
…equired one This is useful when you have two dependencies that use different trait for the same thing and with the same name. The user can accidentally implement the bad one which might be confusing.
66cc4f4
to
35d44c6
Compare
Renaming the fonction to note_impl_ambiguous_trait() . What about the rest ? Do you want that I investigate something ? |
cc #133123
This is a first proposal, suggestions are welcome