-
Notifications
You must be signed in to change notification settings - Fork 107
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
Cycle detected when evaluating trait selection obligation #2116
Comments
Thanks for reporting this! We'll take a look. |
This is definitely a bug on our end, though the rustc error message is also a red herring. Here's a self-contained repro: trait KnownLayout {
type MaybeUninit;
}
impl KnownLayout for u8 {
type MaybeUninit = core::mem::MaybeUninit<Self>;
}
impl<const N: usize, T> KnownLayout for [T; N]
where
T: KnownLayout
{
type MaybeUninit = [<T as KnownLayout>::MaybeUninit; N];
}
#[repr(C)]
pub struct Dummy([u8; Self::CONST]);
impl Dummy {
const CONST: usize = 42;
}
const _: () = {
#[repr(C)]
struct DummyMaybeUninit(<[u8; Self::CONST] as KnownLayout>::MaybeUninit);
impl KnownLayout for Dummy {
type MaybeUninit = DummyMaybeUninit;
}
}; The issue, here, is this line: struct DummyMaybeUninit(<[u8; Self::CONST] as KnownLayout>::MaybeUninit); ...because |
We can probably fix this by replacing occurrences of |
Hm, that approach is complicated by the fact that const exprs can be arbitrarily complicated and define new types in which struct Headache([u8; {
struct Migraine;
impl Migraine {
const A: usize = 21;
const B: usize = 21;
const LEN: usize = Self::A + Self::B;
}
impl Headache {
const A: usize = Migraine::LEN;
const B: usize = Migraine::LEN;
const LEN: usize = Self::A + Self::B;
}
Self::LEN
}]); |
Perhaps, instead, we can add a |
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<const N: usize> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: impl Field<0> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<const N: usize> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: impl Field<0> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<const N: usize> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: impl Field<0> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<const N: usize> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: impl Field<0> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<const N: usize> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: impl Field<0> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<const N: usize> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: impl Field<0> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<const N: usize> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: impl Field<0> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes google#2116
This commit revises the `KnownLayout` derive on `repr(C)` target structs to preserve the correct resolution of `Self` when constructing `__ZerocopyKnownLayoutMaybeUninit`. This type contains a `MaybeUninit` version of each of the target struct's field types. Previously, it achieved this by simply copying the tokens corresponding to field types from the definition of the target struct into the definition of `__ZerocopyKnownLayoutMaybeUninit` However, on types like this: #[repr(C)] struct Struct([u8; Self::N]); …this approach is insufficient. Pasted into `__ZerocopyKnownLayoutMaybeUninit`, `Self` ceases to refer to the target struct and instead refers to `__ZerocopyKnownLayoutMaybeUninit`. To preserve `Self` hygiene, this commit defines a struct for projecting the field types of the target struct based on their index: pub unsafe trait Field<Index> { type Type: ?Sized; } …then implements it for each of the field types of the target struct; e.g.: struct Index<const N: usize>; impl Field<Index<0>> for Struct { type Type = [u8; Self::N]; } With this, the fields of `__ZerocopyKnownLayoutMaybeUninit` can be defined hygienically; e.g., as `<Struct as Field<0>>::Type`. Fixes #2116 Co-authored-by: Jack Wrenn <jswrenn@amazon.com>
With
zerocopy
0.8.11, the following code failed to compile:This compiles on 0.8.10.
The text was updated successfully, but these errors were encountered: