mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Check if call return type is visibly uninhabited when building MIR
This commit is contained in:
parent
4b133a7e27
commit
6f8a1ee45e
@ -255,10 +255,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
func: fun,
|
func: fun,
|
||||||
args,
|
args,
|
||||||
cleanup: None,
|
cleanup: None,
|
||||||
// FIXME(varkor): replace this with an uninhabitedness-based check.
|
// The presence or absence of a return edge affects control-flow sensitive
|
||||||
// This requires getting access to the current module to call
|
// MIR checks and ultimately whether code is accepted or not. We can only
|
||||||
// `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
|
// omit the return edge if a return type is visibly uninhabited to a module
|
||||||
destination: if expr.ty.is_never() {
|
// that makes the call.
|
||||||
|
destination: if this.tcx.is_ty_uninhabited_from(
|
||||||
|
this.parent_module,
|
||||||
|
expr.ty,
|
||||||
|
this.param_env,
|
||||||
|
) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some((destination, success))
|
Some((destination, success))
|
||||||
|
@ -350,6 +350,7 @@ struct Builder<'a, 'tcx> {
|
|||||||
|
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
|
parent_module: DefId,
|
||||||
check_overflow: bool,
|
check_overflow: bool,
|
||||||
fn_span: Span,
|
fn_span: Span,
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
@ -807,15 +808,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let lint_level = LintLevel::Explicit(hir_id);
|
let lint_level = LintLevel::Explicit(hir_id);
|
||||||
|
let param_env = tcx.param_env(def.did);
|
||||||
let mut builder = Builder {
|
let mut builder = Builder {
|
||||||
thir,
|
thir,
|
||||||
tcx,
|
tcx,
|
||||||
infcx,
|
infcx,
|
||||||
typeck_results: tcx.typeck_opt_const_arg(def),
|
typeck_results: tcx.typeck_opt_const_arg(def),
|
||||||
region_scope_tree: tcx.region_scope_tree(def.did),
|
region_scope_tree: tcx.region_scope_tree(def.did),
|
||||||
param_env: tcx.param_env(def.did),
|
param_env,
|
||||||
def_id: def.did.to_def_id(),
|
def_id: def.did.to_def_id(),
|
||||||
hir_id,
|
hir_id,
|
||||||
|
parent_module: tcx.parent_module(hir_id).to_def_id(),
|
||||||
check_overflow,
|
check_overflow,
|
||||||
cfg: CFG { basic_blocks: IndexVec::new() },
|
cfg: CFG { basic_blocks: IndexVec::new() },
|
||||||
fn_span: span,
|
fn_span: span,
|
||||||
|
@ -28,7 +28,7 @@ impl IntoError<Error> for Api
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn into_error(self, error: Self::Source) -> Error {
|
fn into_error(self, error: Self::Source) -> Error {
|
||||||
Error::Api {
|
Error::Api {
|
||||||
source: (|v| v)(error),
|
source: error,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,21 +4,22 @@
|
|||||||
fn h() -> () {
|
fn h() -> () {
|
||||||
let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12
|
let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12
|
||||||
let _1: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
let _1: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ let mut _2: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _9: (); // in scope 0 at $DIR/inline-diverging.rs:27:13: 27:16
|
+ let mut _3: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _10: (); // in scope 0 at $DIR/inline-diverging.rs:28:13: 28:16
|
+ let mut _10: (); // in scope 0 at $DIR/inline-diverging.rs:27:13: 27:16
|
||||||
|
+ let mut _11: (); // in scope 0 at $DIR/inline-diverging.rs:28:13: 28:16
|
||||||
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22
|
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ debug f => _2; // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
|
+ debug f => _3; // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
|
||||||
+ let _3: !; // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
|
+ let _4: !; // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
|
||||||
+ let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
|
+ let mut _5: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
|
||||||
+ let mut _6: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
|
+ let mut _7: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
|
||||||
+ let mut _7: !; // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
|
+ let mut _8: !; // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
|
||||||
+ let mut _8: !; // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
|
+ let mut _9: !; // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
|
||||||
+ scope 2 {
|
+ scope 2 {
|
||||||
+ debug a => _3; // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
|
+ debug a => _4; // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
|
||||||
+ let _5: !; // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
|
+ let _6: !; // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
|
||||||
+ scope 3 {
|
+ scope 3 {
|
||||||
+ debug b => _5; // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
|
+ debug b => _6; // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
|
||||||
+ }
|
+ }
|
||||||
+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:28:13: 28:16
|
+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:28:13: 28:16
|
||||||
+ scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
|
+ scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||||
@ -33,27 +34,25 @@
|
|||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_1); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
StorageLive(_1); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
- _1 = call_twice::<!, fn() -> ! {sleep}>(sleep) -> bb1; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
- call_twice::<!, fn() -> ! {sleep}>(sleep); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ _2 = sleep; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ StorageLive(_3); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
|
+ _3 = sleep; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
- // + span: $DIR/inline-diverging.rs:22:5: 22:15
|
- // + span: $DIR/inline-diverging.rs:22:5: 22:15
|
||||||
- // + literal: Const { ty: fn(fn() -> ! {sleep}) -> (!, !) {call_twice::<!, fn() -> ! {sleep}>}, val: Value(Scalar(<ZST>)) }
|
- // + literal: Const { ty: fn(fn() -> ! {sleep}) -> (!, !) {call_twice::<!, fn() -> ! {sleep}>}, val: Value(Scalar(<ZST>)) }
|
||||||
- // mir::Constant
|
- // mir::Constant
|
||||||
// + span: $DIR/inline-diverging.rs:22:16: 22:21
|
// + span: $DIR/inline-diverging.rs:22:16: 22:21
|
||||||
// + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
|
||||||
+ StorageLive(_3); // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
|
+ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
|
||||||
+ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
|
+ StorageLive(_5); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
|
||||||
+ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
|
+ _5 = &_3; // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
|
||||||
+ StorageLive(_9); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
|
+ StorageLive(_10); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
|
||||||
+ _9 = const (); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
|
+ _10 = const (); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
|
||||||
+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
|
+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
|
||||||
}
|
+ }
|
||||||
|
+
|
||||||
bb1: {
|
+ bb1: {
|
||||||
- StorageDead(_1); // scope 0 at $DIR/inline-diverging.rs:22:22: 22:23
|
|
||||||
- _0 = const (); // scope 0 at $DIR/inline-diverging.rs:21:12: 23:2
|
|
||||||
- return; // scope 0 at $DIR/inline-diverging.rs:23:2: 23:2
|
|
||||||
+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
|
+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ fn main() -> () {
|
|||||||
StorageLive(_2); // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
|
StorageLive(_2); // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
|
||||||
StorageLive(_3); // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
|
StorageLive(_3); // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
|
||||||
_3 = (); // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
|
_3 = (); // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
|
||||||
_2 = transmute::<(), Void>(move _3) -> [return: bb1, unwind: bb4]; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
|
transmute::<(), Void>(move _3) -> bb4; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/issue-72181-1.rs:17:9: 17:40
|
// + span: $DIR/issue-72181-1.rs:17:9: 17:40
|
||||||
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {transmute::<(), Void>}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {transmute::<(), Void>}, val: Value(Scalar(<ZST>)) }
|
||||||
|
@ -119,27 +119,17 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
|
|||||||
78 00 00 00 ff ff ff ff │ x.......
|
78 00 00 00 ff ff ff ff │ x.......
|
||||||
}
|
}
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/ub-enum.rs:92:1
|
--> $DIR/ub-enum.rs:92:77
|
||||||
|
|
|
|
||||||
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
|
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
|
||||||
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
|
||||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
|
||||||
00 00 00 00 00 00 00 00 │ ........
|
|
||||||
}
|
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/ub-enum.rs:94:1
|
--> $DIR/ub-enum.rs:94:77
|
||||||
|
|
|
|
||||||
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
|
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
|
||||||
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
|
||||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
|
||||||
00 00 00 00 00 00 00 00 │ ........
|
|
||||||
}
|
|
||||||
|
|
||||||
error: aborting due to 13 previous errors
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
|
@ -119,27 +119,17 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
|
|||||||
78 00 00 00 ff ff ff ff │ x.......
|
78 00 00 00 ff ff ff ff │ x.......
|
||||||
}
|
}
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/ub-enum.rs:92:1
|
--> $DIR/ub-enum.rs:92:77
|
||||||
|
|
|
|
||||||
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
|
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
|
||||||
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
|
||||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
|
||||||
00 00 00 00 00 00 00 00 │ ........
|
|
||||||
}
|
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/ub-enum.rs:94:1
|
--> $DIR/ub-enum.rs:94:77
|
||||||
|
|
|
|
||||||
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
|
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
|
||||||
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
|
||||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
|
||||||
00 00 00 00 00 00 00 00 │ ........
|
|
||||||
}
|
|
||||||
|
|
||||||
error: aborting due to 13 previous errors
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
|
@ -90,9 +90,9 @@ const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute
|
|||||||
// All variants are uninhabited but also have data.
|
// All variants are uninhabited but also have data.
|
||||||
// Use `0` as constant to make behavior endianess-independent.
|
// Use `0` as constant to make behavior endianess-independent.
|
||||||
const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
|
const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
|
||||||
//~^ ERROR is undefined behavior
|
//~^ ERROR evaluation of constant value failed
|
||||||
const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
|
const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
|
||||||
//~^ ERROR is undefined behavior
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,11 @@ LL | unsafe { std::mem::transmute(()) }
|
|||||||
LL | const FOO: [Empty; 3] = [foo(); 3];
|
LL | const FOO: [Empty; 3] = [foo(); 3];
|
||||||
| ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:13:26
|
| ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:13:26
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/validate_uninhabited_zsts.rs:16:1
|
--> $DIR/validate_uninhabited_zsts.rs:16:35
|
||||||
|
|
|
|
||||||
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
|
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
|
| ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
|
||||||
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
|
||||||
= note: the raw bytes of the constant (size: 0, align: 1) {}
|
|
||||||
|
|
||||||
warning: the type `!` does not permit zero-initialization
|
warning: the type `!` does not permit zero-initialization
|
||||||
--> $DIR/validate_uninhabited_zsts.rs:4:14
|
--> $DIR/validate_uninhabited_zsts.rs:4:14
|
||||||
|
@ -10,14 +10,11 @@ LL | unsafe { std::mem::transmute(()) }
|
|||||||
LL | const FOO: [Empty; 3] = [foo(); 3];
|
LL | const FOO: [Empty; 3] = [foo(); 3];
|
||||||
| ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:13:26
|
| ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:13:26
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/validate_uninhabited_zsts.rs:16:1
|
--> $DIR/validate_uninhabited_zsts.rs:16:35
|
||||||
|
|
|
|
||||||
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
|
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
|
| ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
|
||||||
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
|
||||||
= note: the raw bytes of the constant (size: 0, align: 1) {}
|
|
||||||
|
|
||||||
warning: the type `!` does not permit zero-initialization
|
warning: the type `!` does not permit zero-initialization
|
||||||
--> $DIR/validate_uninhabited_zsts.rs:4:14
|
--> $DIR/validate_uninhabited_zsts.rs:4:14
|
||||||
|
@ -14,7 +14,7 @@ const FOO: [Empty; 3] = [foo(); 3];
|
|||||||
|
|
||||||
#[warn(const_err)]
|
#[warn(const_err)]
|
||||||
const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
|
const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ ERROR evaluation of constant value failed
|
||||||
//~| WARN the type `Empty` does not permit zero-initialization
|
//~| WARN the type `Empty` does not permit zero-initialization
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// edition:2021
|
// edition:2021
|
||||||
// run-pass
|
// run-pass
|
||||||
|
// compile-flags: -Zdrop-tracking
|
||||||
|
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ fn never() -> Never {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn includes_never(crash: bool, x: u32) -> u32 {
|
async fn includes_never(crash: bool, x: u32) -> u32 {
|
||||||
let mut result = async { x * x }.await;
|
let result = async { x * x }.await;
|
||||||
if !crash {
|
if !crash {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,11 @@ extern {
|
|||||||
|
|
||||||
static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
|
static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
|
||||||
//~| WARN: previously accepted
|
//~| WARN: previously accepted
|
||||||
//~| ERROR undefined behavior to use this value
|
//~| ERROR could not evaluate static initializer
|
||||||
//~| WARN: type `Void` does not permit zero-initialization
|
//~| WARN: type `Void` does not permit zero-initialization
|
||||||
static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
|
static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
|
||||||
//~| WARN: previously accepted
|
//~| WARN: previously accepted
|
||||||
//~| ERROR undefined behavior to use this value
|
//~| ERROR could not evaluate static initializer
|
||||||
//~| WARN: type `Void` does not permit zero-initialization
|
//~| WARN: type `Void` does not permit zero-initialization
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -43,23 +43,17 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
|
|||||||
= note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
|
= note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
|
||||||
= note: uninhabited statics cannot be initialized, and any access would be an immediate error
|
= note: uninhabited statics cannot be initialized, and any access would be an immediate error
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: could not evaluate static initializer
|
||||||
--> $DIR/uninhabited-static.rs:12:1
|
--> $DIR/uninhabited-static.rs:12:31
|
||||||
|
|
|
|
||||||
LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
|
LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
|
| ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
|
||||||
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
|
||||||
= note: the raw bytes of the constant (size: 0, align: 1) {}
|
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: could not evaluate static initializer
|
||||||
--> $DIR/uninhabited-static.rs:16:1
|
--> $DIR/uninhabited-static.rs:16:32
|
||||||
|
|
|
|
||||||
LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
|
LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
|
| ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
|
||||||
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
|
||||||
= note: the raw bytes of the constant (size: 0, align: 1) {}
|
|
||||||
|
|
||||||
warning: the type `Void` does not permit zero-initialization
|
warning: the type `Void` does not permit zero-initialization
|
||||||
--> $DIR/uninhabited-static.rs:12:31
|
--> $DIR/uninhabited-static.rs:12:31
|
||||||
|
29
src/test/ui/uninhabited/privately-uninhabited-mir-call.rs
Normal file
29
src/test/ui/uninhabited/privately-uninhabited-mir-call.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Verifies that MIR building for a call expression respects
|
||||||
|
// privacy when checking if a call return type is uninhabited.
|
||||||
|
|
||||||
|
pub mod widget {
|
||||||
|
enum Unimplemented {}
|
||||||
|
pub struct Widget(Unimplemented);
|
||||||
|
|
||||||
|
impl Widget {
|
||||||
|
pub fn new() -> Widget {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn f() {
|
||||||
|
let x: &mut u32;
|
||||||
|
Widget::new();
|
||||||
|
// Ok. Widget type returned from new is known to be uninhabited
|
||||||
|
// and the following code is considered unreachable.
|
||||||
|
*x = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let y: &mut u32;
|
||||||
|
widget::Widget::new();
|
||||||
|
// Error. Widget type is not known to be uninhabited here,
|
||||||
|
// so the following code is considered reachable.
|
||||||
|
*y = 2; //~ ERROR use of possibly-uninitialized variable
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
error[E0381]: use of possibly-uninitialized variable: `y`
|
||||||
|
--> $DIR/privately-uninhabited-mir-call.rs:28:5
|
||||||
|
|
|
||||||
|
LL | *y = 2;
|
||||||
|
| ^^^^^^ use of possibly-uninitialized `y`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0381`.
|
@ -1,11 +1,27 @@
|
|||||||
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||||
--> $DIR/issue-45087-unreachable-unsafe.rs:6:5
|
--> $DIR/issue-45087-unreachable-unsafe.rs:7:5
|
||||||
|
|
|
|
||||||
LL | *(1 as *mut u32) = 42;
|
LL | *(1 as *mut u32) = 42;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
|
| ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
|
||||||
|
|
|
|
||||||
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/issue-45087-unreachable-unsafe.rs:17:5
|
||||||
|
|
|
||||||
|
LL | *a = 1;
|
||||||
|
| ^^^^^^ dereference of raw pointer
|
||||||
|
|
|
||||||
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/issue-45087-unreachable-unsafe.rs:29:5
|
||||||
|
|
|
||||||
|
LL | *b = 1;
|
||||||
|
| ^^^^^^ dereference of raw pointer
|
||||||
|
|
|
||||||
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0133`.
|
For more information about this error, try `rustc --explain E0133`.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// Verify that unreachable code undergoes unsafety checks.
|
||||||
// revisions: mir thir
|
// revisions: mir thir
|
||||||
// [thir]compile-flags: -Z thir-unsafeck
|
// [thir]compile-flags: -Z thir-unsafeck
|
||||||
|
|
||||||
@ -6,3 +7,25 @@ fn main() {
|
|||||||
*(1 as *mut u32) = 42;
|
*(1 as *mut u32) = 42;
|
||||||
//~^ ERROR dereference of raw pointer is unsafe
|
//~^ ERROR dereference of raw pointer is unsafe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn panic() -> ! {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f(a: *mut u32) {
|
||||||
|
panic();
|
||||||
|
*a = 1;
|
||||||
|
//~^ ERROR dereference of raw pointer is unsafe
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Void {}
|
||||||
|
|
||||||
|
fn uninhabited() -> Void {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g(b: *mut u32) {
|
||||||
|
uninhabited();
|
||||||
|
*b = 1;
|
||||||
|
//~^ ERROR dereference of raw pointer is unsafe
|
||||||
|
}
|
||||||
|
@ -1,11 +1,27 @@
|
|||||||
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||||
--> $DIR/issue-45087-unreachable-unsafe.rs:6:5
|
--> $DIR/issue-45087-unreachable-unsafe.rs:7:5
|
||||||
|
|
|
|
||||||
LL | *(1 as *mut u32) = 42;
|
LL | *(1 as *mut u32) = 42;
|
||||||
| ^^^^^^^^^^^^^^^^ dereference of raw pointer
|
| ^^^^^^^^^^^^^^^^ dereference of raw pointer
|
||||||
|
|
|
|
||||||
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/issue-45087-unreachable-unsafe.rs:17:5
|
||||||
|
|
|
||||||
|
LL | *a = 1;
|
||||||
|
| ^^ dereference of raw pointer
|
||||||
|
|
|
||||||
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/issue-45087-unreachable-unsafe.rs:29:5
|
||||||
|
|
|
||||||
|
LL | *b = 1;
|
||||||
|
| ^^ dereference of raw pointer
|
||||||
|
|
|
||||||
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0133`.
|
For more information about this error, try `rustc --explain E0133`.
|
||||||
|
Loading…
Reference in New Issue
Block a user