Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Fix uninhabitedness of non-exhaustive enums.
This commit ensures that non-exhaustive enums are considered inhabited when used in extern crates.
- Loading branch information
Showing
15 changed files
with
398 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,38 @@ | ||
// aux-build:uninhabited.rs | ||
// compile-pass | ||
#![deny(unreachable_patterns)] | ||
#![feature(exhaustive_patterns)] | ||
#![feature(never_type)] | ||
|
||
extern crate uninhabited; | ||
|
||
use uninhabited::{ | ||
PartiallyInhabitedVariants, | ||
UninhabitedEnum, | ||
UninhabitedStruct, | ||
UninhabitedTupleStruct, | ||
UninhabitedVariants, | ||
}; | ||
|
||
fn uninhabited_enum() -> Option<UninhabitedEnum> { | ||
None | ||
} | ||
// This test checks that uninhabited non-exhaustive types cannot coerce to any type, as the never | ||
// type can. | ||
|
||
fn uninhabited_variant() -> Option<UninhabitedVariants> { | ||
None | ||
} | ||
struct A; | ||
|
||
fn partially_inhabited_variant() -> PartiallyInhabitedVariants { | ||
PartiallyInhabitedVariants::Tuple(3) | ||
fn can_coerce_never_type_to_anything(x: !) -> A { | ||
x | ||
} | ||
|
||
fn uninhabited_struct() -> Option<UninhabitedStruct> { | ||
None | ||
fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { | ||
x //~ ERROR mismatched types | ||
} | ||
|
||
fn uninhabited_tuple_struct() -> Option<UninhabitedTupleStruct> { | ||
None | ||
fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { | ||
x //~ ERROR mismatched types | ||
} | ||
|
||
// This test checks that non-exhaustive types that would normally be considered uninhabited within | ||
// the defining crate are not considered uninhabited from extern crates. | ||
|
||
fn main() { | ||
match uninhabited_enum() { | ||
Some(_x) => (), // This line would normally error. | ||
None => (), | ||
} | ||
|
||
match uninhabited_variant() { | ||
Some(_x) => (), // This line would normally error. | ||
None => (), | ||
} | ||
|
||
// This line would normally error. | ||
while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { | ||
} | ||
|
||
while let Some(_x) = uninhabited_struct() { // This line would normally error. | ||
} | ||
fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { | ||
x //~ ERROR mismatched types | ||
} | ||
|
||
while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. | ||
} | ||
fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { | ||
x //~ ERROR mismatched types | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
error[E0308]: mismatched types | ||
--> $DIR/uninhabited.rs:23:5 | ||
| | ||
LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { | ||
| - expected `A` because of return type | ||
LL | x | ||
| ^ expected struct `A`, found enum `uninhabited::UninhabitedEnum` | ||
| | ||
= note: expected type `A` | ||
found type `uninhabited::UninhabitedEnum` | ||
|
||
error[E0308]: mismatched types | ||
--> $DIR/uninhabited.rs:27:5 | ||
| | ||
LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { | ||
| - expected `A` because of return type | ||
LL | x | ||
| ^ expected struct `A`, found struct `uninhabited::UninhabitedTupleStruct` | ||
| | ||
= note: expected type `A` | ||
found type `uninhabited::UninhabitedTupleStruct` | ||
|
||
error[E0308]: mismatched types | ||
--> $DIR/uninhabited.rs:31:5 | ||
| | ||
LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { | ||
| - expected `A` because of return type | ||
LL | x | ||
| ^ expected struct `A`, found struct `uninhabited::UninhabitedStruct` | ||
| | ||
= note: expected type `A` | ||
found type `uninhabited::UninhabitedStruct` | ||
|
||
error[E0308]: mismatched types | ||
--> $DIR/uninhabited.rs:35:5 | ||
| | ||
LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { | ||
| - expected `A` because of return type | ||
LL | x | ||
| ^ expected struct `A`, found enum `uninhabited::UninhabitedVariants` | ||
| | ||
= note: expected type `A` | ||
found type `uninhabited::UninhabitedVariants` | ||
|
||
error: aborting due to 4 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0308`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// aux-build:uninhabited.rs | ||
#![feature(never_type)] | ||
|
||
extern crate uninhabited; | ||
|
||
use uninhabited::{ | ||
UninhabitedEnum, | ||
}; | ||
|
||
struct A; | ||
|
||
// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate | ||
// will not compile. | ||
|
||
fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { | ||
match x {} //~ ERROR non-exhaustive patterns | ||
} | ||
|
||
fn main() {} |
11 changes: 11 additions & 0 deletions
11
src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty | ||
--> $DIR/uninhabited_match.rs:16:11 | ||
| | ||
LL | match x {} | ||
| ^ | ||
| | ||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0004`. |
18 changes: 18 additions & 0 deletions
18
src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// compile-pass | ||
#![feature(never_type)] | ||
#![feature(non_exhaustive)] | ||
|
||
#[non_exhaustive] | ||
pub enum UninhabitedEnum { | ||
} | ||
|
||
struct A; | ||
|
||
// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate | ||
// will compile. | ||
|
||
fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { | ||
match x {} | ||
} | ||
|
||
fn main() {} |
22 changes: 22 additions & 0 deletions
22
src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// aux-build:uninhabited.rs | ||
#![deny(unreachable_patterns)] | ||
#![feature(exhaustive_patterns)] | ||
#![feature(never_type)] | ||
|
||
extern crate uninhabited; | ||
|
||
use uninhabited::{ | ||
UninhabitedEnum, | ||
}; | ||
|
||
struct A; | ||
|
||
// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate | ||
// will not compile. In particular, this enables the `exhaustive_patterns` feature as this can | ||
// change the branch used in the compiler to determine this. | ||
|
||
fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { | ||
match x {} //~ ERROR non-exhaustive patterns | ||
} | ||
|
||
fn main() {} |
11 changes: 11 additions & 0 deletions
11
src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty | ||
--> $DIR/uninhabited_match_with_exhaustive_patterns.rs:19:11 | ||
| | ||
LL | match x {} | ||
| ^ | ||
| | ||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0004`. |
21 changes: 21 additions & 0 deletions
21
src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// compile-pass | ||
#![deny(unreachable_patterns)] | ||
#![feature(exhaustive_patterns)] | ||
#![feature(never_type)] | ||
#![feature(non_exhaustive)] | ||
|
||
#[non_exhaustive] | ||
pub enum UninhabitedEnum { | ||
} | ||
|
||
struct A; | ||
|
||
// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate | ||
// will compile. In particular, this enables the `exhaustive_patterns` feature as this can | ||
// change the branch used in the compiler to determine this. | ||
|
||
fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { | ||
match x {} | ||
} | ||
|
||
fn main() {} |
59 changes: 59 additions & 0 deletions
59
src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// aux-build:uninhabited.rs | ||
// compile-pass | ||
#![deny(unreachable_patterns)] | ||
#![feature(exhaustive_patterns)] | ||
|
||
extern crate uninhabited; | ||
|
||
use uninhabited::{ | ||
PartiallyInhabitedVariants, | ||
UninhabitedEnum, | ||
UninhabitedStruct, | ||
UninhabitedTupleStruct, | ||
UninhabitedVariants, | ||
}; | ||
|
||
fn uninhabited_enum() -> Option<UninhabitedEnum> { | ||
None | ||
} | ||
|
||
fn uninhabited_variant() -> Option<UninhabitedVariants> { | ||
None | ||
} | ||
|
||
fn partially_inhabited_variant() -> PartiallyInhabitedVariants { | ||
PartiallyInhabitedVariants::Tuple(3) | ||
} | ||
|
||
fn uninhabited_struct() -> Option<UninhabitedStruct> { | ||
None | ||
} | ||
|
||
fn uninhabited_tuple_struct() -> Option<UninhabitedTupleStruct> { | ||
None | ||
} | ||
|
||
// This test checks that non-exhaustive types that would normally be considered uninhabited within | ||
// the defining crate are not considered uninhabited from extern crates. | ||
|
||
fn main() { | ||
match uninhabited_enum() { | ||
Some(_x) => (), // This line would normally error. | ||
None => (), | ||
} | ||
|
||
match uninhabited_variant() { | ||
Some(_x) => (), // This line would normally error. | ||
None => (), | ||
} | ||
|
||
// This line would normally error. | ||
while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { | ||
} | ||
|
||
while let Some(_x) = uninhabited_struct() { // This line would normally error. | ||
} | ||
|
||
while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#![deny(unreachable_patterns)] | ||
#![feature(exhaustive_patterns)] | ||
#![feature(never_type)] | ||
#![feature(non_exhaustive)] | ||
|
||
#[non_exhaustive] | ||
pub enum UninhabitedEnum { | ||
} | ||
|
||
#[non_exhaustive] | ||
pub struct UninhabitedTupleStruct(!); | ||
|
||
#[non_exhaustive] | ||
pub struct UninhabitedStruct { | ||
_priv: !, | ||
} | ||
|
||
pub enum UninhabitedVariants { | ||
#[non_exhaustive] Tuple(!), | ||
#[non_exhaustive] Struct { x: ! } | ||
} | ||
|
||
pub enum PartiallyInhabitedVariants { | ||
Tuple(u8), | ||
#[non_exhaustive] Struct { x: ! } | ||
} | ||
|
||
fn uninhabited_enum() -> Option<UninhabitedEnum> { | ||
None | ||
} | ||
|
||
fn uninhabited_variant() -> Option<UninhabitedVariants> { | ||
None | ||
} | ||
|
||
fn partially_inhabited_variant() -> PartiallyInhabitedVariants { | ||
PartiallyInhabitedVariants::Tuple(3) | ||
} | ||
|
||
fn uninhabited_struct() -> Option<UninhabitedStruct> { | ||
None | ||
} | ||
|
||
fn uninhabited_tuple_struct() -> Option<UninhabitedTupleStruct> { | ||
None | ||
} | ||
|
||
// This test checks that non-exhaustive types that would normally be considered uninhabited within | ||
// the defining crate are still considered uninhabited. | ||
|
||
fn main() { | ||
match uninhabited_enum() { | ||
Some(_x) => (), //~ ERROR unreachable pattern | ||
None => (), | ||
} | ||
|
||
match uninhabited_variant() { | ||
Some(_x) => (), //~ ERROR unreachable pattern | ||
None => (), | ||
} | ||
|
||
while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ||
//~^ ERROR unreachable pattern | ||
} | ||
|
||
while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern | ||
} | ||
|
||
while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern | ||
} | ||
} |
Oops, something went wrong.