Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion library/core/src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use crate::marker::PhantomData;
#[expect(missing_debug_implementations)]
#[fundamental]
pub struct FieldRepresentingType<T: ?Sized, const VARIANT: u32, const FIELD: u32> {
_phantom: PhantomData<T>,
// We want this type to be invariant over `T`, because otherwise `field_of!(Struct<'short>,
// field)` is a subtype of `field_of!(Struct<'long>, field)`. This subtype relationship does not
// have an immediately obvious meaning and we want to prevent people from relying on it.
_phantom: PhantomData<fn(T) -> T>,
}

// SAFETY: `FieldRepresentingType` doesn't contain any `T`
Expand Down
34 changes: 34 additions & 0 deletions tests/ui/field_representing_types/invariant.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error: lifetime may not live long enough
--> $DIR/invariant.rs:15:5
|
LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | consume(x, y);
| ^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of the type `field_of!(Struct<'_>, field)`, which makes the generic argument `Struct<'_>` invariant
= note: the struct `FieldRepresentingType<T, VARIANT, FIELD>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error: lifetime may not live long enough
--> $DIR/invariant.rs:15:5
|
LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | consume(x, y);
| ^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of the type `field_of!(Struct<'_>, field)`, which makes the generic argument `Struct<'_>` invariant
= note: the struct `FieldRepresentingType<T, VARIANT, FIELD>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

help: `'a` and `'b` must be the same: replace one with the other

error: aborting due to 2 previous errors

34 changes: 34 additions & 0 deletions tests/ui/field_representing_types/invariant.old.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error: lifetime may not live long enough
--> $DIR/invariant.rs:15:5
|
LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | consume(x, y);
| ^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of the type `field_of!(Struct<'_>, field)`, which makes the generic argument `Struct<'_>` invariant
= note: the struct `FieldRepresentingType<T, VARIANT, FIELD>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error: lifetime may not live long enough
--> $DIR/invariant.rs:15:5
|
LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | consume(x, y);
| ^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of the type `field_of!(Struct<'_>, field)`, which makes the generic argument `Struct<'_>` invariant
= note: the struct `FieldRepresentingType<T, VARIANT, FIELD>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

help: `'a` and `'b` must be the same: replace one with the other

error: aborting due to 2 previous errors

20 changes: 20 additions & 0 deletions tests/ui/field_representing_types/invariant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//@ revisions: old next
//@ [next] compile-flags: -Znext-solver
#![expect(incomplete_features)]
#![feature(field_projections)]

use std::field::field_of;

pub struct Struct<'a> {
field: &'a (),
}

fn consume<'a>(_: field_of!(Struct<'a>, field), _: field_of!(Struct<'a>, field)) {}

fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) {
consume(x, y);
//~^ ERROR: lifetime may not live long enough
//~^^ ERROR: lifetime may not live long enough
}

fn main() {}
Loading