diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2025-01-14 07:56:24 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-14 07:56:24 +0100 |
| commit | 4cadb5d513348fa2eee2e1ef1d50eca5dc9030bc (patch) | |
| tree | 60f66fc66175d6acb8ddb465d2fc86bb919804d9 | |
| parent | 62f2c3c75c43fcee7d32716c25885a3caa7a99e4 (diff) | |
| parent | 7a3c4f73ae165b7087ab9f03f11ce3b4006d1498 (diff) | |
| download | rust-4cadb5d513348fa2eee2e1ef1d50eca5dc9030bc.tar.gz rust-4cadb5d513348fa2eee2e1ef1d50eca5dc9030bc.zip | |
Rollup merge of #135464 - lukas-code:project-infinite-to-error, r=FedericoBruzzone,oli-obk
fix ICE with references to infinite structs in consts
fixes https://github.com/rust-lang/rust/issues/114484
Normalizing `<Type as Pointee>::Metadata` may emit a (non-fatal) error during trait selection if finding the struct tail of `Type` hits the recursion limit. When this happens, prior this PR, we would treat the projection as rigid, i.e. don't normalize it further. This PR changes it so that we normalize to `ty::Error` instead.
This is important, because to compute the layout of `&Type` we need to compute the layout of `<Type as Pointee>::Metadata`
https://github.com/rust-lang/rust/blob/2ae9916816a448fcaab3b2da461de754eda0055a/compiler/rustc_ty_utils/src/layout.rs#L247-L273
and computing the layout of a rigid alias will (correctly) fail and needs to report an error to the user. For example:
```rust
trait Project {
type Assoc;
}
fn foo<T: Project>() {
[(); {
let _: Option<T::Assoc> = None;
// ^^^^^^^^ this projection is rigid, so we can't know it's layout
0
}];
}
```
```
error: constant expression depends on a generic parameter
--> src/lib.rs:6:10
|
6 | [(); {
| __________^
7 | | let _: Option<T::Assoc> = None;
8 | | // ^^^^^^^^ this projection is rigid, so we can't know it's layout
9 | | 0
10 | | }];
| |_____^
|
= note: this may fail depending on what value the parameter takes
```
For non-generic rigid projections we will currently ICE, because we incorrectly assume that `LayoutError::Unknown` means that a const must be generic (https://github.com/rust-lang/rust/issues/135138). This is being fixed and turned into a proper error in https://github.com/rust-lang/rust/pull/135158.
```rust
#![feature(trivial_bounds)]
trait Project {
type Assoc;
}
fn foo()
where
u8: Project,
{
[(); {
let _: Option<<u8 as Project>::Assoc> = None; // ICEs currently, but will be an error
0
}];
}
```
However, if we hit the recursion limit when normalizing `<Type as Pointee>::Metadata` we don't want to report a layout error, because we already emitted the recursion error. So by normalizing to `ty::Error` here, we get a `LayoutError::ReferencesError` instead of a `LayoutError::Unknown` and don't report the layout error to the user.
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/project.rs | 7 | ||||
| -rw-r--r-- | tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs (renamed from tests/crashes/114484.rs) | 10 | ||||
| -rw-r--r-- | tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr | 86 | ||||
| -rw-r--r-- | tests/ui/structs/ice-struct-tail-normalization-113272.rs | 1 | ||||
| -rw-r--r-- | tests/ui/structs/ice-struct-tail-normalization-113272.stderr | 13 |
5 files changed, 111 insertions, 6 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 69b7d5cff1e..aae0e34ddf3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1148,7 +1148,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // If returned by `struct_tail` this is the empty tuple. | ty::Tuple(..) // Integers and floats are always Sized, and so have unit type metadata. - | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, + | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) + // This happens if we reach the recursion limit when finding the struct tail. + | ty::Error(..) => true, // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able. // Otherwise, type parameters, opaques, and unnormalized projections have @@ -1179,8 +1181,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Alias(..) | ty::Bound(..) | ty::Placeholder(..) - | ty::Infer(..) - | ty::Error(_) => { + | ty::Infer(..) => { if tail.has_infer_types() { candidate_set.mark_ambiguous(); } diff --git a/tests/crashes/114484.rs b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs index 9d90c153624..410862c5326 100644 --- a/tests/crashes/114484.rs +++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs @@ -1,4 +1,12 @@ -//@ known-bug: #114484 +//@ build-fail + +//@ error-pattern: reached the recursion limit while instantiating +//@ error-pattern: reached the recursion limit finding the struct tail + +// Regression test for #114484: This used to ICE during monomorphization, because we treated +// `<VirtualWrapper<...> as Pointee>::Metadata` as a rigid projection after reaching the recursion +// limit when finding the struct tail. + use std::marker::PhantomData; trait MyTrait { diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr new file mode 100644 index 00000000000..7c961b79c0c --- /dev/null +++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr @@ -0,0 +1,86 @@ +error: reached the recursion limit finding the struct tail for `[u8; 256]` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: reached the recursion limit finding the struct tail for `[u8; 256]` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: reached the recursion limit finding the struct tail for `[u8; 256]` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: reached the recursion limit finding the struct tail for `[u8; 256]` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + | +LL | unsafe { virtualize_my_trait(L, self) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: reached the recursion limit finding the struct tail for `SomeData<256>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: reached the recursion limit finding the struct tail for `SomeData<256>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: reached the recursion limit finding the struct tail for `SomeData<256>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: reached the recursion limit finding the struct tail for `SomeData<256>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + | +LL | unsafe { virtualize_my_trait(L, self) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + | +LL | unsafe { virtualize_my_trait(L, self) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: reached the recursion limit while instantiating `<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<..., 1>, 1>, 1>, 1>, 1> as MyTrait>::virtualize` + | +note: `<VirtualWrapper<T, L> as MyTrait>::virtualize` defined here + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:25:5 + | +LL | fn virtualize(&self) -> &dyn MyTrait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation-struct-tail-ice-114484/infinite-instantiation-struct-tail-ice-114484.long-type.txt' + +error: aborting due to 13 previous errors + diff --git a/tests/ui/structs/ice-struct-tail-normalization-113272.rs b/tests/ui/structs/ice-struct-tail-normalization-113272.rs index 85d3d1b4886..0ae24a7b71b 100644 --- a/tests/ui/structs/ice-struct-tail-normalization-113272.rs +++ b/tests/ui/structs/ice-struct-tail-normalization-113272.rs @@ -13,5 +13,6 @@ struct Other { fn main() { unsafe { std::mem::transmute::<Option<()>, Option<&Other>>(None); + //~^ ERROR cannot transmute } } diff --git a/tests/ui/structs/ice-struct-tail-normalization-113272.stderr b/tests/ui/structs/ice-struct-tail-normalization-113272.stderr index a205eb80f5c..8c55dbca187 100644 --- a/tests/ui/structs/ice-struct-tail-normalization-113272.stderr +++ b/tests/ui/structs/ice-struct-tail-normalization-113272.stderr @@ -13,7 +13,16 @@ LL | type RefTarget; LL | impl Trait for () where Missing: Trait {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `RefTarget` in implementation -error: aborting due to 2 previous errors +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/ice-struct-tail-normalization-113272.rs:15:9 + | +LL | std::mem::transmute::<Option<()>, Option<&Other>>(None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<()>` (8 bits) + = note: target type: `Option<&Other>` (unable to determine layout for `Other` because `<() as Trait>::RefTarget` cannot be normalized) + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0046, E0412. +Some errors have detailed explanations: E0046, E0412, E0512. For more information about an error, try `rustc --explain E0046`. |
