1
Fork 0

Rollup merge of #100367 - fmease:fix-100365, r=compiler-errors

Suggest the path separator when a dot is used on a trait

Fixes #100365.

`@rustbot` label A-diagnostics
r? diagnostics
This commit is contained in:
Michael Goulet 2022-08-13 21:06:49 -07:00 committed by GitHub
commit e248c7f9ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 394 additions and 53 deletions

View file

@ -985,27 +985,45 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let ns = source.namespace(); let ns = source.namespace();
let is_expected = &|res| source.is_expected(res); let is_expected = &|res| source.is_expected(res);
let path_sep = |err: &mut Diagnostic, expr: &Expr| match expr.kind { let path_sep = |err: &mut Diagnostic, expr: &Expr, kind: DefKind| {
ExprKind::Field(_, ident) => { const MESSAGE: &str = "use the path separator to refer to an item";
let (lhs_span, rhs_span) = match &expr.kind {
ExprKind::Field(base, ident) => (base.span, ident.span),
ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span),
_ => return false,
};
if lhs_span.eq_ctxt(rhs_span) {
err.span_suggestion( err.span_suggestion(
expr.span, lhs_span.between(rhs_span),
"use the path separator to refer to an item", MESSAGE,
format!("{}::{}", path_str, ident), "::",
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
true true
} } else if kind == DefKind::Struct
ExprKind::MethodCall(ref segment, ..) => { && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
let span = expr.span.with_hi(segment.ident.span.hi()); && let Ok(snippet) = self.r.session.source_map().span_to_snippet(lhs_source_span)
err.span_suggestion( {
span, // The LHS is a type that originates from a macro call.
"use the path separator to refer to an item", // We have to add angle brackets around it.
format!("{}::{}", path_str, segment.ident),
err.span_suggestion_verbose(
lhs_source_span.until(rhs_span),
MESSAGE,
format!("<{snippet}>::"),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
true true
} else {
// Either we were unable to obtain the source span / the snippet or
// the LHS originates from a macro call and it is not a type and thus
// there is no way to replace `.` with `::` and still somehow suggest
// valid Rust code.
false
} }
_ => false,
}; };
let find_span = |source: &PathSource<'_>, err: &mut Diagnostic| { let find_span = |source: &PathSource<'_>, err: &mut Diagnostic| {
@ -1027,7 +1045,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
match source { match source {
PathSource::Expr(Some( PathSource::Expr(Some(
parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. }, parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. },
)) if path_sep(err, &parent) => {} )) if path_sep(err, &parent, DefKind::Struct) => {}
PathSource::Expr( PathSource::Expr(
None None
| Some(Expr { | Some(Expr {
@ -1143,8 +1161,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
} }
} }
} }
(Res::Def(DefKind::Mod, _), PathSource::Expr(Some(parent))) => { (
if !path_sep(err, &parent) { Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
PathSource::Expr(Some(parent)),
) => {
if !path_sep(err, &parent, kind) {
return false; return false;
} }
} }

View file

@ -0,0 +1,50 @@
fn main() {
let addr = Into::<std::net::IpAddr>.into([127, 0, 0, 1]);
//~^ ERROR expected value, found trait `Into`
//~| HELP use the path separator
let _ = Into.into(());
//~^ ERROR expected value, found trait `Into`
//~| HELP use the path separator
let _ = Into::<()>.into;
//~^ ERROR expected value, found trait `Into`
//~| HELP use the path separator
}
macro_rules! Trait {
() => {
::std::iter::Iterator
//~^ ERROR expected value, found trait `std::iter::Iterator`
//~| ERROR expected value, found trait `std::iter::Iterator`
};
}
macro_rules! create {
() => {
Into::<String>.into("")
//~^ ERROR expected value, found trait `Into`
//~| HELP use the path separator
};
}
fn interaction_with_macros() {
//
// Note that if the receiver is a macro call, we do not want to suggest to replace
// `.` with `::` as that would be a syntax error.
// Since the receiver is a trait and not a type, we cannot suggest to surround
// it with angle brackets. It would be interpreted as a trait object type void of
// `dyn` which is most likely not what the user intended to write.
// `<_ as Trait!()>::` is also not an option as it's equally syntactically invalid.
//
Trait!().map(std::convert::identity); // no `help` here!
Trait!().map; // no `help` here!
//
// Ensure that the suggestion is shown for expressions inside of macro definitions.
//
let _ = create!();
}

View file

@ -0,0 +1,54 @@
error[E0423]: expected value, found trait `Into`
--> $DIR/issue-100365.rs:2:16
|
LL | let addr = Into::<std::net::IpAddr>.into([127, 0, 0, 1]);
| ^^^^^^^^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::`
error[E0423]: expected value, found trait `Into`
--> $DIR/issue-100365.rs:6:13
|
LL | let _ = Into.into(());
| ^^^^- help: use the path separator to refer to an item: `::`
error[E0423]: expected value, found trait `Into`
--> $DIR/issue-100365.rs:10:13
|
LL | let _ = Into::<()>.into;
| ^^^^^^^^^^- help: use the path separator to refer to an item: `::`
error[E0423]: expected value, found trait `std::iter::Iterator`
--> $DIR/issue-100365.rs:17:9
|
LL | ::std::iter::Iterator
| ^^^^^^^^^^^^^^^^^^^^^ not a value
...
LL | Trait!().map(std::convert::identity); // no `help` here!
| -------- in this macro invocation
|
= note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0423]: expected value, found trait `std::iter::Iterator`
--> $DIR/issue-100365.rs:17:9
|
LL | ::std::iter::Iterator
| ^^^^^^^^^^^^^^^^^^^^^ not a value
...
LL | Trait!().map; // no `help` here!
| -------- in this macro invocation
|
= note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0423]: expected value, found trait `Into`
--> $DIR/issue-100365.rs:25:9
|
LL | Into::<String>.into("")
| ^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::`
...
LL | let _ = create!();
| --------- in this macro invocation
|
= note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0423`.

View file

@ -1,3 +1,60 @@
fn main() { fn main() {
let _ = String.new(); //~ ERROR expected value, found struct `String` let _ = String.new();
//~^ ERROR expected value, found struct `String`
//~| HELP use the path separator
let _ = String.default;
//~^ ERROR expected value, found struct `String`
//~| HELP use the path separator
let _ = Vec::<()>.with_capacity(1);
//~^ ERROR expected value, found struct `Vec`
//~| HELP use the path separator
}
macro_rules! Type {
() => {
::std::cell::Cell
//~^ ERROR expected value, found struct `std::cell::Cell`
//~| ERROR expected value, found struct `std::cell::Cell`
//~| ERROR expected value, found struct `std::cell::Cell`
};
}
macro_rules! create {
(type method) => {
Vec.new()
//~^ ERROR expected value, found struct `Vec`
//~| HELP use the path separator
};
(type field) => {
Vec.new
//~^ ERROR expected value, found struct `Vec`
//~| HELP use the path separator
};
(macro method) => {
Type!().new(0)
//~^ HELP use the path separator
};
}
fn interaction_with_macros() {
//
// Verify that we do not only suggest to replace `.` with `::` if the receiver is a
// macro call but that we also correctly suggest to surround it with angle brackets.
//
Type!().get();
//~^ HELP use the path separator
Type! {}.get;
//~^ HELP use the path separator
//
// Ensure that the suggestion is shown for expressions inside of macro definitions.
//
let _ = create!(type method);
let _ = create!(type field);
let _ = create!(macro method);
} }

View file

@ -2,10 +2,87 @@ error[E0423]: expected value, found struct `String`
--> $DIR/issue-22692.rs:2:13 --> $DIR/issue-22692.rs:2:13
| |
LL | let _ = String.new(); LL | let _ = String.new();
| ^^^^^^---- | ^^^^^^- help: use the path separator to refer to an item: `::`
| |
| help: use the path separator to refer to an item: `String::new`
error: aborting due to previous error error[E0423]: expected value, found struct `String`
--> $DIR/issue-22692.rs:6:13
|
LL | let _ = String.default;
| ^^^^^^- help: use the path separator to refer to an item: `::`
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-22692.rs:10:13
|
LL | let _ = Vec::<()>.with_capacity(1);
| ^^^^^^^^^- help: use the path separator to refer to an item: `::`
error[E0423]: expected value, found struct `std::cell::Cell`
--> $DIR/issue-22692.rs:17:9
|
LL | ::std::cell::Cell
| ^^^^^^^^^^^^^^^^^
...
LL | Type!().get();
| ------- in this macro invocation
|
= note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use the path separator to refer to an item
|
LL | <Type!()>::get();
| ~~~~~~~~~~~
error[E0423]: expected value, found struct `std::cell::Cell`
--> $DIR/issue-22692.rs:17:9
|
LL | ::std::cell::Cell
| ^^^^^^^^^^^^^^^^^
...
LL | Type! {}.get;
| -------- in this macro invocation
|
= note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use the path separator to refer to an item
|
LL | <Type! {}>::get;
| ~~~~~~~~~~~~
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-22692.rs:26:9
|
LL | Vec.new()
| ^^^- help: use the path separator to refer to an item: `::`
...
LL | let _ = create!(type method);
| -------------------- in this macro invocation
|
= note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-22692.rs:31:9
|
LL | Vec.new
| ^^^- help: use the path separator to refer to an item: `::`
...
LL | let _ = create!(type field);
| ------------------- in this macro invocation
|
= note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0423]: expected value, found struct `std::cell::Cell`
--> $DIR/issue-22692.rs:17:9
|
LL | ::std::cell::Cell
| ^^^^^^^^^^^^^^^^^
...
LL | let _ = create!(macro method);
| --------------------- in this macro invocation
|
= note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use the path separator to refer to an item
|
LL | <Type!()>::new(0)
| ~~~~~~~~~~~
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0423`. For more information about this error, try `rustc --explain E0423`.

View file

@ -2,17 +2,13 @@ error[E0423]: expected value, found struct `SomeTupleStruct`
--> $DIR/suggest-path-for-tuple-struct.rs:22:13 --> $DIR/suggest-path-for-tuple-struct.rs:22:13
| |
LL | let _ = SomeTupleStruct.new(); LL | let _ = SomeTupleStruct.new();
| ^^^^^^^^^^^^^^^---- | ^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::`
| |
| help: use the path separator to refer to an item: `SomeTupleStruct::new`
error[E0423]: expected value, found struct `SomeRegularStruct` error[E0423]: expected value, found struct `SomeRegularStruct`
--> $DIR/suggest-path-for-tuple-struct.rs:24:13 --> $DIR/suggest-path-for-tuple-struct.rs:24:13
| |
LL | let _ = SomeRegularStruct.new(); LL | let _ = SomeRegularStruct.new();
| ^^^^^^^^^^^^^^^^^---- | ^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::`
| |
| help: use the path separator to refer to an item: `SomeRegularStruct::new`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -16,44 +16,96 @@ pub mod a {
fn h1() -> i32 { fn h1() -> i32 {
a.I a.I
//~^ ERROR expected value, found module `a` //~^ ERROR expected value, found module `a`
//~| HELP use the path separator
} }
fn h2() -> i32 { fn h2() -> i32 {
a.g() a.g()
//~^ ERROR expected value, found module `a` //~^ ERROR expected value, found module `a`
//~| HELP use the path separator
} }
fn h3() -> i32 { fn h3() -> i32 {
a.b.J a.b.J
//~^ ERROR expected value, found module `a` //~^ ERROR expected value, found module `a`
//~| HELP use the path separator
} }
fn h4() -> i32 { fn h4() -> i32 {
a::b.J a::b.J
//~^ ERROR expected value, found module `a::b` //~^ ERROR expected value, found module `a::b`
//~| HELP a constant with a similar name exists
//~| HELP use the path separator
} }
fn h5() { fn h5() {
a.b.f(); a.b.f();
//~^ ERROR expected value, found module `a` //~^ ERROR expected value, found module `a`
//~| HELP use the path separator
let v = Vec::new(); let v = Vec::new();
v.push(a::b); v.push(a::b);
//~^ ERROR expected value, found module `a::b` //~^ ERROR expected value, found module `a::b`
//~| HELP a constant with a similar name exists
} }
fn h6() -> i32 { fn h6() -> i32 {
a::b.f() a::b.f()
//~^ ERROR expected value, found module `a::b` //~^ ERROR expected value, found module `a::b`
//~| HELP a constant with a similar name exists
//~| HELP use the path separator
} }
fn h7() { fn h7() {
a::b a::b
//~^ ERROR expected value, found module `a::b` //~^ ERROR expected value, found module `a::b`
//~| HELP a constant with a similar name exists
} }
fn h8() -> i32 { fn h8() -> i32 {
a::b() a::b()
//~^ ERROR expected function, found module `a::b` //~^ ERROR expected function, found module `a::b`
//~| HELP a constant with a similar name exists
}
macro_rules! module {
() => {
a
//~^ ERROR expected value, found module `a`
//~| ERROR expected value, found module `a`
};
}
macro_rules! create {
(method) => {
a.f()
//~^ ERROR expected value, found module `a`
//~| HELP use the path separator
};
(field) => {
a.f
//~^ ERROR expected value, found module `a`
//~| HELP use the path separator
};
}
fn h9() {
//
// Note that if the receiver is a macro call, we do not want to suggest to replace
// `.` with `::` as that would be a syntax error.
// Since the receiver is a module and not a type, we cannot suggest to surround
// it with angle brackets.
//
module!().g::<()>(); // no `help` here!
module!().g; // no `help` here!
//
// Ensure that the suggestion is shown for expressions inside of macro definitions.
//
let _ = create!(method);
let _ = create!(field);
} }
fn main() {} fn main() {}

View file

@ -2,28 +2,22 @@ error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:17:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:17:5
| |
LL | a.I LL | a.I
| ^-- | ^- help: use the path separator to refer to an item: `::`
| |
| help: use the path separator to refer to an item: `a::I`
error[E0423]: expected value, found module `a` error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:23:5
| |
LL | a.g() LL | a.g()
| ^-- | ^- help: use the path separator to refer to an item: `::`
| |
| help: use the path separator to refer to an item: `a::g`
error[E0423]: expected value, found module `a` error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:29:5
| |
LL | a.b.J LL | a.b.J
| ^-- | ^- help: use the path separator to refer to an item: `::`
| |
| help: use the path separator to refer to an item: `a::b`
error[E0423]: expected value, found module `a::b` error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:35:5
| |
LL | pub const I: i32 = 1; LL | pub const I: i32 = 1;
| --------------------- similarly named constant `I` defined here | --------------------- similarly named constant `I` defined here
@ -34,22 +28,20 @@ LL | a::b.J
help: use the path separator to refer to an item help: use the path separator to refer to an item
| |
LL | a::b::J LL | a::b::J
| | ~~
help: a constant with a similar name exists help: a constant with a similar name exists
| |
LL | a::I.J LL | a::I.J
| ~ | ~
error[E0423]: expected value, found module `a` error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:42:5
| |
LL | a.b.f(); LL | a.b.f();
| ^-- | ^- help: use the path separator to refer to an item: `::`
| |
| help: use the path separator to refer to an item: `a::b`
error[E0423]: expected value, found module `a::b` error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:46:12
| |
LL | pub const I: i32 = 1; LL | pub const I: i32 = 1;
| --------------------- similarly named constant `I` defined here | --------------------- similarly named constant `I` defined here
@ -60,7 +52,7 @@ LL | v.push(a::b);
| help: a constant with a similar name exists: `I` | help: a constant with a similar name exists: `I`
error[E0423]: expected value, found module `a::b` error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:52:5
| |
LL | pub const I: i32 = 1; LL | pub const I: i32 = 1;
| --------------------- similarly named constant `I` defined here | --------------------- similarly named constant `I` defined here
@ -71,14 +63,14 @@ LL | a::b.f()
help: use the path separator to refer to an item help: use the path separator to refer to an item
| |
LL | a::b::f() LL | a::b::f()
| ~~~~~~~ | ~~
help: a constant with a similar name exists help: a constant with a similar name exists
| |
LL | a::I.f() LL | a::I.f()
| ~ | ~
error[E0423]: expected value, found module `a::b` error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:59:5
| |
LL | pub const I: i32 = 1; LL | pub const I: i32 = 1;
| --------------------- similarly named constant `I` defined here | --------------------- similarly named constant `I` defined here
@ -89,7 +81,7 @@ LL | a::b
| help: a constant with a similar name exists: `I` | help: a constant with a similar name exists: `I`
error[E0423]: expected function, found module `a::b` error[E0423]: expected function, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:5 --> $DIR/suggest-path-instead-of-mod-dot-item.rs:65:5
| |
LL | pub const I: i32 = 1; LL | pub const I: i32 = 1;
| --------------------- similarly named constant `I` defined here | --------------------- similarly named constant `I` defined here
@ -99,6 +91,50 @@ LL | a::b()
| | | |
| help: a constant with a similar name exists: `I` | help: a constant with a similar name exists: `I`
error: aborting due to 9 previous errors error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9
|
LL | a
| ^ not a value
...
LL | module!().g::<()>(); // no `help` here!
| --------- in this macro invocation
|
= note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9
|
LL | a
| ^ not a value
...
LL | module!().g; // no `help` here!
| --------- in this macro invocation
|
= note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:80:9
|
LL | a.f()
| ^- help: use the path separator to refer to an item: `::`
...
LL | let _ = create!(method);
| --------------- in this macro invocation
|
= note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:85:9
|
LL | a.f
| ^- help: use the path separator to refer to an item: `::`
...
LL | let _ = create!(field);
| -------------- in this macro invocation
|
= note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0423`. For more information about this error, try `rustc --explain E0423`.

View file

@ -2,9 +2,7 @@ error[E0423]: expected value, found struct `Mod::Foo`
--> $DIR/assoc-const-as-field.rs:11:9 --> $DIR/assoc-const-as-field.rs:11:9
| |
LL | foo(Mod::Foo.Bar); LL | foo(Mod::Foo.Bar);
| ^^^^^^^^---- | ^^^^^^^^- help: use the path separator to refer to an item: `::`
| |
| help: use the path separator to refer to an item: `Mod::Foo::Bar`
error: aborting due to previous error error: aborting due to previous error