Skip to content

Commit 4dea3a2

Browse files
authored
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
2 parents f715e43 + 0610df9 commit 4dea3a2

File tree

6 files changed

+32
-59
lines changed

6 files changed

+32
-59
lines changed

compiler/rustc_lint/src/builtin.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -2635,7 +2635,13 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
26352635
cx.emit_spanned_lint(
26362636
INVALID_VALUE,
26372637
expr.span,
2638-
BuiltinUnpermittedTypeInit { msg, ty: conjured_ty, label: expr.span, sub },
2638+
BuiltinUnpermittedTypeInit {
2639+
msg,
2640+
ty: conjured_ty,
2641+
label: expr.span,
2642+
sub,
2643+
tcx: cx.tcx,
2644+
},
26392645
);
26402646
}
26412647
}

compiler/rustc_lint/src/lints.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use rustc_errors::{
88
};
99
use rustc_hir::def_id::DefId;
1010
use rustc_macros::{LintDiagnostic, Subdiagnostic};
11-
use rustc_middle::ty::{PolyExistentialTraitRef, Predicate, Ty, TyCtxt};
11+
use rustc_middle::ty::{
12+
inhabitedness::InhabitedPredicate, PolyExistentialTraitRef, Predicate, Ty, TyCtxt,
13+
};
1214
use rustc_session::parse::ParseSess;
1315
use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
1416

@@ -419,6 +421,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> {
419421
pub ty: Ty<'a>,
420422
pub label: Span,
421423
pub sub: BuiltinUnpermittedTypeInitSub,
424+
pub tcx: TyCtxt<'a>,
422425
}
423426

424427
impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
@@ -428,7 +431,13 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
428431
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
429432
diag.set_arg("ty", self.ty);
430433
diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label);
431-
diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label_suggestion);
434+
if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) {
435+
// Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited.
436+
diag.span_label(
437+
self.label,
438+
fluent::lint_builtin_unpermitted_type_init_label_suggestion,
439+
);
440+
}
432441
self.sub.add_to_diagnostic(diag);
433442
diag
434443
}

tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ warning: the type `!` does not permit zero-initialization
22
--> $DIR/validate_uninhabited_zsts.rs:4:14
33
|
44
LL | unsafe { std::mem::transmute(()) }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^
6-
| |
7-
| this code causes undefined behavior when executed
8-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
5+
| ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
96
|
107
= note: the `!` type has no valid value
118
= note: `#[warn(invalid_value)]` on by default
@@ -40,10 +37,7 @@ warning: the type `empty::Empty` does not permit zero-initialization
4037
--> $DIR/validate_uninhabited_zsts.rs:21:42
4138
|
4239
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
43-
| ^^^^^^^^^^^^^^^^^^^^^^^
44-
| |
45-
| this code causes undefined behavior when executed
46-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
40+
| ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
4741
|
4842
note: in this struct field
4943
--> $DIR/validate_uninhabited_zsts.rs:16:22

tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ warning: the type `!` does not permit zero-initialization
22
--> $DIR/validate_uninhabited_zsts.rs:4:14
33
|
44
LL | unsafe { std::mem::transmute(()) }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^
6-
| |
7-
| this code causes undefined behavior when executed
8-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
5+
| ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
96
|
107
= note: the `!` type has no valid value
118
= note: `#[warn(invalid_value)]` on by default
@@ -40,10 +37,7 @@ warning: the type `empty::Empty` does not permit zero-initialization
4037
--> $DIR/validate_uninhabited_zsts.rs:21:42
4138
|
4239
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
43-
| ^^^^^^^^^^^^^^^^^^^^^^^
44-
| |
45-
| this code causes undefined behavior when executed
46-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
40+
| ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
4741
|
4842
note: in this struct field
4943
--> $DIR/validate_uninhabited_zsts.rs:16:22

tests/ui/lint/invalid_value.stderr

+8-32
Original file line numberDiff line numberDiff line change
@@ -61,54 +61,39 @@ error: the type `!` does not permit zero-initialization
6161
--> $DIR/invalid_value.rs:65:23
6262
|
6363
LL | let _val: ! = mem::zeroed();
64-
| ^^^^^^^^^^^^^
65-
| |
66-
| this code causes undefined behavior when executed
67-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
64+
| ^^^^^^^^^^^^^ this code causes undefined behavior when executed
6865
|
6966
= note: the `!` type has no valid value
7067

