mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Disallow arm bodies on never patterns
This commit is contained in:
parent
06a8ed10b6
commit
70deb9a57f
@ -108,6 +108,11 @@ ast_lowering_misplaced_impl_trait =
|
|||||||
ast_lowering_misplaced_relax_trait_bound =
|
ast_lowering_misplaced_relax_trait_bound =
|
||||||
`?Trait` bounds are only permitted at the point where a type parameter is declared
|
`?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||||
|
|
||||||
|
ast_lowering_never_pattern_with_body =
|
||||||
|
a never pattern is always unreachable
|
||||||
|
.label = this will never be executed
|
||||||
|
.suggestion = remove this expression
|
||||||
|
|
||||||
ast_lowering_never_pattern_with_guard =
|
ast_lowering_never_pattern_with_guard =
|
||||||
a guard on a never pattern will never be run
|
a guard on a never pattern will never be run
|
||||||
.suggestion = remove this guard
|
.suggestion = remove this guard
|
||||||
|
@ -349,6 +349,15 @@ pub struct MatchArmWithNoBody {
|
|||||||
pub suggestion: Span,
|
pub suggestion: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_lowering_never_pattern_with_body)]
|
||||||
|
pub struct NeverPatternWithBody {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
#[suggestion(code = "", applicability = "maybe-incorrect")]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_lowering_never_pattern_with_guard)]
|
#[diag(ast_lowering_never_pattern_with_guard)]
|
||||||
pub struct NeverPatternWithGuard {
|
pub struct NeverPatternWithGuard {
|
||||||
|
@ -2,7 +2,8 @@ use super::errors::{
|
|||||||
AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
|
AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
|
||||||
BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
|
BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
|
||||||
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
|
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
|
||||||
NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign,
|
NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure,
|
||||||
|
UnderscoreExprLhsAssign,
|
||||||
};
|
};
|
||||||
use super::ResolverAstLoweringExt;
|
use super::ResolverAstLoweringExt;
|
||||||
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
|
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
|
||||||
@ -567,20 +568,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let hir_id = self.next_id();
|
let hir_id = self.next_id();
|
||||||
let span = self.lower_span(arm.span);
|
let span = self.lower_span(arm.span);
|
||||||
self.lower_attrs(hir_id, &arm.attrs);
|
self.lower_attrs(hir_id, &arm.attrs);
|
||||||
let body = if let Some(body) = &arm.body {
|
let is_never_pattern = pat.is_never_pattern();
|
||||||
// FIXME(never_patterns): Disallow never pattern with a body or guard
|
let body = if let Some(body) = &arm.body
|
||||||
|
&& !is_never_pattern
|
||||||
|
{
|
||||||
self.lower_expr(body)
|
self.lower_expr(body)
|
||||||
} else {
|
} else {
|
||||||
if !pat.is_never_pattern() {
|
// Either `body.is_none()` or `is_never_pattern` here.
|
||||||
self.tcx
|
if !is_never_pattern {
|
||||||
.sess
|
let suggestion = span.shrink_to_hi();
|
||||||
.emit_err(MatchArmWithNoBody { span, suggestion: span.shrink_to_hi() });
|
self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
|
||||||
|
} else if let Some(body) = &arm.body {
|
||||||
|
self.tcx.sess.emit_err(NeverPatternWithBody { span: body.span });
|
||||||
|
guard = None;
|
||||||
} else if let Some(g) = &arm.guard {
|
} else if let Some(g) = &arm.guard {
|
||||||
self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span });
|
self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span });
|
||||||
guard = None;
|
guard = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// An arm without a body, meant for never patterns.
|
|
||||||
// We add a fake `loop {}` arm body so that it typecks to `!`.
|
// We add a fake `loop {}` arm body so that it typecks to `!`.
|
||||||
// FIXME(never_patterns): Desugar into a call to `unreachable_unchecked`.
|
// FIXME(never_patterns): Desugar into a call to `unreachable_unchecked`.
|
||||||
let block = self.arena.alloc(hir::Block {
|
let block = self.arena.alloc(hir::Block {
|
||||||
|
@ -12,7 +12,7 @@ fn main() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let ptr: *const Void = NonNull::dangling().as_ptr();
|
let ptr: *const Void = NonNull::dangling().as_ptr();
|
||||||
match *ptr {
|
match *ptr {
|
||||||
! => {} //~ ERROR `!` patterns are experimental
|
! //~ ERROR `!` patterns are experimental
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ LL | let (Ok(_x) | Err(&!)) = res.as_ref();
|
|||||||
error[E0658]: `!` patterns are experimental
|
error[E0658]: `!` patterns are experimental
|
||||||
--> $DIR/feature-gate-never_patterns.rs:15:13
|
--> $DIR/feature-gate-never_patterns.rs:15:13
|
||||||
|
|
|
|
||||||
LL | ! => {}
|
LL | !
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
|
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
|
||||||
|
@ -12,6 +12,7 @@ macro_rules! never {
|
|||||||
fn no_arms_or_guards(x: Void) {
|
fn no_arms_or_guards(x: Void) {
|
||||||
match None::<Void> {
|
match None::<Void> {
|
||||||
Some(!) => {}
|
Some(!) => {}
|
||||||
|
//~^ ERROR a never pattern is always unreachable
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
match None::<Void> {
|
match None::<Void> {
|
||||||
@ -21,10 +22,12 @@ fn no_arms_or_guards(x: Void) {
|
|||||||
}
|
}
|
||||||
match None::<Void> {
|
match None::<Void> {
|
||||||
Some(!) if true => {}
|
Some(!) if true => {}
|
||||||
|
//~^ ERROR a never pattern is always unreachable
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
match None::<Void> {
|
match None::<Void> {
|
||||||
Some(never!()) => {},
|
Some(never!()) => {},
|
||||||
|
//~^ ERROR a never pattern is always unreachable
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,35 @@
|
|||||||
|
error: a never pattern is always unreachable
|
||||||
|
--> $DIR/check.rs:14:20
|
||||||
|
|
|
||||||
|
LL | Some(!) => {}
|
||||||
|
| ^^
|
||||||
|
| |
|
||||||
|
| this will never be executed
|
||||||
|
| help: remove this expression
|
||||||
|
|
||||||
error: a guard on a never pattern will never be run
|
error: a guard on a never pattern will never be run
|
||||||
--> $DIR/check.rs:18:20
|
--> $DIR/check.rs:19:20
|
||||||
|
|
|
|
||||||
LL | Some(!) if true,
|
LL | Some(!) if true,
|
||||||
| ^^^^ help: remove this guard
|
| ^^^^ help: remove this guard
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: a never pattern is always unreachable
|
||||||
|
--> $DIR/check.rs:24:28
|
||||||
|
|
|
||||||
|
LL | Some(!) if true => {}
|
||||||
|
| ^^
|
||||||
|
| |
|
||||||
|
| this will never be executed
|
||||||
|
| help: remove this expression
|
||||||
|
|
||||||
|
error: a never pattern is always unreachable
|
||||||
|
--> $DIR/check.rs:29:27
|
||||||
|
|
|
||||||
|
LL | Some(never!()) => {},
|
||||||
|
| ^^
|
||||||
|
| |
|
||||||
|
| this will never be executed
|
||||||
|
| help: remove this expression
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -20,58 +20,58 @@ fn never_pattern_location(void: Void) {
|
|||||||
// FIXME(never_patterns): Don't accept on a non-empty type.
|
// FIXME(never_patterns): Don't accept on a non-empty type.
|
||||||
match Some(0) {
|
match Some(0) {
|
||||||
None => {}
|
None => {}
|
||||||
Some(!) => {}
|
Some(!),
|
||||||
}
|
}
|
||||||
// FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches.
|
// FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches.
|
||||||
match () {
|
match () {
|
||||||
() => {}
|
() => {}
|
||||||
! => {}
|
!,
|
||||||
}
|
}
|
||||||
// FIXME(never_patterns): Don't accept even on an empty branch.
|
// FIXME(never_patterns): Don't accept even on an empty branch.
|
||||||
match None::<Void> {
|
match None::<Void> {
|
||||||
None => {}
|
None => {}
|
||||||
! => {}
|
!,
|
||||||
}
|
}
|
||||||
// FIXME(never_patterns): Let alone if the emptiness is behind a reference.
|
// FIXME(never_patterns): Let alone if the emptiness is behind a reference.
|
||||||
match None::<&Void> {
|
match None::<&Void> {
|
||||||
None => {}
|
None => {}
|
||||||
! => {}
|
!,
|
||||||
}
|
}
|
||||||
// Participate in match ergonomics.
|
// Participate in match ergonomics.
|
||||||
match &void {
|
match &void {
|
||||||
! => {}
|
!
|
||||||
}
|
}
|
||||||
match &&void {
|
match &&void {
|
||||||
! => {}
|
!
|
||||||
}
|
}
|
||||||
match &&void {
|
match &&void {
|
||||||
&! => {}
|
&!
|
||||||
}
|
}
|
||||||
match &None::<Void> {
|
match &None::<Void> {
|
||||||
None => {}
|
None => {}
|
||||||
Some(!) => {}
|
Some(!)
|
||||||
}
|
}
|
||||||
match None::<&Void> {
|
match None::<&Void> {
|
||||||
None => {}
|
None => {}
|
||||||
Some(!) => {}
|
Some(!),
|
||||||
}
|
}
|
||||||
// Accept on a composite empty type.
|
// Accept on a composite empty type.
|
||||||
match None::<&(u32, Void)> {
|
match None::<&(u32, Void)> {
|
||||||
None => {}
|
None => {}
|
||||||
Some(&!) => {}
|
Some(&!),
|
||||||
}
|
}
|
||||||
// Accept on an simple empty type.
|
// Accept on an simple empty type.
|
||||||
match None::<Void> {
|
match None::<Void> {
|
||||||
None => {}
|
None => {}
|
||||||
Some(!) => {}
|
Some(!),
|
||||||
}
|
}
|
||||||
match None::<&Void> {
|
match None::<&Void> {
|
||||||
None => {}
|
None => {}
|
||||||
Some(&!) => {}
|
Some(&!),
|
||||||
}
|
}
|
||||||
match None::<&(u32, Void)> {
|
match None::<&(u32, Void)> {
|
||||||
None => {}
|
None => {}
|
||||||
Some(&(_, !)) => {}
|
Some(&(_, !)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ fn never_and_bindings() {
|
|||||||
// FIXME(never_patterns): A never pattern mustn't have bindings.
|
// FIXME(never_patterns): A never pattern mustn't have bindings.
|
||||||
match x {
|
match x {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(&(_b, !)) => {}
|
Err(&(_b, !)),
|
||||||
}
|
}
|
||||||
match x {
|
match x {
|
||||||
Ok(_a) | Err(&(_b, !)) => {}
|
Ok(_a) | Err(&(_b, !)) => {}
|
||||||
|
Loading…
Reference in New Issue
Block a user