Skip to content
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

remove the unused :: between trait and type to give user correct diag… #102421

Merged
merged 1 commit into from
Sep 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2263,13 +2263,22 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
trait_impls.non_blanket_impls().len()
)
};

let mut suggestions = vec![(
trait_path_segment.ident.span.shrink_to_lo(),
format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sidenote, using self.tcx.def_path(impl_def_id).to_string_no_crate_verbose() here feels wrong, I would expect us to use self.tcx.type_of(impl_def_id) here to print the self type. rn this is causing us to print ::StructA instead of StructA.

@lyming2007 would you be interested in changing this in a followup pr?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both <::StructA as TraitA<i32>>::func() and <StructA as TraitA<i32>>::func() will work for the compiler.
Do we really need to change it from ::StructA to StructA?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need to do it, but it's a lot more idiomatic to use StructA instead of ::StructA. Using ::StructA is pretty confusing to most people, so it's better to avoid imo

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see this PR #102670 @lcnr

)];
if let Some(generic_arg) = trait_path_segment.args {
let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
// get rid of :: between Trait and <type>
// must be '::' between them, otherwise the parser won't accept the code
suggestions.push((between_span, "".to_string(),));
suggestions.push((generic_arg.span_ext.shrink_to_hi(), format!(">")));
} else {
suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), format!(">")));
}
err.multipart_suggestion(
message,
vec![
(trait_path_segment.ident.span.shrink_to_lo(), format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())),
(trait_path_segment.ident.span.shrink_to_hi(), format!(">"))
],
suggestions,
Applicability::MaybeIncorrect
);
}
Expand Down
15 changes: 15 additions & 0 deletions src/test/ui/type/issue-101866.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
trait TraitA<T> {
fn func();
}

struct StructA {}

impl TraitA<i32> for StructA {
fn func() {}
}

fn main() {
TraitA::<i32>::func();
//~^ ERROR: cannot call associated function on trait without specifying the corresponding `impl` type [E0790]
//~| help: use the fully-qualified path to the only available implementation
}
18 changes: 18 additions & 0 deletions src/test/ui/type/issue-101866.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
--> $DIR/issue-101866.rs:12:5
|
LL | fn func();
| ---------- `TraitA::func` defined here
...
LL | TraitA::<i32>::func();
| ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
help: use the fully-qualified path to the only available implementation
|
LL - TraitA::<i32>::func();
LL + <::StructA as TraitA<i32>>::func();
|

error: aborting due to previous error

For more information about this error, try `rustc --explain E0790`.