Rollup merge of #136344 - zachs18:dot_notation_more_defkinds_3, r=davidtwco

Suggest replacing `.` with `::` in more error diagnostics.

First commit makes the existing "help: use the path separator to refer to an item" also work when the base is a type alias, not just a trait/module/struct.

The existing unconditional `DefKind::Mod | DefKind::Trait` match arm is changed to a conditional `DefKind::Mod | DefKind::Trait | DefKind::TyAlias` arm that only matches if the `path_sep` suggestion-adding closure succeeds, so as not to stop the later `DefKind::TyAlias`-specific suggestions if the path-sep suggestion does not apply. This shouldn't change behavior for `Mod` or `Trait` (due to the default arm's `return false` etc).

This commit also updates `tests/ui/resolve/issue-22692.rs` to reflect this, and also renames it to something more meaningful.

This commit also makes the `bad_struct_syntax_suggestion` closure take `err` as a parameter instead of capturing it, since otherwise caused borrowing errors due to the change to using `path_sep` in a pattern guard.

<details> <summary> Type alias diagnostic example </summary>

```rust
type S = String;

fn main() {
    let _ = S.new;
}
```

```diff
 error[E0423]: expected value, found type alias `S`
  --> diag7.rs:4:13
   |
 4 |     let _ = S.new;
   |             ^
   |
-  = note: can't use a type alias as a constructor
+  help: use the path separator to refer to an item
+  |
+4 |     let _ = S::new;
+  |              ~~
```

</details>

Second commit adds some cases for `enum`s, where if there is a field/method expression where the field/method has the name of a unit/tuple variant, we assume the user intended to create that variant[^1] and suggest replacing the `.` from the field/method suggestion with a `::` path separator. If no such variant is found (or if the error is not a field/method expression), we give the existing suggestion that suggests adding `::TupleVariant(/* fields */)` after the enum.

<details> <summary> Enum diagnostic example </summary>

```rust
enum Foo {
    A(u32),
    B,
    C { x: u32 },
}

fn main() {
    let _ = Foo.A(42); // changed
    let _ = Foo.B;     // changed
    let _ = Foo.D(42); // no change
    let _ = Foo.D;     // no change
    let _ = Foo(42);   // no change
}
```

```diff
 error[E0423]: expected value, found enum `Foo`
  --> diag8.rs:8:13
   |
 8 |     let _ = Foo.A(42); // changed
   |             ^^^
   |
 note: the enum is defined here
  --> diag8.rs:1:1
   |
 1 | / enum Foo {
 2 | |     A(u32),
 3 | |     B,
 4 | |     C { x: u32 },
 5 | | }
   | |_^
-help: you might have meant to use the following enum variant
-  |
-8 |     let _ = Foo::B.A(42); // changed
-  |             ~~~~~~
-help: alternatively, the following enum variant is available
+help: use the path separator to refer to a variant
   |
-8 |     let _ = (Foo::A(/* fields */)).A(42); // changed
-  |             ~~~~~~~~~~~~~~~~~~~~~~
+8 |     let _ = Foo::A(42); // changed
+  |                ~~

 error[E0423]: expected value, found enum `Foo`
  --> diag8.rs:9:13
   |
 9 |     let _ = Foo.B;     // changed
   |             ^^^
   |
 note: the enum is defined here
  --> diag8.rs:1:1
   |
 1 | / enum Foo {
 2 | |     A(u32),
 3 | |     B,
 4 | |     C { x: u32 },
 5 | | }
   | |_^
-help: you might have meant to use the following enum variant
-  |
-9 |     let _ = Foo::B.B;     // changed
-  |             ~~~~~~
-help: alternatively, the following enum variant is available
+help: use the path separator to refer to a variant
   |
-9 |     let _ = (Foo::A(/* fields */)).B;     // changed
-  |             ~~~~~~~~~~~~~~~~~~~~~~
+9 |     let _ = Foo::B;     // changed
+  |                ~~

 error[E0423]: expected value, found enum `Foo`
   --> diag8.rs:10:13
    |
 10 |     let _ = Foo.D(42); // no change
    |             ^^^
    |
 note: the enum is defined here
   --> diag8.rs:1:1
    |
 1  | / enum Foo {
 2  | |     A(u32),
 3  | |     B,
 4  | |     C { x: u32 },
 5  | | }
    | |_^
 help: you might have meant to use the following enum variant
    |
 10 |     let _ = Foo::B.D(42); // no change
    |             ~~~~~~
 help: alternatively, the following enum variant is available
    |
 10 |     let _ = (Foo::A(/* fields */)).D(42); // no change
    |             ~~~~~~~~~~~~~~~~~~~~~~

 error[E0423]: expected value, found enum `Foo`
   --> diag8.rs:11:13
    |
 11 |     let _ = Foo.D;     // no change
    |             ^^^
    |
 note: the enum is defined here
   --> diag8.rs:1:1
    |
 1  | / enum Foo {
 2  | |     A(u32),
 3  | |     B,
 4  | |     C { x: u32 },
 5  | | }
    | |_^
 help: you might have meant to use the following enum variant
    |
 11 |     let _ = Foo::B.D;     // no change
    |             ~~~~~~
 help: alternatively, the following enum variant is available
    |
 11 |     let _ = (Foo::A(/* fields */)).D;     // no change
    |             ~~~~~~~~~~~~~~~~~~~~~~

 error[E0423]: expected function, tuple struct or tuple variant, found enum `Foo`
   --> diag8.rs:12:13
    |
 12 |     let _ = Foo(42);   // no change
    |             ^^^ help: try to construct one of the enum's variants: `Foo::A`
    |
    = help: you might have meant to construct the enum's non-tuple variant
 note: the enum is defined here
   --> diag8.rs:1:1
    |
 1  | / enum Foo {
 2  | |     A(u32),
 3  | |     B,
 4  | |     C { x: u32 },
 5  | | }
    | |_^

 error: aborting due to 5 previous errors
```

</details>

[^1]: or if it's a field expression and a tuple variant, that they meant to refer the variant constructor.
This commit is contained in:
Matthias Krüger 2025-02-19 21:16:07 +01:00 committed by GitHub
commit 82279108e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 730 additions and 204 deletions

View File

@ -8,7 +8,7 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty};
use rustc_ast::{
self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind,
Item, ItemKind, MethodCall, NodeId, Path, Ty, TyKind,
Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind,
};
use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
@ -1529,7 +1529,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
Applicability::MaybeIncorrect,
);
true
} else if kind == DefKind::Struct
} else if matches!(kind, DefKind::Struct | DefKind::TyAlias)
&& let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
&& let Ok(snippet) = this.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
{
@ -1566,7 +1566,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
};
let mut bad_struct_syntax_suggestion = |this: &mut Self, def_id: DefId| {
let bad_struct_syntax_suggestion = |this: &mut Self, err: &mut Diag<'_>, def_id: DefId| {
let (followed_by_brace, closing_brace) = this.followed_by_brace(span);
match source {
@ -1740,12 +1740,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
}
(
Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
Res::Def(kind @ (DefKind::Mod | DefKind::Trait | DefKind::TyAlias), _),
PathSource::Expr(Some(parent)),
) => {
if !path_sep(self, err, parent, kind) {
return false;
}
) if path_sep(self, err, parent, kind) => {
return true;
}
(
Res::Def(DefKind::Enum, def_id),
@ -1777,13 +1775,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor {
if let PathSource::Expr(Some(parent)) = source {
if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind {
bad_struct_syntax_suggestion(self, def_id);
bad_struct_syntax_suggestion(self, err, def_id);
return true;
}
}
struct_ctor
} else {
bad_struct_syntax_suggestion(self, def_id);
bad_struct_syntax_suggestion(self, err, def_id);
return true;
};
@ -1861,7 +1859,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
err.span_label(span, "constructor is not visible here due to private fields");
}
(Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => {
bad_struct_syntax_suggestion(self, def_id);
bad_struct_syntax_suggestion(self, err, def_id);
}
(Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
match source {
@ -2471,31 +2469,73 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
def_id: DefId,
span: Span,
) {
let Some(variants) = self.collect_enum_ctors(def_id) else {
let Some(variant_ctors) = self.collect_enum_ctors(def_id) else {
err.note("you might have meant to use one of the enum's variants");
return;
};
let suggest_only_tuple_variants =
matches!(source, PathSource::TupleStruct(..)) || source.is_call();
if suggest_only_tuple_variants {
// If the expression is a field-access or method-call, try to find a variant with the field/method name
// that could have been intended, and suggest replacing the `.` with `::`.
// Otherwise, suggest adding `::VariantName` after the enum;
// and if the expression is call-like, only suggest tuple variants.
let (suggest_path_sep_dot_span, suggest_only_tuple_variants) = match source {
// `Type(a, b)` in a pattern, only suggest adding a tuple variant after `Type`.
PathSource::TupleStruct(..) => (None, true),
PathSource::Expr(Some(expr)) => match &expr.kind {
// `Type(a, b)`, only suggest adding a tuple variant after `Type`.
ExprKind::Call(..) => (None, true),
// `Type.Foo(a, b)`, suggest replacing `.` -> `::` if variant `Foo` exists and is a tuple variant,
// otherwise suggest adding a variant after `Type`.
ExprKind::MethodCall(box MethodCall {
receiver,
span,
seg: PathSegment { ident, .. },
..
}) => {
let dot_span = receiver.span.between(*span);
let found_tuple_variant = variant_ctors.iter().any(|(path, _, ctor_kind)| {
*ctor_kind == CtorKind::Fn
&& path.segments.last().is_some_and(|seg| seg.ident == *ident)
});
(found_tuple_variant.then_some(dot_span), false)
}
// `Type.Foo`, suggest replacing `.` -> `::` if variant `Foo` exists and is a unit or tuple variant,
// otherwise suggest adding a variant after `Type`.
ExprKind::Field(base, ident) => {
let dot_span = base.span.between(ident.span);
let found_tuple_or_unit_variant = variant_ctors.iter().any(|(path, ..)| {
path.segments.last().is_some_and(|seg| seg.ident == *ident)
});
(found_tuple_or_unit_variant.then_some(dot_span), false)
}
_ => (None, false),
},
_ => (None, false),
};
if let Some(dot_span) = suggest_path_sep_dot_span {
err.span_suggestion_verbose(
dot_span,
"use the path separator to refer to a variant",
"::",
Applicability::MaybeIncorrect,
);
} else if suggest_only_tuple_variants {
// Suggest only tuple variants regardless of whether they have fields and do not
// suggest path with added parentheses.
let mut suggestable_variants = variants
let mut suggestable_variants = variant_ctors
.iter()
.filter(|(.., kind)| *kind == CtorKind::Fn)
.map(|(variant, ..)| path_names_to_string(variant))
.collect::<Vec<_>>();
suggestable_variants.sort();
let non_suggestable_variant_count = variants.len() - suggestable_variants.len();
let non_suggestable_variant_count = variant_ctors.len() - suggestable_variants.len();
let source_msg = if source.is_call() {
"to construct"
} else if matches!(source, PathSource::TupleStruct(..)) {
let source_msg = if matches!(source, PathSource::TupleStruct(..)) {
"to match against"
} else {
unreachable!()
"to construct"
};
if !suggestable_variants.is_empty() {
@ -2514,7 +2554,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
// If the enum has no tuple variants..
if non_suggestable_variant_count == variants.len() {
if non_suggestable_variant_count == variant_ctors.len() {
err.help(format!("the enum has no tuple variants {source_msg}"));
}
@ -2537,7 +2577,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
};
let mut suggestable_variants = variants
let mut suggestable_variants = variant_ctors
.iter()
.filter(|(_, def_id, kind)| !needs_placeholder(*def_id, *kind))
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))
@ -2564,7 +2604,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
);
}
let mut suggestable_variants_with_placeholders = variants
let mut suggestable_variants_with_placeholders = variant_ctors
.iter()
.filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))

View File

@ -3619,7 +3619,6 @@ ui/resolve/issue-21221-1.rs
ui/resolve/issue-21221-2.rs
ui/resolve/issue-21221-3.rs
ui/resolve/issue-21221-4.rs
ui/resolve/issue-22692.rs
ui/resolve/issue-2330.rs
ui/resolve/issue-23305.rs
ui/resolve/issue-2356.rs

View File

@ -0,0 +1,123 @@
// see also https://github.com/rust-lang/rust/issues/22692
type Alias = Vec<u32>;
mod foo {
fn bar() {}
}
fn main() {
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
let _ = Alias.new();
//~^ ERROR expected value, found type alias `Alias`
//~| HELP use the path separator
let _ = Alias.default;
//~^ ERROR expected value, found type alias `Alias`
//~| HELP use the path separator
let _ = foo.bar;
//~^ ERROR expected value, found module `foo`
//~| 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`
};
(alias) => {
Alias
//~^ ERROR expected value, found type alias `Alias`
//~| ERROR expected value, found type alias `Alias`
//~| ERROR expected value, found type alias `Alias`
};
}
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
};
(macro method alias) => {
Type!(alias).new(0)
//~^ HELP use the path separator
};
}
macro_rules! check_ty {
($Ty:ident) => {
$Ty.foo
//~^ ERROR expected value, found type alias `Alias`
//~| HELP use the path separator
};
}
macro_rules! check_ident {
($Ident:ident) => {
Alias.$Ident
//~^ ERROR expected value, found type alias `Alias`
//~| HELP use the path separator
};
}
macro_rules! check_ty_ident {
($Ty:ident, $Ident:ident) => {
$Ty.$Ident
//~^ ERROR expected value, found type alias `Alias`
//~| 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
Type!(alias).get();
//~^ HELP use the path separator
Type! {alias}.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);
let _ = create!(macro method alias);
let _ = check_ty!(Alias);
let _ = check_ident!(foo);
let _ = check_ty_ident!(Alias, foo);
}

