Skip to content

Make phantom variance markers unit structs - #164820

Open
Amanieu wants to merge 4 commits into
rust-lang:mainfrom
Amanieu:phantom-variance-attribute
Open

Amanieu wants to merge 4 commits into
rust-lang:mainfrom
Amanieu:phantom-variance-attribute

Conversation

@Amanieu

@Amanieu Amanieu commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Tracking issue: #135806

This PR changes the Phantom{Covariant,Contravariant,Invariant}(Lifetime) marker types so that they mirror the PhantomData type: they can now be constructed as unit structs, no longer need the awkward variance() constructor, and are treated the same way as PhantomData.

The compiler side adds 2 internal attributes:

  • #[rustc_force_variance(covariant|contravariant|invariant|bivariant)] on a generic parameter sets the variance of that parameter and overrides the one inferred from fields. This also removes the requirement that this parameter is used within a struct, allowing for generics on a unit struct. This is used for UnsafeCell, CovariantUnsafeCell and PhantomData, removing the current list of special cases in the variance solver.
  • #[rustc_phantom_marker] on a unit struct indicates that this type should be ignored by some lints and structural checks, listed below.

These checks were previously explicitly ignoring PhantomData fields, and have now been extended to ignore all #[rustc_phantom_marker] fields:

  • DispatchFromDyn
  • CoerceUnsized
  • Reborrow
  • FFI safety
  • Unused field lint (dead_code)
  • used_underscore_binding in clippy

These checks continue to be specific to PhantomData because it implies ownership of a T:

  • Special casing in the old and new trait solvers which considers T for auto-traits.
  • Special casing in dropck which includes T in the drop-check constraints.

Finally, the trait impls have been changed to be consistent with PhantomData: these types now have a const Default impl and a StructualPartialEq impl.

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Oct 23, 2026
@rust-log-analyzer

This comment has been minimized.

@Amanieu
Amanieu force-pushed the phantom-variance-attribute branch from 08d707c to 9959a0a Compare October 23, 2026 19:39
@Amanieu

Amanieu commented Oct 24, 2026

Copy link
Copy Markdown
Member Author

r? mejrs

@Amanieu Amanieu added the llm-assisted An LLM-assisted PR as defined by the LLM policy. Requires ahead-of-time consent by assignee. label Oct 24, 2026
@Amanieu
Amanieu marked this pull request as ready for review October 24, 2026 09:34
@rustbot

rustbot commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_passes/src/check_attr.rs

cc @jdonszelmann, @JonathanBrouwer

rustc_codegen_gcc is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_gcc instead.

cc @antoyo, @GuillaumeGomez

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

clippy is developed in its own repository. If possible, consider making this change to rust-lang/rust-clippy instead.

cc @rust-lang/clippy

rustc_codegen_cranelift is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_cranelift instead.

cc @bjorn3

Some changes occurred in compiler/rustc_attr_ir

cc @jdonszelmann, @JonathanBrouwer

@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 Oct 24, 2026

@mejrs mejrs left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

rustc_force_variance is unsound, with it you can write code such as:

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

struct CovariantMutRef<'a, #[rustc_force_variance(covariant)] T> {
    data: &'a mut T,
}

fn main() {
    let mut x: &'static str = "ferris";
    let long: CovariantMutRef<'_, &'static str> = CovariantMutRef { data: &mut x };
    {
        let y = String::from("corro");
        let short: CovariantMutRef<'_, &str> = long;
        *short.data = &y;
    }
    println!("{}", x);
}

produces:

error: Undefined Behavior: constructing invalid value of type &str: encountered a dangling reference (use-after-free)
  --> RUSTLIB/core/src/fmt/mod.rs:LL:CC
   |
LL |             fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }
   |                                                                       ^^^^^^^ Undefined Behavior occurred here
...
LL | fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }
   | ----------------------------------------------------------------------------------- in this macro invocation
   |
   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior

While it's not a Big Deal since it's an internal attribute, I think it ought to be addressed:

  • someone might at some point end up using it in a std data structure and accidentally expose such an unsoundness
  • I'm not entirely sure what CovariantUnsafeCell needs to do to be sound. I think it is currently sound because of the absence of a &mut T -> &mut CovariantUnsafeCell<T> method? It would be nice to capture this in a safety comment somewhere.

I suspect the easiest fix is to just make the attribute unsafe.

Can you also add a feature gate test for both attributes?

View changes since this review

if let ItemKind::Struct(_, _, data) = &item.kind
&& !matches!(data, VariantData::Unit(_))
{
cx.emit_err(crate::diagnostics::InvalidPhantomMarkerTarget { attr_span });

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you add a test for this?

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 25, 2026
@Amanieu

Amanieu commented Oct 26, 2026

Copy link
Copy Markdown
Member Author

I'll make the attribute unsafe and add the test.

These attributes shouldn't get a feature gate: they are internal and never going to be stabilized. There is no point in giving them a separate tracking issue.

Improving the docs of CovariantUnsafeCell is outside the scope of this PR. But the basic idea is that for a MyCell<T>:

  • It must be covariant if exposes a read-like API: fn read(&self) -> T<'a> can allow 'a to be shortened but not lengthened.
  • It must be contravariant if it exposes a write-like API: fn write(&self, val: T<'a>) can allow 'a to be lengthened but not shortened.
  • Having both APIs required invariance.

@mejrs

mejrs commented Oct 26, 2026

Copy link
Copy Markdown
Member

These attributes shouldn't get a feature gate: they are internal and never going to be stabilized. There is no point in giving them a separate tracking issue.

No, I mean a test checking that they can't be used without #![feature(rustc_attrs)]

@rust-bors

This comment has been minimized.

@Amanieu
Amanieu force-pushed the phantom-variance-attribute branch from 9959a0a to 684476f Compare October 28, 2026 09:35
@rustbot

rustbot commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main 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.

@rust-bors

rust-bors Bot commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #165056) made this pull request unmergeable. Please resolve the merge conflicts by rebasing.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` llm-assisted An LLM-assisted PR as defined by the LLM policy. Requires ahead-of-time consent by assignee. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants