Skip to content

Conversation

Kivooeo
Copy link
Member

@Kivooeo Kivooeo commented May 23, 2025

fixes #141264

r? @Veykril

Unresolved questions:

  • Any edge cases?
  • How this works with rust-analyzer (because all I've did is prevent compiler from emitting error in &raw context) (Allow &raw [mut | const] for union field  rust-analyzer#19867)
  • Should we allow addr_of! and addr_of_mut! as well? In current version they both (&raw and addr_of!) are allowed (They are the same)
  • Is chain of union fields is a safe? (Yes)

@rustbot
Copy link
Collaborator

rustbot commented May 23, 2025

Failed to set assignee to Veykril: invalid assignee

Note: Only org members with at least the repository "read" role, users with write permissions, or people who have commented on the PR may be assigned.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 23, 2025
@jieyouxu
Copy link
Member

cc @RalfJung

@fmease fmease added the I-lang-nominated Nominated for discussion during a lang team meeting. label May 23, 2025
@Kivooeo Kivooeo changed the title Allow &raw [mut | const] for union field in safe Allow &raw [mut | const] for union field in safe May 23, 2025
@fmease fmease added the needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. label May 23, 2025
@RalfJung
Copy link
Member

Uh, the unsafety checker is not actually code I know very well, sorry.
r? compiler

@rustbot rustbot assigned davidtwco and unassigned RalfJung May 23, 2025
@RalfJung
Copy link
Member

Should we allow addr_of! and addr_of_mut! as well? In current version they both (&raw and addr_of!) are allowed

The macros just expand to &raw, it's not even possible to treat them differently.

@rust-log-analyzer

This comment has been minimized.

@Kivooeo
Copy link
Member Author

Kivooeo commented May 23, 2025

I will debug this later today but this is very weird

@fmease fmease added T-lang Relevant to the language team S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed I-lang-nominated Nominated for discussion during a lang team meeting. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 24, 2025
@Kivooeo Kivooeo force-pushed the remove-usnsafegate branch from b006128 to 43892d3 Compare May 24, 2025 11:46
@rust-log-analyzer

This comment has been minimized.

@Kivooeo Kivooeo force-pushed the remove-usnsafegate branch from b60d3ff to fc03435 Compare May 24, 2025 12:03
@rust-log-analyzer

This comment has been minimized.

@Kivooeo Kivooeo force-pushed the remove-usnsafegate branch from 9ccf35d to cde9fa0 Compare May 24, 2025 12:48
@Kivooeo
Copy link
Member Author

Kivooeo commented May 24, 2025

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 24, 2025
@apiraino
Copy link
Contributor

Seems this is now up for grab to anyone having interest to push it to the finish line. Start an FCP, then find a reviewer, IIUC.

cc @fmease that added the FCP label (comment), can you elaborate on this? thanks

@fmease
Copy link
Member

fmease commented Aug 28, 2025

Well, it's an insta-stable change in semantics and as such it warrants an FCP, as simple as that ;)

Likely a T-lang or T-lang+T-opsem FCP and for that it needs a lang nomination first.

@fmease fmease added I-lang-nominated Nominated for discussion during a lang team meeting. T-opsem Relevant to the opsem team S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) labels Aug 28, 2025
@traviscross traviscross removed the T-opsem Relevant to the opsem team label Aug 30, 2025
@traviscross
Copy link
Contributor

Seems right to me. The Reference is already correct on this matter.

@rfcbot fcp merge

cc @rust-lang/opsem

@rust-rfcbot
Copy link
Collaborator

rust-rfcbot commented Aug 30, 2025

Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Aug 30, 2025
@traviscross traviscross added T-opsem Relevant to the opsem team P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang labels Aug 30, 2025
@scottmcm
Copy link
Member

Makes sense to me. Getting the pointer is fine, and inside the allocation of the union the fields have to be GEPi too so no need to worry about that the way pointer projection does.

@rust-rfcbot reviewed

Copy link
Member

@compiler-errors compiler-errors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR causes UB:

union A {
    a: usize,
    b: &'static &'static B,
}

union B {
    c: usize,
}

fn main() {
    let a = A { a: 0 };
    let p = &raw const (**a.b).c;
    println!("{p:?}");
}

Specifically, using global state for the nested union access is not the right choice, because it means that we suppress union accesses in arbitrary nested accesses. I don't think we should (or need to) be using a field on UnsafetyVisitor to properly implement this behavior.

View changes since this review

@Kivooeo
Copy link
Member Author

Kivooeo commented Aug 31, 2025

Good catch, thanks! I was tried to reproduce a way to exploit this global state and am currently thinking about how to do it better. If anyone has ideas, I would appreciate it

Comment on lines 106 to 132
// Test for union fields chain, this should be allowed
#[derive(Copy, Clone)]
union Inner {
a: u8,
}

union MoreInner {
moreinner: ManuallyDrop<Inner>,
}

union LessOuter {
lessouter: ManuallyDrop<MoreInner>,
}

union Outer {
outer: ManuallyDrop<LessOuter>,
}

let super_outer = Outer {
outer: ManuallyDrop::new(LessOuter {
lessouter: ManuallyDrop::new(MoreInner {
moreinner: ManuallyDrop::new(Inner { a: 42 }),
}),
}),
};

let ptr = &raw const super_outer.outer.lessouter.moreinner.a;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this should compile. These implicitly desugar to derefs:

let ptr = &raw const (*(*(*super_outer.outer).lessouter).moreinner).a;

Copy link
Member

@RalfJung RalfJung Aug 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, projecting into a ManuallyDrop should still be unsafe.

Copy link
Member

@compiler-errors compiler-errors Aug 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And allowing arbitrary derefs here is also UB, of course:

use std::ops::Deref;

union A {
    a: usize,
    b: B,
}

#[derive(Copy, Clone)]
struct B(&'static str);

impl Deref for B {
    type Target = C;

    fn deref(&self) -> &C {
        println!("{:?}", self.0);
        &C { c: 0 }
    }
}

union C {
    c: usize,
}

fn main() {
    let a = A { a: 0 };
    let p = &raw const (*a.b).c;
    println!("{p:?}");
}

// Or not implicit:
fn main2() {
    let a = A { a: 0 };
    let p = &raw const a.b.c;
    println!("{p:?}");
}

@compiler-errors
Copy link
Member

I believe the actual implementation of this feature can be significantly simplified:

https://github.com/compiler-errors/rust/pull/new/proper-union-field-unsafety

@Kivooeo
Copy link
Member Author

Kivooeo commented Aug 31, 2025

Yes, your approach looks more simple and fixes things above because of no leaking global state in chains. Would you mind pushing the changes directly to this PR?

@compiler-errors
Copy link
Member

I could push directly but I also would like for you to add additional tests exercising the corner cases I pointed out, so I think you can just push the changes when you get around to adding those tests.

@rust-cloud-vms rust-cloud-vms bot force-pushed the remove-usnsafegate branch from 3db681f to 4024f37 Compare August 31, 2025 17:04
@rustbot
Copy link
Collaborator

rustbot commented Aug 31, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@Kivooeo
Copy link
Member Author

Kivooeo commented Aug 31, 2025

Not sure if I shoulded to split this test into separate files

@rust-cloud-vms rust-cloud-vms bot force-pushed the remove-usnsafegate branch from 4024f37 to 23f1767 Compare August 31, 2025 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. I-lang-nominated Nominated for discussion during a lang team meeting. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). T-lang Relevant to the language team T-opsem Relevant to the opsem team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

&raw const some_union.field erroneously requires unsafe