View File

@ -0,0 +1,251 @@
error[E0423]: expected value, found struct `String`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:10:13
|
LL | let _ = String.new();
| ^^^^^^
|
help: use the path separator to refer to an item
|
LL - let _ = String.new();
LL + let _ = String::new();
|
error[E0423]: expected value, found struct `String`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:14:13
|
LL | let _ = String.default;
| ^^^^^^
|
help: use the path separator to refer to an item
|
LL - let _ = String.default;
LL + let _ = String::default;
|
error[E0423]: expected value, found struct `Vec`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:18:13
|
LL | let _ = Vec::<()>.with_capacity(1);
| ^^^^^^^^^
|
help: use the path separator to refer to an item
|
LL - let _ = Vec::<()>.with_capacity(1);
LL + let _ = Vec::<()>::with_capacity(1);
|
error[E0423]: expected value, found type alias `Alias`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:22:13
|
LL | let _ = Alias.new();
| ^^^^^
|
help: use the path separator to refer to an item
|
LL - let _ = Alias.new();
LL + let _ = Alias::new();
|
error[E0423]: expected value, found type alias `Alias`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:26:13
|
LL | let _ = Alias.default;
| ^^^^^
|
help: use the path separator to refer to an item
|
LL - let _ = Alias.default;
LL + let _ = Alias::default;
|
error[E0423]: expected value, found module `foo`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:30:13
|
LL | let _ = foo.bar;
| ^^^
|
help: use the path separator to refer to an item
|
LL - let _ = foo.bar;
LL + let _ = foo::bar;
|
error[E0423]: expected value, found struct `std::cell::Cell`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37: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();
LL + <Type!()>::get();
|
error[E0423]: expected value, found struct `std::cell::Cell`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37: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;
LL + <Type! {}>::get;
|
error[E0423]: expected value, found type alias `Alias`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
|
LL | Alias
| ^^^^^
...
LL | Type!(alias).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!(alias).get();
LL + <Type!(alias)>::get();
|
error[E0423]: expected value, found type alias `Alias`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
|
LL | Alias
| ^^^^^
...
LL | Type! {alias}.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! {alias}.get;
LL + <Type! {alias}>::get;
|
error[E0423]: expected value, found struct `Vec`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:52:9
|
LL | Vec.new()
| ^^^
...
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)
help: use the path separator to refer to an item
|
LL - Vec.new()
LL + Vec::new()
|
error[E0423]: expected value, found struct `Vec`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:57:9
|
LL | Vec.new
| ^^^
...
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)
help: use the path separator to refer to an item
|
LL - Vec.new
LL + Vec::new
|
error[E0423]: expected value, found struct `std::cell::Cell`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37: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)
LL + <Type!()>::new(0)
|
error[E0423]: expected value, found type alias `Alias`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
|
LL | Alias
| ^^^^^
...
LL | let _ = create!(macro method alias);
| --------------------------- 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!(alias).new(0)
LL + <Type!(alias)>::new(0)
|
error[E0423]: expected value, found type alias `Alias`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:73:9
|
LL | $Ty.foo
| ^^^
...
LL | let _ = check_ty!(Alias);
| ---------------- in this macro invocation
|
= note: this error originates in the macro `check_ty` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use the path separator to refer to an item
|
LL - $Ty.foo
LL + $Ty::foo
|
error[E0423]: expected value, found type alias `Alias`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:80:9
|
LL | Alias.$Ident
| ^^^^^
...
LL | let _ = check_ident!(foo);
| ----------------- in this macro invocation
|
= note: this error originates in the macro `check_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use the path separator to refer to an item
|
LL - Alias.$Ident
LL + <Alias>::$Ident
|
error[E0423]: expected value, found type alias `Alias`
--> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:87:9
|
LL | $Ty.$Ident
| ^^^
...
LL | let _ = check_ty_ident!(Alias, foo);
| --------------------------- in this macro invocation
|
= note: this error originates in the macro `check_ty_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use the path separator to refer to an item
|
LL - $Ty.$Ident
LL + <$Ty>::$Ident
|
error: aborting due to 17 previous errors
For more information about this error, try `rustc --explain E0423`.

