diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e6e445c54b1e3..07b08f69277cd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -39,6 +39,7 @@ declare_lint_pass! { DUPLICATE_MACRO_ATTRIBUTES, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, ELIDED_LIFETIMES_IN_PATHS, + EMPTY_MATCH_ON_UNSAFE_PLACE, EXPORTED_PRIVATE_DEPENDENCIES, FFI_UNWIND_CALLS, FORBIDDEN_LINT_GROUPS, @@ -4019,6 +4020,76 @@ declare_lint! { @feature_gate = sym::non_exhaustive_omitted_patterns_lint; } +declare_lint! { + /// The `empty_match_on_unsafe_place` lint detects uses of `match ... {}` on an empty type where + /// the matched place could contain invalid data in a well-defined program. These matches are + /// considered exhaustive for backwards-compatibility, but they shouldn't be since a `_` arm + /// would be reachable. + /// + /// This will become an error in the future. + /// + /// ### Example + /// + /// ```compile_fail + /// #![feature(min_exhaustive_patterns)] + /// enum Void {} + /// let ptr: *const Void = ...; + /// unsafe { + /// match *ptr {} + /// } + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning: empty match on potentially-invalid data + /// --> $DIR/empty-types.rs:157:9 + /// | + /// LL | match *ptr {} + /// | ^^^^^^^^^^^^^ + /// | + /// note: this place can hold invalid data, which would make the match reachable + /// --> $DIR/empty-types.rs:157:15 + /// | + /// LL | match *ptr {} + /// | ^^^^ + /// = note: `#[warn(empty_match_on_unsafe_place)]` on by default + /// help: consider forcing a read of the value + /// | + /// LL | match { *ptr } {} + /// | + + + /// ``` + /// + /// ### Explanation + /// + /// Some place expressions (namely pointer dereferences, union field accesses, and + /// (conservatively) reference dereferences) can hold invalid data without causing UB. For + /// example, the following is a well-defined program that prints "reachable!". + /// + /// ```rust + /// #[derive(Copy, Clone)] + /// enum Void {} + /// union Uninit { + /// value: T, + /// uninit: (), + /// } + /// unsafe { + /// let x: Uninit = Uninit { uninit: () }; + /// match x.value { + /// _ => println!("reachable!"), + /// } + /// } + /// ``` + /// + /// Therefore when the matched place can hold invalid data, a match with no arm should not be + /// considered exhaustive. For backwards-compatibility we consider them exhaustive but warn with + /// this lint. It will become an error in the future. + pub EMPTY_MATCH_ON_UNSAFE_PLACE, + Warn, + "warn about empty matches on a place with potentially-invalid data", + @feature_gate = sym::min_exhaustive_patterns; +} + declare_lint! { /// The `text_direction_codepoint_in_comment` lint detects Unicode codepoints in comments that /// change the visual representation of text on screen in a way that does not correspond to diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index c8d6c2114e9eb..a35384cbfcd3c 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -97,6 +97,13 @@ mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior .label = dereference of raw pointer +mir_build_empty_match_on_unsafe_place = + empty match on potentially-invalid data + .note = this place can hold invalid data, which would make the match reachable + +mir_build_empty_match_on_unsafe_place_wrap_suggestion = + consider forcing a read of the value + mir_build_extern_static_requires_unsafe = use of extern static is unsafe and requires unsafe block .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 8d2a559e73ce4..aed6ea047df8a 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -841,6 +841,27 @@ impl<'tcx> AddToDiagnostic for Overlap<'tcx> { } } +#[derive(LintDiagnostic)] +#[diag(mir_build_empty_match_on_unsafe_place)] +pub struct EmptyMatchOnUnsafePlace { + #[note] + pub scrut_span: Span, + #[subdiagnostic] + pub suggestion: EmptyMatchOnUnsafePlaceWrapSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + mir_build_empty_match_on_unsafe_place_wrap_suggestion, + applicability = "maybe-incorrect" +)] +pub struct EmptyMatchOnUnsafePlaceWrapSuggestion { + #[suggestion_part(code = "{{ ")] + pub scrut_start: Span, + #[suggestion_part(code = " }}")] + pub scrut_end: Span, +} + #[derive(LintDiagnostic)] #[diag(mir_build_non_exhaustive_omitted_pattern)] #[help] diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 27b5c4e67a58e..f00a011af73a3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -557,8 +557,8 @@ use super::deconstruct_pat::{ WitnessPat, }; use crate::errors::{ - NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap, - OverlappingRangeEndpoints, Uncovered, + EmptyMatchOnUnsafePlace, EmptyMatchOnUnsafePlaceWrapSuggestion, NonExhaustiveOmittedPattern, + NonExhaustiveOmittedPatternLintOnArm, Overlap, OverlappingRangeEndpoints, Uncovered, }; use rustc_data_structures::captures::Captures; @@ -1238,22 +1238,17 @@ fn compute_exhaustiveness_and_usefulness<'p, 'tcx>( debug!("ty: {ty:?}"); let pcx = &PatCtxt { cx, ty, is_top_level }; - let ctors_for_ty = ConstructorSet::for_ty(cx, ty); // Whether the place/column we are inspecting is known to contain valid data. let mut place_validity = matrix.place_validity[0]; - if !pcx.cx.tcx.features().min_exhaustive_patterns - || (is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors)) - { - // For backwards compability we allow omitting some empty arms that we ideally shouldn't. + if cx.tcx.features().exhaustive_patterns { + // Under `exhaustive_patterns` we allow omitting empty arms even when they aren't redundant. place_validity = place_validity.allow_omitting_side_effecting_arms(); } // Analyze the constructors present in this column. let ctors = matrix.heads().map(|p| p.ctor()); - let split_set = ctors_for_ty.split(pcx, ctors); - - // Decide what constructors to report. + let split_set = ConstructorSet::for_ty(cx, ty).split(pcx, ctors); let all_missing = split_set.present.is_empty(); // Build the set of constructors we will specialize with. It must cover the whole type. @@ -1578,6 +1573,40 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( arms: &[MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, ) -> UsefulnessReport<'p, 'tcx> { + if !cx.known_valid_scrutinee && arms.iter().all(|arm| arm.has_guard) { + let is_directly_empty = match scrut_ty.kind() { + ty::Adt(def, ..) => { + def.is_enum() + && def.variants().is_empty() + && !cx.is_foreign_non_exhaustive_enum(scrut_ty) + } + ty::Never => true, + _ => false, + }; + if is_directly_empty { + if cx.tcx.features().min_exhaustive_patterns { + cx.tcx.emit_spanned_lint( + lint::builtin::EMPTY_MATCH_ON_UNSAFE_PLACE, + cx.match_lint_level, + cx.whole_match_span.unwrap_or(cx.scrut_span), + EmptyMatchOnUnsafePlace { + scrut_span: cx.scrut_span, + suggestion: EmptyMatchOnUnsafePlaceWrapSuggestion { + scrut_start: cx.scrut_span.shrink_to_lo(), + scrut_end: cx.scrut_span.shrink_to_hi(), + }, + }, + ); + } + + // For backwards compability we allow an empty match in this case. + return UsefulnessReport { + arm_usefulness: Vec::new(), + non_exhaustiveness_witnesses: Vec::new(), + }; + } + } + let scrut_validity = ValidityConstraint::from_bool(cx.known_valid_scrutinee); let mut matrix = Matrix::new(cx, arms, scrut_ty, scrut_validity); let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness(cx, &mut matrix, true); diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr index 98eac28201515..ea8cc6e912245 100644 --- a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr @@ -192,6 +192,23 @@ error: unreachable pattern LL | _ => {} | ^ +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:157:9 + | +LL | match *ref_void {} + | ^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:157:15 + | +LL | match *ref_void {} + | ^^^^^^^^^ + = note: `#[warn(empty_match_on_unsafe_place)]` on by default +help: consider forcing a read of the value + | +LL | match { *ref_void } {} + | + + + error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/empty-types.rs:162:15 | @@ -210,6 +227,38 @@ LL ~ None => {}, LL + Some(_) => todo!() | +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:179:9 + | +LL | match union_void.value {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:179:15 + | +LL | match union_void.value {} + | ^^^^^^^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { union_void.value } {} + | + + + +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:184:9 + | +LL | match *ptr_void {} + | ^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:184:15 + | +LL | match *ptr_void {} + | ^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { *ptr_void } {} + | + + + error: unreachable pattern --> $DIR/empty-types.rs:205:13 | @@ -240,6 +289,118 @@ error: unreachable pattern LL | _ => {} | ^ +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:233:9 + | +LL | match *ptr_never {} + | ^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:233:15 + | +LL | match *ptr_never {} + | ^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { *ptr_never } {} + | + + + +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:238:9 + | +LL | match *ref_never {} + | ^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:238:15 + | +LL | match *ref_never {} + | ^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { *ref_never } {} + | + + + +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:244:9 + | +LL | match ref_x.never {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:244:15 + | +LL | match ref_x.never {} + | ^^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { ref_x.never } {} + | + + + +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:250:9 + | +LL | match nested_ref_x.0.never {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:250:15 + | +LL | match nested_ref_x.0.never {} + | ^^^^^^^^^^^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { nested_ref_x.0.never } {} + | + + + +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:255:9 + | +LL | match (*ptr_never as Void) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:255:15 + | +LL | match (*ptr_never as Void) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { (*ptr_never as Void) } {} + | + + + +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:261:9 + | +LL | match union_never.value {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:261:15 + | +LL | match union_never.value {} + | ^^^^^^^^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { union_never.value } {} + | + + + +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:267:9 + | +LL | match slice_never[0] {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:267:15 + | +LL | match slice_never[0] {} + | ^^^^^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { slice_never[0] } {} + | + + + error: unreachable pattern --> $DIR/empty-types.rs:285:9 | @@ -264,6 +425,38 @@ error: unreachable pattern LL | Err(_) => {} | ^^^^^^ +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:308:5 + | +LL | match *x {} + | ^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:308:11 + | +LL | match *x {} + | ^^ +help: consider forcing a read of the value + | +LL | match { *x } {} + | + + + +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:310:5 + | +LL | match *x {} + | ^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:310:11 + | +LL | match *x {} + | ^^ +help: consider forcing a read of the value + | +LL | match { *x } {} + | + + + error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty --> $DIR/empty-types.rs:313:11 | @@ -490,6 +683,22 @@ LL ~ &None => {}, LL + &Some(_) => todo!() | +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:473:5 + | +LL | match *ref_never {} + | ^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:473:11 + | +LL | match *ref_never {} + | ^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { *ref_never } {} + | + + + error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/empty-types.rs:488:11 | @@ -582,8 +791,28 @@ error: unreachable pattern LL | _x if false => {} | ^^ +warning: empty match on potentially-invalid data + --> $DIR/empty-types.rs:629:5 + | +LL | / match *ref_never { +LL | | +LL | | // useful, !reachable +LL | | _a if false => {} +LL | | } + | |_____^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty-types.rs:629:11 + | +LL | match *ref_never { + | ^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { *ref_never } { + | + + + error[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/empty-types.rs:633:11 + --> $DIR/empty-types.rs:634:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&_` not covered @@ -598,7 +827,7 @@ LL + &_ => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:661:11 + --> $DIR/empty-types.rs:662:11 | LL | match *x { | ^^ pattern `Some(_)` not covered @@ -615,7 +844,7 @@ LL ~ None => {}, LL + Some(_) => todo!() | -error: aborting due to 63 previous errors +error: aborting due to 63 previous errors; 14 warnings emitted Some errors have detailed explanations: E0004, E0005. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index 178e50a7db93f..fb41d2482f860 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -579,7 +579,7 @@ LL | _x if false => {} | ^^ error[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/empty-types.rs:633:11 + --> $DIR/empty-types.rs:634:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&_` not covered @@ -594,7 +594,7 @@ LL + &_ => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:661:11 + --> $DIR/empty-types.rs:662:11 | LL | match *x { | ^^ pattern `Some(_)` not covered diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs index 09a2fb702d43f..2348871e36358 100644 --- a/tests/ui/pattern/usefulness/empty-types.rs +++ b/tests/ui/pattern/usefulness/empty-types.rs @@ -154,7 +154,7 @@ fn void_same_as_never(x: NeverBundle) { } let ref_void: &Void = &x.void; - match *ref_void {} + match *ref_void {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match *ref_void { _ => {} } @@ -176,12 +176,12 @@ fn void_same_as_never(x: NeverBundle) { _a => {} } let union_void = Uninit::::new(); - match union_void.value {} + match union_void.value {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match union_void.value { _ => {} } let ptr_void: *const Void = std::ptr::null(); - match *ptr_void {} + match *ptr_void {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match *ptr_void { _ => {} } @@ -230,41 +230,41 @@ fn invalid_scrutinees(x: NeverBundle) { // These should be considered !known_valid and not warn unreachable. unsafe { // A pointer may point to a place with an invalid value. - match *ptr_never {} + match *ptr_never {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match *ptr_never { _ => {} } // A reference may point to a place with an invalid value. - match *ref_never {} + match *ref_never {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match *ref_never { _ => {} } // This field access is a dereference. let ref_x: &NeverBundle = &x; - match ref_x.never {} + match ref_x.never {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match ref_x.never { _ => {} } // This nested field access is a dereference. let nested_ref_x: &NestedNeverBundle = &nested_x; - match nested_ref_x.0.never {} + match nested_ref_x.0.never {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match nested_ref_x.0.never { _ => {} } // A cast does not load. - match (*ptr_never as Void) {} + match (*ptr_never as Void) {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match (*ptr_never as Void) { _ => {} } // A union field may contain invalid data. let union_never = Uninit::::new(); - match union_never.value {} + match union_never.value {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match union_never.value { _ => {} } // Indexing is like a field access. This one accesses behind a reference. let slice_never: &[!] = &[]; - match slice_never[0] {} + match slice_never[0] {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match slice_never[0] { _ => {} } @@ -305,9 +305,9 @@ fn nested_validity_tracking(bundle: NeverBundle) { fn invalid_empty_match(bundle: NeverBundle) { // We allow these two for backwards-compability. let x: &! = &bundle.never; - match *x {} + match *x {} //[min_exh_pats]~ WARN empty match on potentially-invalid data let x: &Void = &bundle.void; - match *x {} + match *x {} //[min_exh_pats]~ WARN empty match on potentially-invalid data let x: &(u32, !) = &bundle.tuple_half_never; match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive @@ -470,7 +470,7 @@ fn bindings(x: NeverBundle) { } // On a !known_valid place. - match *ref_never {} + match *ref_never {} //[min_exh_pats]~ WARN empty match on potentially-invalid data match *ref_never { // useful, reachable _ => {} @@ -627,6 +627,7 @@ fn guards_and_validity(x: NeverBundle) { } // The above still applies to the implicit `_` pattern used for exhaustiveness. match *ref_never { + //[min_exh_pats]~^ WARN empty match on potentially-invalid data // useful, !reachable _a if false => {} } diff --git a/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.fixed b/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.fixed new file mode 100644 index 0000000000000..34935ceec39e4 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.fixed @@ -0,0 +1,23 @@ +// run-rustfix +#![feature(min_exhaustive_patterns)] +#![deny(empty_match_on_unsafe_place)] +#![allow(unreachable_code)] + +#[derive(Copy, Clone)] +enum Void {} + +macro_rules! deref { + ($e:expr) => { + { *$e } + }; +} + +fn main() { + let ptr: *const Void = std::ptr::null(); + unsafe { + match { *ptr } {} //~ ERROR empty match on potentially-invalid data + + // rustfix unfortunately changes the macro instead of this expression; we'd need better spans. + match deref!(ptr) {} //~ ERROR empty match on potentially-invalid data + } +} diff --git a/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.rs b/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.rs new file mode 100644 index 0000000000000..8407fbf028262 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.rs @@ -0,0 +1,23 @@ +// run-rustfix +#![feature(min_exhaustive_patterns)] +#![deny(empty_match_on_unsafe_place)] +#![allow(unreachable_code)] + +#[derive(Copy, Clone)] +enum Void {} + +macro_rules! deref { + ($e:expr) => { + *$e + }; +} + +fn main() { + let ptr: *const Void = std::ptr::null(); + unsafe { + match *ptr {} //~ ERROR empty match on potentially-invalid data + + // rustfix unfortunately changes the macro instead of this expression; we'd need better spans. + match deref!(ptr) {} //~ ERROR empty match on potentially-invalid data + } +} diff --git a/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.stderr b/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.stderr new file mode 100644 index 0000000000000..c55a51b2d49e7 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty_match_on_unsafe_place.stderr @@ -0,0 +1,43 @@ +error: empty match on potentially-invalid data + --> $DIR/empty_match_on_unsafe_place.rs:18:9 + | +LL | match *ptr {} + | ^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty_match_on_unsafe_place.rs:18:15 + | +LL | match *ptr {} + | ^^^^ +note: the lint level is defined here + --> $DIR/empty_match_on_unsafe_place.rs:3:9 + | +LL | #![deny(empty_match_on_unsafe_place)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider forcing a read of the value + | +LL | match { *ptr } {} + | + + + +error: empty match on potentially-invalid data + --> $DIR/empty_match_on_unsafe_place.rs:21:9 + | +LL | match deref!(ptr) {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: this place can hold invalid data, which would make the match reachable + --> $DIR/empty_match_on_unsafe_place.rs:11:9 + | +LL | *$e + | ^^^ +... +LL | match deref!(ptr) {} + | ----------- in this macro invocation + = note: this error originates in the macro `deref` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider forcing a read of the value + | +LL | { *$e } + | + + + +error: aborting due to 2 previous errors +