layout_of: put back not-so-unreachable case
This commit is contained in:
parent
71e06b9c59
commit
a825e37fe4
5 changed files with 91 additions and 1 deletions
|
@ -147,12 +147,25 @@ fn extract_const_value<'tcx>(
|
||||||
) -> Result<ty::Value<'tcx>, &'tcx LayoutError<'tcx>> {
|
) -> Result<ty::Value<'tcx>, &'tcx LayoutError<'tcx>> {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Value(cv) => Ok(cv),
|
ty::ConstKind::Value(cv) => Ok(cv),
|
||||||
ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => {
|
ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
|
||||||
if !ct.has_param() {
|
if !ct.has_param() {
|
||||||
bug!("failed to normalize const, but it is not generic: {ct:?}");
|
bug!("failed to normalize const, but it is not generic: {ct:?}");
|
||||||
}
|
}
|
||||||
Err(error(cx, LayoutError::TooGeneric(ty)))
|
Err(error(cx, LayoutError::TooGeneric(ty)))
|
||||||
}
|
}
|
||||||
|
ty::ConstKind::Unevaluated(_) => {
|
||||||
|
let err = if ct.has_param() {
|
||||||
|
LayoutError::TooGeneric(ty)
|
||||||
|
} else {
|
||||||
|
// This case is reachable with unsatisfiable predicates and GCE (which will
|
||||||
|
// cause anon consts to inherit the unsatisfiable predicates). For example
|
||||||
|
// if we have an unsatisfiable `u8: Trait` bound, then it's not a compile
|
||||||
|
// error to mention `[u8; <u8 as Trait>::CONST]`, but we can't compute its
|
||||||
|
// layout.
|
||||||
|
LayoutError::Unknown(ty)
|
||||||
|
};
|
||||||
|
Err(error(cx, err))
|
||||||
|
}
|
||||||
ty::ConstKind::Infer(_)
|
ty::ConstKind::Infer(_)
|
||||||
| ty::ConstKind::Bound(..)
|
| ty::ConstKind::Bound(..)
|
||||||
| ty::ConstKind::Placeholder(_)
|
| ty::ConstKind::Placeholder(_)
|
||||||
|
|
27
tests/ui/layout/gce-rigid-const-in-array-len.rs
Normal file
27
tests/ui/layout/gce-rigid-const-in-array-len.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//! With `feature(generic_const_exprs)`, anon consts (e.g. length in array types) will
|
||||||
|
//! inherit their parent's predicates. When combined with `feature(trivial_bounds)`, it
|
||||||
|
//! is possible to have an unevaluated constant that is rigid, but not generic.
|
||||||
|
//!
|
||||||
|
//! This is what happens below: `u8: A` does not hold in the global environment, but
|
||||||
|
//! with trivial bounds + GCE it it possible that `<u8 as A>::B` can appear in an array
|
||||||
|
//! length without causing a compile error. This constant is *rigid* (i.e. it cannot be
|
||||||
|
//! normalized further), but it is *not generic* (i.e. it does not depend on any generic
|
||||||
|
//! parameters).
|
||||||
|
//!
|
||||||
|
//! This test ensures that we do not ICE in layout computation when encountering such a
|
||||||
|
//! constant.
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
#![feature(generic_const_exprs)] //~ WARNING: the feature `generic_const_exprs` is incomplete
|
||||||
|
#![feature(trivial_bounds)]
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
trait A {
|
||||||
|
const B: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_layout(debug)]
|
||||||
|
struct S([u8; <u8 as A>::B]) //~ ERROR: the type `[u8; <u8 as A>::B]` has an unknown layout
|
||||||
|
where
|
||||||
|
u8: A;
|
17
tests/ui/layout/gce-rigid-const-in-array-len.stderr
Normal file
17
tests/ui/layout/gce-rigid-const-in-array-len.stderr
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/gce-rigid-const-in-array-len.rs:15:12
|
||||||
|
|
|
||||||
|
LL | #![feature(generic_const_exprs)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error: the type `[u8; <u8 as A>::B]` has an unknown layout
|
||||||
|
--> $DIR/gce-rigid-const-in-array-len.rs:25:1
|
||||||
|
|
|
||||||
|
LL | struct S([u8; <u8 as A>::B])
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
|
|
18
tests/ui/layout/unconstrained-param-ice-137308.rs
Normal file
18
tests/ui/layout/unconstrained-param-ice-137308.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
//! Regression test for <https://github.com/rust-lang/rust/issues/137308>.
|
||||||
|
//!
|
||||||
|
//! This used to ICE in layout computation, because `<u8 as A>::B` fails to normalize
|
||||||
|
//! due to the unconstrained param on the impl.
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
trait A {
|
||||||
|
const B: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: ?Sized> A for u8 { //~ ERROR: the type parameter `C` is not constrained
|
||||||
|
const B: usize = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_layout(debug)]
|
||||||
|
struct S([u8; <u8 as A>::B]); //~ ERROR: the type `[u8; <u8 as A>::B]` has an unknown layout
|
15
tests/ui/layout/unconstrained-param-ice-137308.stderr
Normal file
15
tests/ui/layout/unconstrained-param-ice-137308.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0207]: the type parameter `C` is not constrained by the impl trait, self type, or predicates
|
||||||
|
--> $DIR/unconstrained-param-ice-137308.rs:13:6
|
||||||
|
|
|
||||||
|
LL | impl<C: ?Sized> A for u8 {
|
||||||
|
| ^ unconstrained type parameter
|
||||||
|
|
||||||
|
error: the type `[u8; <u8 as A>::B]` has an unknown layout
|
||||||
|
--> $DIR/unconstrained-param-ice-137308.rs:18:1
|
||||||
|
|
|
||||||
|
LL | struct S([u8; <u8 as A>::B]);
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0207`.
|
Loading…
Add table
Add a link
Reference in a new issue