View File

@ -0,0 +1,58 @@
enum Foo {
//~^ HELP consider importing this tuple variant
A(u32),
B(u32),
}
enum Bar {
C(u32),
D(u32),
E,
F,
}
fn main() {
let _: Foo = Foo(0);
//~^ ERROR expected function
//~| HELP try to construct one of the enum's variants
let _: Foo = Foo.A(0);
//~^ ERROR expected value, found enum `Foo`
//~| HELP use the path separator to refer to a variant
let _: Foo = Foo.Bad(0);
//~^ ERROR expected value, found enum `Foo`
//~| HELP the following enum variants are available
let _: Bar = Bar(0);
//~^ ERROR expected function
//~| HELP try to construct one of the enum's variants
//~| HELP you might have meant to construct one of the enum's non-tuple variants
let _: Bar = Bar.C(0);
//~^ ERROR expected value, found enum `Bar`
//~| HELP use the path separator to refer to a variant
let _: Bar = Bar.E;
//~^ ERROR expected value, found enum `Bar`
//~| HELP use the path separator to refer to a variant
let _: Bar = Bar.Bad(0);
//~^ ERROR expected value, found enum `Bar`
//~| HELP you might have meant to use one of the following enum variants
//~| HELP alternatively, the following enum variants are also available
let _: Bar = Bar.Bad;
//~^ ERROR expected value, found enum `Bar`
//~| HELP you might have meant to use one of the following enum variants
//~| HELP alternatively, the following enum variants are also available
match Foo::A(42) {
A(..) => {}
//~^ ERROR cannot find tuple struct or tuple variant `A` in this scope
Foo(..) => {}
//~^ ERROR expected tuple struct or tuple variant
//~| HELP try to match against one of the enum's variants
_ => {}
}
}

