Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop the dereferenceable attribute when a reference is passed in an enum #131834

Closed
DianQK opened this issue Oct 17, 2024 · 7 comments · Fixed by #132745
Closed

Drop the dereferenceable attribute when a reference is passed in an enum #131834

DianQK opened this issue Oct 17, 2024 · 7 comments · Fixed by #132745
Labels
A-codegen Area: Code generation C-bug Category: This is a bug. I-miscompile Issue: Correct Rust code lowers to incorrect machine code requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@DianQK
Copy link
Member

DianQK commented Oct 17, 2024

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

@rustbot rustbot added needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. A-codegen Area: Code generation I-miscompile Issue: Correct Rust code lowers to incorrect machine code requires-nightly This issue requires a nightly compiler in some way. labels Oct 17, 2024
@DianQK
Copy link
Member Author

DianQK commented Oct 17, 2024

@rustbot label -needs-triage

@rustbot rustbot removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Oct 17, 2024
@fmease fmease added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Oct 17, 2024
@RalfJung
Copy link
Member

RalfJung commented Oct 17, 2024

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
Copy link
Contributor

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
Copy link
Member

the8472 commented Oct 17, 2024

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

#131698 should fix that

@RalfJung RalfJung changed the title Drop the dereferenceable attribute when a non-null niche is passed as a pointer Drop the dereferenceable attribute when a reference is passed in an enum Nov 5, 2024
@RalfJung
Copy link
Member

RalfJung commented Nov 7, 2024

I have a fix for this up at #132745

@RalfJung
Copy link
Member

RalfJung commented Nov 8, 2024

Turns out there is already another PR related to this issue, which strangely was not mentioned here: #131739. However, it doesn't fix this issue -- see the comment I posted there.

@RalfJung
Copy link
Member

RalfJung commented Nov 8, 2024

This is a very good catch btw, a really subtle bug to spot!

@bors bors closed this as completed in 6e05afd Nov 9, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Nov 9, 2024
Rollup merge of rust-lang#132745 - RalfJung:pointee-info-inside-enum, r=DianQK

pointee_info_at: fix logic for recursing into enums

Fixes rust-lang#131834

The logic in `pointee_info_at` was likely written at a time when the null pointer optimization was the *only* enum layout optimization -- and as `Variant::Multiple` kept getting expanded, nobody noticed that the logic is now unsound.

The job of this function is to figure out whether there is a dereferenceable-or-null and aligned pointer at a given offset inside a type. So when we recurse into a multi-variant enum, we better make sure that all the other enum variants must be null! This is the part that was forgotten, and this PR adds it.

The reason this didn't explode in many ways so far is that our references only have 1 niche value (null), so it's not possible on stable to have a multi-variant enum with a dereferenceable pointer and other enum variants that are not null. But with `rustc_layout_scalar_valid_range` attributes one can force such a layout, and if `@the8472's` work on alignment niches ever lands, that will make this possible on stable.
mati865 pushed a commit to mati865/rust that referenced this issue Nov 12, 2024
… r=DianQK

pointee_info_at: fix logic for recursing into enums

Fixes rust-lang#131834

The logic in `pointee_info_at` was likely written at a time when the null pointer optimization was the *only* enum layout optimization -- and as `Variant::Multiple` kept getting expanded, nobody noticed that the logic is now unsound.

The job of this function is to figure out whether there is a dereferenceable-or-null and aligned pointer at a given offset inside a type. So when we recurse into a multi-variant enum, we better make sure that all the other enum variants must be null! This is the part that was forgotten, and this PR adds it.

The reason this didn't explode in many ways so far is that our references only have 1 niche value (null), so it's not possible on stable to have a multi-variant enum with a dereferenceable pointer and other enum variants that are not null. But with `rustc_layout_scalar_valid_range` attributes one can force such a layout, and if `@the8472's` work on alignment niches ever lands, that will make this possible on stable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation C-bug Category: This is a bug. I-miscompile Issue: Correct Rust code lowers to incorrect machine code requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants