diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2023-02-21 14:19:58 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-02-21 14:19:58 +0530 |
| commit | 4dea3a295f99f166472ddec78ed9d590900436ff (patch) | |
| tree | 34b05afe9d34eaa2e63798f6a1bd4d3491b2cffc | |
| parent | f715e430aac0de131e2ad21804013ea405722a66 (diff) | |
| parent | 0610df931449375a80bdd7ae03c2fd3116291c82 (diff) | |
| download | rust-4dea3a295f99f166472ddec78ed9d590900436ff.tar.gz rust-4dea3a295f99f166472ddec78ed9d590900436ff.zip | |
Rollup merge of #108000 - y21:no-zero-init-for-uninhabited, r=jackh726
lint: don't suggest MaybeUninit::assume_init for uninhabited types Creating a zeroed uninhabited type such as `!` or an empty enum with `mem::zeroed()` (or transmuting `()` to `!`) currently triggers this lint: ```rs warning: the type `!` does not permit zero-initialization --> test.rs:5:23 | 5 | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done | = note: the `!` type has no valid value ``` The `MaybeUninit` suggestion in the help message seems confusing/useless for uninhabited types, as such a type cannot be fully initialized in the first place (as the note implies). This PR limits this help message to inhabited types which can be initialized
| -rw-r--r-- | compiler/rustc_lint/src/builtin.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/lints.rs | 13 | ||||
| -rw-r--r-- | tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr | 10 | ||||
| -rw-r--r-- | tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr | 10 | ||||
| -rw-r--r-- | tests/ui/lint/invalid_value.stderr | 40 | ||||
| -rw-r--r-- | tests/ui/statics/uninhabited-static.stderr | 10 |
6 files changed, 32 insertions, 59 deletions
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 11fb1f80a11..726042479e9 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2635,7 +2635,13 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { cx.emit_spanned_lint( INVALID_VALUE, expr.span, - BuiltinUnpermittedTypeInit { msg, ty: conjured_ty, label: expr.span, sub }, + BuiltinUnpermittedTypeInit { + msg, + ty: conjured_ty, + label: expr.span, + sub, + tcx: cx.tcx, + }, ); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 94a43ab0c46..aa6e230dc6d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -8,7 +8,9 @@ use rustc_errors::{ }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::{PolyExistentialTraitRef, Predicate, Ty, TyCtxt}; +use rustc_middle::ty::{ + inhabitedness::InhabitedPredicate, PolyExistentialTraitRef, Predicate, Ty, TyCtxt, +}; use rustc_session::parse::ParseSess; use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; @@ -419,6 +421,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> { pub ty: Ty<'a>, pub label: Span, pub sub: BuiltinUnpermittedTypeInitSub, + pub tcx: TyCtxt<'a>, } impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { @@ -428,7 +431,13 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { diag.set_arg("ty", self.ty); diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); - diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label_suggestion); + if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { + // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. + diag.span_label( + self.label, + fluent::lint_builtin_unpermitted_type_init_label_suggestion, + ); + } self.sub.add_to_diagnostic(diag); diag } diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr index 9710bf476ec..69fb1a59d4f 100644 --- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr +++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr @@ -2,10 +2,7 @@ warning: the type `!` does not permit zero-initialization --> $DIR/validate_uninhabited_zsts.rs:4:14 | LL | unsafe { std::mem::transmute(()) } - | ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: the `!` type has no valid value = note: `#[warn(invalid_value)]` on by default @@ -40,10 +37,7 @@ warning: the type `empty::Empty` does not permit zero-initialization --> $DIR/validate_uninhabited_zsts.rs:21:42 | LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: in this struct field --> $DIR/validate_uninhabited_zsts.rs:16:22 diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr index 9710bf476ec..69fb1a59d4f 100644 --- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr +++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr @@ -2,10 +2,7 @@ warning: the type `!` does not permit zero-initialization --> $DIR/validate_uninhabited_zsts.rs:4:14 | LL | unsafe { std::mem::transmute(()) } - | ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: the `!` type has no valid value = note: `#[warn(invalid_value)]` on by default @@ -40,10 +37,7 @@ warning: the type `empty::Empty` does not permit zero-initialization --> $DIR/validate_uninhabited_zsts.rs:21:42 | LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: in this struct field --> $DIR/validate_uninhabited_zsts.rs:16:22 diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr index 48fd4169da7..57531b0968f 100644 --- a/tests/ui/lint/invalid_value.stderr +++ b/tests/ui/lint/invalid_value.stderr @@ -61,10 +61,7 @@ error: the type `!` does not permit zero-initialization --> $DIR/invalid_value.rs:65:23 | LL | let _val: ! = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: the `!` type has no valid value @@ -72,10 +69,7 @@ error: the type `!` does not permit being left uninitialized --> $DIR/invalid_value.rs:66:23 | LL | let _val: ! = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: the `!` type has no valid value @@ -83,10 +77,7 @@ error: the type `(i32, !)` does not permit zero-initialization --> $DIR/invalid_value.rs:68:30 | LL | let _val: (i32, !) = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: the `!` type has no valid value @@ -94,10 +85,7 @@ error: the type `(i32, !)` does not permit being left uninitialized --> $DIR/invalid_value.rs:69:30 | LL | let _val: (i32, !) = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | = note: integers must be initialized @@ -105,10 +93,7 @@ error: the type `Void` does not permit zero-initialization --> $DIR/invalid_value.rs:71:26 | LL | let _val: Void = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: enums with no inhabited variants have no valid value --> $DIR/invalid_value.rs:12:1 @@ -120,10 +105,7 @@ error: the type `Void` does not permit being left uninitialized --> $DIR/invalid_value.rs:72:26 | LL | let _val: Void = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: enums with no inhabited variants have no valid value --> $DIR/invalid_value.rs:12:1 @@ -405,10 +387,7 @@ error: the type `TwoUninhabited` does not permit zero-initialization --> $DIR/invalid_value.rs:104:36 | LL | let _val: TwoUninhabited = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: enums with no inhabited variants have no valid value --> $DIR/invalid_value.rs:42:1 @@ -420,10 +399,7 @@ error: the type `TwoUninhabited` does not permit being left uninitialized --> $DIR/invalid_value.rs:105:36 | LL | let _val: TwoUninhabited = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: enums with no inhabited variants have no valid value --> $DIR/invalid_value.rs:42:1 diff --git a/tests/ui/statics/uninhabited-static.stderr b/tests/ui/statics/uninhabited-static.stderr index ef794bb36ac..437053a4476 100644 --- a/tests/ui/statics/uninhabited-static.stderr +++ b/tests/ui/statics/uninhabited-static.stderr @@ -53,10 +53,7 @@ warning: the type `Void` does not permit zero-initialization --> $DIR/uninhabited-static.rs:12:31 | LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: enums with no inhabited variants have no valid value --> $DIR/uninhabited-static.rs:4:1 @@ -75,10 +72,7 @@ warning: the type `Void` does not permit zero-initialization --> $DIR/uninhabited-static.rs:16:32 | LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: enums with no inhabited variants have no valid value --> $DIR/uninhabited-static.rs:4:1 |