View File

@ -0,0 +1,234 @@
error[E0423]: expected value, found enum `Foo`
--> $DIR/enum-expected-value-suggest-variants.rs:19:18
|
LL | let _: Foo = Foo.A(0);
| ^^^
|
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:1:1
|
LL | / enum Foo {
LL | |
LL | | A(u32),
LL | | B(u32),
LL | | }
| |_^
help: use the path separator to refer to a variant
|
LL - let _: Foo = Foo.A(0);
LL + let _: Foo = Foo::A(0);
|
error[E0423]: expected value, found enum `Foo`
--> $DIR/enum-expected-value-suggest-variants.rs:23:18
|
LL | let _: Foo = Foo.Bad(0);
| ^^^
|
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:1:1
|
LL | / enum Foo {
LL | |
LL | | A(u32),
LL | | B(u32),
LL | | }
| |_^
help: the following enum variants are available
|
LL - let _: Foo = Foo.Bad(0);
LL + let _: Foo = (Foo::A(/* fields */)).Bad(0);
|
LL - let _: Foo = Foo.Bad(0);
LL + let _: Foo = (Foo::B(/* fields */)).Bad(0);
|
error[E0423]: expected value, found enum `Bar`
--> $DIR/enum-expected-value-suggest-variants.rs:32:18
|
LL | let _: Bar = Bar.C(0);
| ^^^
|
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:7:1
|
LL | / enum Bar {
LL | | C(u32),
LL | | D(u32),
LL | | E,
LL | | F,
LL | | }
| |_^
help: use the path separator to refer to a variant
|
LL - let _: Bar = Bar.C(0);
LL + let _: Bar = Bar::C(0);
|
error[E0423]: expected value, found enum `Bar`
--> $DIR/enum-expected-value-suggest-variants.rs:36:18
|
LL | let _: Bar = Bar.E;
| ^^^
|
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:7:1
|
LL | / enum Bar {
LL | | C(u32),
LL | | D(u32),
LL | | E,
LL | | F,
LL | | }
| |_^
help: use the path separator to refer to a variant
|
LL - let _: Bar = Bar.E;
LL + let _: Bar = Bar::E;
|
error[E0423]: expected value, found enum `Bar`
--> $DIR/enum-expected-value-suggest-variants.rs:40:18
|
LL | let _: Bar = Bar.Bad(0);
| ^^^
|
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:7:1
|
LL | / enum Bar {
LL | | C(u32),
LL | | D(u32),
LL | | E,
LL | | F,
LL | | }
| |_^
help: you might have meant to use one of the following enum variants
|
LL | let _: Bar = Bar::E.Bad(0);
| +++
LL | let _: Bar = Bar::F.Bad(0);
| +++
help: alternatively, the following enum variants are also available
|
LL - let _: Bar = Bar.Bad(0);
LL + let _: Bar = (Bar::C(/* fields */)).Bad(0);
|
LL - let _: Bar = Bar.Bad(0);
LL + let _: Bar = (Bar::D(/* fields */)).Bad(0);
|
error[E0423]: expected value, found enum `Bar`
--> $DIR/enum-expected-value-suggest-variants.rs:45:18
|
LL | let _: Bar = Bar.Bad;
| ^^^
|
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:7:1
|
LL | / enum Bar {
LL | | C(u32),
LL | | D(u32),
LL | | E,
LL | | F,
LL | | }
| |_^
help: you might have meant to use one of the following enum variants
|
LL | let _: Bar = Bar::E.Bad;
| +++
LL | let _: Bar = Bar::F.Bad;
| +++
help: alternatively, the following enum variants are also available
|
LL - let _: Bar = Bar.Bad;
LL + let _: Bar = (Bar::C(/* fields */)).Bad;
|
LL - let _: Bar = Bar.Bad;
LL + let _: Bar = (Bar::D(/* fields */)).Bad;
|
error[E0531]: cannot find tuple struct or tuple variant `A` in this scope
--> $DIR/enum-expected-value-suggest-variants.rs:51:9
|
LL | A(..) => {}
| ^ not found in this scope
|
help: consider importing this tuple variant
|
LL + use Foo::A;
|
error[E0532]: expected tuple struct or tuple variant, found enum `Foo`
--> $DIR/enum-expected-value-suggest-variants.rs:53:9
|
LL | Foo(..) => {}
| ^^^
|
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:1:1
|
LL | / enum Foo {
LL | |
LL | | A(u32),
LL | | B(u32),
LL | | }
| |_^
help: try to match against one of the enum's variants
|
LL | Foo::A(..) => {}
| +++
LL | Foo::B(..) => {}
| +++
error[E0423]: expected function, tuple struct or tuple variant, found enum `Foo`
--> $DIR/enum-expected-value-suggest-variants.rs:15:18
|
LL | let _: Foo = Foo(0);
| ^^^
|
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:1:1
|
LL | / enum Foo {
LL | |
LL | | A(u32),
LL | | B(u32),
LL | | }
| |_^
help: try to construct one of the enum's variants
|
LL | let _: Foo = Foo::A(0);
| +++
LL | let _: Foo = Foo::B(0);
| +++
error[E0423]: expected function, tuple struct or tuple variant, found enum `Bar`
--> $DIR/enum-expected-value-suggest-variants.rs:27:18
|
LL | let _: Bar = Bar(0);
| ^^^
|
= help: you might have meant to construct one of the enum's non-tuple variants
note: the enum is defined here
--> $DIR/enum-expected-value-suggest-variants.rs:7:1
|
LL | / enum Bar {
LL | | C(u32),
LL | | D(u32),
LL | | E,
LL | | F,
LL | | }
| |_^
help: try to construct one of the enum's variants
|
LL | let _: Bar = Bar::C(0);
| +++
LL | let _: Bar = Bar::D(0);
| +++
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0423, E0531, E0532.
For more information about an error, try `rustc --explain E0423`.

View File

@ -1,60 +0,0 @@
fn main() {
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

@ -1,119 +0,0 @@
error[E0423]: expected value, found struct `String`
--> $DIR/issue-22692.rs:2:13
|
LL | let _ = String.new();
| ^^^^^^
|
help: use the path separator to refer to an item
|
LL - let _ = String.new();
LL + let _ = String::new();
|
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
|
LL - let _ = String.default;
LL + let _ = String::default;
|
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
|
LL - let _ = Vec::<()>.with_capacity(1);
LL + let _ = Vec::<()>::with_capacity(1);
|
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();
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;
LL + <Type! {}>::get;
|
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-22692.rs:26:9
|
LL | Vec.new()
| ^^^
...
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)
help: use the path separator to refer to an item
|
LL - Vec.new()
LL + Vec::new()
|
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-22692.rs:31:9
|
LL | Vec.new
| ^^^
...
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)
help: use the path separator to refer to an item
|
LL - Vec.new
LL + Vec::new
|
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)
LL + <Type!()>::new(0)
|
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0423`.