mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +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 =
|
||||
`?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 =
|
||||
a guard on a never pattern will never be run
|
||||
.suggestion = remove this guard
|
||||
|
@ -349,6 +349,15 @@ pub struct MatchArmWithNoBody {
|
||||
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)]
|
||||
#[diag(ast_lowering_never_pattern_with_guard)]
|
||||
pub struct NeverPatternWithGuard {
|
||||
|
@ -2,7 +2,8 @@ use super::errors::{
|
||||
AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
|
||||
BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
|
||||
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
|
||||
NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign,
|
||||
NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure,
|
||||
UnderscoreExprLhsAssign,
|
||||
};
|
||||
use super::ResolverAstLoweringExt;
|
||||
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
|
||||
@ -567,20 +568,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let hir_id = self.next_id();
|
||||
let span = self.lower_span(arm.span);
|
||||
self.lower_attrs(hir_id, &arm.attrs);
|
||||
let body = if let Some(body) = &arm.body {
|
||||
// FIXME(never_patterns): Disallow never pattern with a body or guard
|
||||
let is_never_pattern = pat.is_never_pattern();
|
||||
let body = if let Some(body) = &arm.body
|
||||
&& !is_never_pattern
|
||||
{
|
||||
self.lower_expr(body)
|
||||
} else {
|
||||
if !pat.is_never_pattern() {
|
||||
self.tcx
|
||||
.sess
|
||||
.emit_err(MatchArmWithNoBody { span, suggestion: span.shrink_to_hi() });
|
||||
// Either `body.is_none()` or `is_never_pattern` here.
|
||||
if !is_never_pattern {
|
||||
let 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 {
|
||||
self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span });
|
||||
guard = None;
|
||||
}
|
||||
|
||||
// An arm without a body, meant for never patterns.
|
||||
// We add a fake `loop {}` arm body so that it typecks to `!`.
|
||||
// FIXME(never_patterns): Desugar into a call to `unreachable_unchecked`.
|
||||
let block = self.arena.alloc(hir::Block {
|
||||
|
@ -12,7 +12,7 @@ fn main() {
|
||||
unsafe {
|
||||
let ptr: *const Void = NonNull::dangling().as_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
|
||||
--> $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
|
||||
|
@ -12,6 +12,7 @@ macro_rules! never {
|
||||
fn no_arms_or_guards(x: Void) {
|
||||
match None::<Void> {
|
||||
Some(!) => {}
|
||||
//~^ ERROR a never pattern is always unreachable
|
||||
None => {}
|
||||
}
|
||||
match None::<Void> {
|
||||
@ -21,10 +22,12 @@ fn no_arms_or_guards(x: Void) {
|
||||
}
|
||||
match None::<Void> {
|
||||
Some(!) if true => {}
|
||||
//~^ ERROR a never pattern is always unreachable
|
||||
None => {}
|
||||
}
|
||||
match None::<Void> {
|
||||
Some(never!()) => {},
|
||||
//~^ ERROR a never pattern is always unreachable
|
||||
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
|
||||
--> $DIR/check.rs:18:20
|
||||
--> $DIR/check.rs:19:20
|
||||
|
|
||||
LL | Some(!) if true,
|
||||
| ^^^^ 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.
|
||||
match Some(0) {
|
||||
None => {}
|
||||
Some(!) => {}
|
||||
Some(!),
|
||||
}
|
||||
// FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches.
|
||||
match () {
|
||||
() => {}
|
||||
! => {}
|
||||
!,
|
||||
}
|
||||
// FIXME(never_patterns): Don't accept even on an empty branch.
|
||||
match None::<Void> {
|
||||
None => {}
|
||||
! => {}
|
||||
!,
|
||||
}
|
||||
// FIXME(never_patterns): Let alone if the emptiness is behind a reference.
|
||||
match None::<&Void> {
|
||||
None => {}
|
||||
! => {}
|
||||
!,
|
||||
}
|
||||
// Participate in match ergonomics.
|
||||
match &void {
|
||||
! => {}
|
||||
!
|
||||
}
|
||||
match &&void {
|
||||
! => {}
|
||||
!
|
||||
}
|
||||
match &&void {
|
||||
&! => {}
|
||||
&!
|
||||
}
|
||||
match &None::<Void> {
|
||||
None => {}
|
||||
Some(!) => {}
|
||||
Some(!)
|
||||
}
|
||||
match None::<&Void> {
|
||||
None => {}
|
||||
Some(!) => {}
|
||||
Some(!),
|
||||
}
|
||||
// Accept on a composite empty type.
|
||||
match None::<&(u32, Void)> {
|
||||
None => {}
|
||||
Some(&!) => {}
|
||||
Some(&!),
|
||||
}
|
||||
// Accept on an simple empty type.
|
||||
match None::<Void> {
|
||||
None => {}
|
||||
Some(!) => {}
|
||||
Some(!),
|
||||
}
|
||||
match None::<&Void> {
|
||||
None => {}
|
||||
Some(&!) => {}
|
||||
Some(&!),
|
||||
}
|
||||
match None::<&(u32, Void)> {
|
||||
None => {}
|
||||
Some(&(_, !)) => {}
|
||||
Some(&(_, !)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ fn never_and_bindings() {
|
||||
// FIXME(never_patterns): A never pattern mustn't have bindings.
|
||||
match x {
|
||||
Ok(_) => {}
|
||||
Err(&(_b, !)) => {}
|
||||
Err(&(_b, !)),
|
||||
}
|
||||
match x {
|
||||
Ok(_a) | Err(&(_b, !)) => {}
|
||||
|
Loading…
Reference in New Issue
Block a user