7168
error: the type `!` does not permit being left uninitialized
7269
--> $DIR/invalid_value.rs:66:23
7370
|
7471
LL | let _val: ! = mem::uninitialized();
75-
| ^^^^^^^^^^^^^^^^^^^^
76-
| |
77-
| this code causes undefined behavior when executed
78-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
72+
| ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
7973
|
8074
= note: the `!` type has no valid value
8175

8276
error: the type `(i32, !)` does not permit zero-initialization
8377
--> $DIR/invalid_value.rs:68:30
8478
|
8579
LL | let _val: (i32, !) = mem::zeroed();
86-
| ^^^^^^^^^^^^^
87-
| |
88-
| this code causes undefined behavior when executed
89-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
80+
| ^^^^^^^^^^^^^ this code causes undefined behavior when executed
9081
|
9182
= note: the `!` type has no valid value
9283

9384
error: the type `(i32, !)` does not permit being left uninitialized
9485
--> $DIR/invalid_value.rs:69:30
9586
|
9687
LL | let _val: (i32, !) = mem::uninitialized();
97-
| ^^^^^^^^^^^^^^^^^^^^
98-
| |
99-
| this code causes undefined behavior when executed
100-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
88+
| ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
10189
|
10290
= note: integers must be initialized
10391

10492
error: the type `Void` does not permit zero-initialization
10593
--> $DIR/invalid_value.rs:71:26
10694
|
10795
LL | let _val: Void = mem::zeroed();
108-
| ^^^^^^^^^^^^^
109-
| |
110-
| this code causes undefined behavior when executed
111-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
96+
| ^^^^^^^^^^^^^ this code causes undefined behavior when executed
11297
|
11398
note: enums with no inhabited variants have no valid value
11499
--> $DIR/invalid_value.rs:12:1
@@ -120,10 +105,7 @@ error: the type `Void` does not permit being left uninitialized
120105
--> $DIR/invalid_value.rs:72:26
121106
|
122107
LL | let _val: Void = mem::uninitialized();
123-
| ^^^^^^^^^^^^^^^^^^^^
124-
| |
125-
| this code causes undefined behavior when executed
126-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
108+
| ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
127109
|
128110
note: enums with no inhabited variants have no valid value
129111
--> $DIR/invalid_value.rs:12:1
@@ -405,10 +387,7 @@ error: the type `TwoUninhabited` does not permit zero-initialization
405387
--> $DIR/invalid_value.rs:104:36
406388
|
407389
LL | let _val: TwoUninhabited = mem::zeroed();
408-
| ^^^^^^^^^^^^^
409-
| |
410-
| this code causes undefined behavior when executed
411-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
390+
| ^^^^^^^^^^^^^ this code causes undefined behavior when executed
412391
|
413392
note: enums with no inhabited variants have no valid value
414393
--> $DIR/invalid_value.rs:42:1
@@ -420,10 +399,7 @@ error: the type `TwoUninhabited` does not permit being left uninitialized
420399
--> $DIR/invalid_value.rs:105:36
421400
|
422401
LL | let _val: TwoUninhabited = mem::uninitialized();
423-
| ^^^^^^^^^^^^^^^^^^^^
424-
| |
425-
| this code causes undefined behavior when executed
426-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
402+
| ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
427403
|
428404
note: enums with no inhabited variants have no valid value
429405
--> $DIR/invalid_value.rs:42:1

tests/ui/statics/uninhabited-static.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,7 @@ warning: the type `Void` does not permit zero-initialization
5353
--> $DIR/uninhabited-static.rs:12:31
5454
|
5555
LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
56-
| ^^^^^^^^^^^^^^^^^^^^^^^
57-
| |
58-
| this code causes undefined behavior when executed
59-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
56+
| ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
6057
|
6158
note: enums with no inhabited variants have no valid value
6259
--> $DIR/uninhabited-static.rs:4:1
@@ -75,10 +72,7 @@ warning: the type `Void` does not permit zero-initialization
7572
--> $DIR/uninhabited-static.rs:16:32
7673
|
7774
LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
78-
| ^^^^^^^^^^^^^^^^^^^^^^^
79-
| |
80-
| this code causes undefined behavior when executed
81-
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
75+
| ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
8276
|
8377
note: enums with no inhabited variants have no valid value
8478
--> $DIR/uninhabited-static.rs:4:1

0 commit comments

Comments
 (0)