Commit 05c31baf authored by Mazdak Farrokhzad's avatar Mazdak Farrokhzad Committed by GitHub

Rollup merge of #59639 - cuviper:ignore-uninhabited, r=eddyb

Never return uninhabited values at all

Functions with uninhabited return values are already marked `noreturn`,
but we were still generating return instructions for this. When running
with `-C passes=lint`, LLVM prints:

    Unusual: Return statement in function with noreturn attribute

The LLVM manual makes a stronger statement about `noreturn` though:

> This produces undefined behavior at runtime if the function ever does
dynamically return.

We now emit an `abort` anywhere that would have tried to return an
uninhabited value.

Fixes #48227
cc #7463 #48229

r? @eddyb
parents 56328a59 c2e0d7f1
......@@ -238,6 +238,13 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if self.fn_ty.ret.layout.abi.is_uninhabited() {
// Functions with uninhabited return values are marked `noreturn`,
// so we should make sure that we never actually do.
let llval = match self.fn_ty.ret.mode {
PassMode::Ignore(IgnoreMode::Zst) | PassMode::Indirect(..) => {
// compile-flags: -g -C no-prepopulate-passes
// ignore-tidy-linelength
#![crate_type = "lib"]
#[derive(Clone, Copy)]
pub enum EmptyEnum {}
pub fn empty(x: &EmptyEnum) -> EmptyEnum {
// CHECK: @empty({{.*}}) unnamed_addr #0
// CHECK-NOT: ret void
// CHECK: call void @llvm.trap()
// CHECK: unreachable
pub struct Foo(String, EmptyEnum);
pub fn foo(x: String, y: &EmptyEnum) -> Foo {
// CHECK: @foo({{.*}}) unnamed_addr #0
// CHECK-NOT: ret %Foo
// CHECK: call void @llvm.trap()
// CHECK: unreachable
Foo(x, *y)
// CHECK: attributes #0 = {{{.*}} noreturn {{.*}}}
// CHECK: DISubprogram(name: "empty", {{.*}} DIFlagNoReturn
// CHECK: DISubprogram(name: "foo", {{.*}} DIFlagNoReturn
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment