Skip to content

R raymond/fix/issue 107165 #125716

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
Closed
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
6 changes: 6 additions & 0 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1896,13 +1896,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
// Final step in the import chain, point out if the ADT is `non_exhaustive`
// which is probably why this privacy violation occurred.
let mut err_help = None;
if next_binding.is_none()
&& let Some(span) = non_exhaustive
{
note_span.push_span_label(
span,
"cannot be constructed because it is `#[non_exhaustive]`",
);
err_help =
Some(format!("consider using a struct pattern instead: `{ident} {{ .. }}`"));
}
let note = errors::NoteAndRefersToTheItemDefinedHere {
span: note_span,
Expand All @@ -1912,6 +1915,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
dots: next_binding.is_some(),
};
err.subdiagnostic(self.tcx.dcx(), note);
if let Some(err_help) = err_help {
err.span_help(ident.span, err_help);
}
}
// We prioritize shorter paths, non-core imports and direct imports over the alternatives.
sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0] == "core", *reexport));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub enum Elibrary {
#[non_exhaustive]
Unit,

#[non_exhaustive]
Tuple(i64),
}
49 changes: 49 additions & 0 deletions tests/ui/match/non-exhaustive-variant-hint-issue-107165.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//@ aux-build:non_exhaustive_structs_and_variants_lib.rs

/* Provide a hint to the user that a match of a non-exhaustive variant might
* fail because of a missing struct pattern (issue #107165).
*/

// Ignore non_exhaustive in the same crate
enum Elocal {
#[non_exhaustive]
Unit,

#[non_exhaustive]
Tuple(i64),
}

extern crate non_exhaustive_structs_and_variants_lib;
use non_exhaustive_structs_and_variants_lib::Elibrary;

fn local() -> Elocal {
todo!()
}

fn library() -> Elibrary {
todo!()
}

fn main() {
let loc = local();
// No error for enums defined in this crate
match loc {
Elocal::Unit => (),
Elocal::Tuple(_) => (),
};

// Elibrary is externally defined
let lib = library();

match lib {
Elibrary::Unit => (),
//~^ ERROR unit variant `Unit` is private [E0603]
_ => (),
};

match lib {
Elibrary::Tuple(_) => (),
//~^ ERROR tuple variant `Tuple` is private [E0603]
_ => (),
};
}
41 changes: 41 additions & 0 deletions tests/ui/match/non-exhaustive-variant-hint-issue-107165.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
error[E0603]: unit variant `Unit` is private
--> $DIR/non-exhaustive-variant-hint-issue-107165.rs:39:19
|
LL | Elibrary::Unit => (),
| ^^^^ private unit variant
|
note: the unit variant `Unit` is defined here
--> $DIR/auxiliary/non_exhaustive_structs_and_variants_lib.rs:3:5
|
LL | #[non_exhaustive]
| ----------------- cannot be constructed because it is `#[non_exhaustive]`
LL | Unit,
| ^^^^
help: consider using a struct pattern instead: `Unit { .. }`
--> $DIR/non-exhaustive-variant-hint-issue-107165.rs:39:19
|
LL | Elibrary::Unit => (),
| ^^^^

error[E0603]: tuple variant `Tuple` is private
--> $DIR/non-exhaustive-variant-hint-issue-107165.rs:45:19
|
LL | Elibrary::Tuple(_) => (),
| ^^^^^ private tuple variant
|
note: the tuple variant `Tuple` is defined here
--> $DIR/auxiliary/non_exhaustive_structs_and_variants_lib.rs:6:5
|
LL | #[non_exhaustive]
| ----------------- cannot be constructed because it is `#[non_exhaustive]`
LL | Tuple(i64),
| ^^^^^
help: consider using a struct pattern instead: `Tuple { .. }`
--> $DIR/non-exhaustive-variant-hint-issue-107165.rs:45:19
|
LL | Elibrary::Tuple(_) => (),
| ^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0603`.
10 changes: 10 additions & 0 deletions tests/ui/rfcs/rfc-2008-non-exhaustive/struct.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ LL | #[non_exhaustive]
| ----------------- cannot be constructed because it is `#[non_exhaustive]`
LL | pub struct TupleStruct(pub u16, pub u16);
| ^^^^^^^^^^^^^^^^^^^^^^
help: consider using a struct pattern instead: `TupleStruct { .. }`
--> $DIR/struct.rs:23:32
|
LL | let ts_explicit = structs::TupleStruct(640, 480);
| ^^^^^^^^^^^

error[E0603]: unit struct `UnitStruct` is private
--> $DIR/struct.rs:32:32
Expand All @@ -31,6 +36,11 @@ LL | #[non_exhaustive]
| ----------------- cannot be constructed because it is `#[non_exhaustive]`
LL | pub struct UnitStruct;
| ^^^^^^^^^^^^^^^^^^^^^
help: consider using a struct pattern instead: `UnitStruct { .. }`
--> $DIR/struct.rs:32:32
|
LL | let us_explicit = structs::UnitStruct;
| ^^^^^^^^^^

error[E0639]: cannot create non-exhaustive struct using struct expression
--> $DIR/struct.rs:7:14
Expand Down
25 changes: 25 additions & 0 deletions tests/ui/rfcs/rfc-2008-non-exhaustive/variant.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ LL | #[non_exhaustive] Tuple(u32),
| ----------------- ^^^^^
| |
| cannot be constructed because it is `#[non_exhaustive]`
help: consider using a struct pattern instead: `Tuple { .. }`
--> $DIR/variant.rs:11:48
|
LL | let variant_tuple = NonExhaustiveVariants::Tuple(640);
| ^^^^^

error[E0603]: unit variant `Unit` is private
--> $DIR/variant.rs:14:47
Expand All @@ -25,6 +30,11 @@ LL | #[non_exhaustive] Unit,
| ----------------- ^^^^
| |
| cannot be constructed because it is `#[non_exhaustive]`
help: consider using a struct pattern instead: `Unit { .. }`
--> $DIR/variant.rs:14:47
|
LL | let variant_unit = NonExhaustiveVariants::Unit;
| ^^^^

error[E0603]: unit variant `Unit` is private
--> $DIR/variant.rs:18:32
Expand All @@ -39,6 +49,11 @@ LL | #[non_exhaustive] Unit,
| ----------------- ^^^^
| |
| cannot be constructed because it is `#[non_exhaustive]`
help: consider using a struct pattern instead: `Unit { .. }`
--> $DIR/variant.rs:18:32
|
LL | NonExhaustiveVariants::Unit => "",
| ^^^^

error[E0603]: tuple variant `Tuple` is private
--> $DIR/variant.rs:20:32
Expand All @@ -53,6 +68,11 @@ LL | #[non_exhaustive] Tuple(u32),
| ----------------- ^^^^^
| |
| cannot be constructed because it is `#[non_exhaustive]`
help: consider using a struct pattern instead: `Tuple { .. }`
--> $DIR/variant.rs:20:32
|
LL | NonExhaustiveVariants::Tuple(fe_tpl) => "",
| ^^^^^

error[E0603]: tuple variant `Tuple` is private
--> $DIR/variant.rs:26:35
Expand All @@ -67,6 +87,11 @@ LL | #[non_exhaustive] Tuple(u32),
| ----------------- ^^^^^
| |
| cannot be constructed because it is `#[non_exhaustive]`
help: consider using a struct pattern instead: `Tuple { .. }`
--> $DIR/variant.rs:26:35
|
LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
| ^^^^^

error[E0639]: cannot create non-exhaustive variant using struct expression
--> $DIR/variant.rs:8:26
Expand Down
Loading