rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.88k stars 12.67k forks source link

Drop the dereferenceable attribute when a non-null niche is passed as a pointer #131834

Open DianQK opened 4 days ago

DianQK commented 4 days ago

Considering the following code, it should print 0 with a release build, but I get a segmentation violation.

#![feature(rustc_attrs)]
#![allow(internal_features)]
#![allow(dead_code)]

#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_layout_scalar_valid_range_end(0xfffffffffffffff0)]
pub struct RestrictedAddress(&'static i8);

enum E {
    A(RestrictedAddress),
    B,
    C,
}

#[no_mangle]
#[inline(never)]
fn foo(a: E) -> i8 {
    match a {
        E::A(v) => *v.0,
        _ => 0,
    }
}

fn main() {
    println!("{}", foo(std::hint::black_box(E::B)));
}

This is because we are adding the dereferenceable attribute, which allows LLVM to hoist the load instruction. In this case, we need to drop the dereferenceable attribute.

@rustbot label +requires-nightly +I-miscompile +A-codegen

DianQK commented 4 days ago

@rustbot label -needs-triage

RalfJung commented 4 days ago

It's less about the niche and more about the enum. The logic that computes the attribute has to just stop at the enum.

An argument of type RestrictedAddress should still get the attribute.

clubby789 commented 4 days ago

While looking into this I noticed that

#![feature(rustc_attrs)]
#![allow(internal_features)]
#![allow(dead_code)]

#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_layout_scalar_valid_range_end(0xfffffffffffffff0)]
pub struct RestrictedAddress(&'static i8);

enum E {
    A(RestrictedAddress),
    B,
    C,
}

fn main() {
    std::hint::black_box(E::B);
}

causes a debug-only ICE (only allows integer types in const_uint_big) when codegenning the discriminant set.

the8472 commented 4 days ago

causes a debug-only ICE (only allows integer types in const_uint_big) when codegenning the discriminant set.

131698 should fix that