Skip to content

Commit 78d2dea

Browse files
committed
use parent substs
1 parent 44a500c commit 78d2dea

File tree

7 files changed

+123
-3
lines changed

7 files changed

+123
-3
lines changed

compiler/rustc_trait_selection/src/traits/wf.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::traits;
33
use rustc_hir as hir;
44
use rustc_hir::def_id::DefId;
55
use rustc_hir::lang_items::LangItem;
6-
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
7-
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
6+
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
7+
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeVisitable};
88
use rustc_span::Span;
99

1010
use std::iter;
@@ -452,7 +452,24 @@ impl<'tcx> WfPredicates<'tcx> {
452452
match ct.kind() {
453453
ty::ConstKind::Unevaluated(uv) => {
454454
if !ct.has_escaping_bound_vars() {
455-
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
455+
let substs = if let Some(did) = uv.def.did.as_local()
456+
&& self
457+
.tcx
458+
.hir()
459+
.opt_const_param_default_param_def_id(
460+
self.tcx.hir().local_def_id_to_hir_id(did),
461+
)
462+
.is_some()
463+
&& let Some(did) = self.tcx.opt_parent(uv.def.did)
464+
{
465+
// HACK(TaKO8Ki) `WfPredicates::nominal_obligations` calls `SubstsFolder::fold_const` in it.
466+
// If `uv.substs` is used, it will cause an ICE because `uv.substs` does not include the const.
467+
// `substs` argument `WfPredicates::nominal_obligations` should be parent substs here.
468+
InternalSubsts::identity_for_item(self.tcx, did)
469+
} else {
470+
uv.substs
471+
};
472+
let obligations = self.nominal_obligations(uv.def.did, substs);
456473
self.out.extend(obligations);
457474

458475
let predicate =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(generic_const_exprs)]
2+
#![allow(incomplete_features)]
3+
4+
const fn t<const N: usize>() -> u8 {
5+
N as u8
6+
}
7+
8+
#[repr(u8)]
9+
enum T<const N: u8 = { T::<0>::A as u8 + T::<0>::B as u8 }>
10+
where
11+
[(); N as usize]:
12+
{
13+
A = t::<N>() as u8, B //~ ERROR: unconstrained generic constant
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: unconstrained generic constant
2+
--> $DIR/issue-101036.rs:13:9
3+
|
4+
LL | A = t::<N>() as u8, B
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= help: try adding a `where` bound using this expression: `where [(); t::<N>() as u8]:`
8+
9+
error: aborting due to previous error
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(generic_const_exprs)]
2+
#![allow(incomplete_features)]
3+
4+
struct A<const B: str = 1, C>;
5+
//~^ ERROR generic parameters with a default must be trailing
6+
//~| ERROR the size for values of type `str` cannot be known at compilation time
7+
//~| ERROR mismatched types
8+
//~| ERROR parameter `C` is never used
9+
//~| ERROR `str` is forbidden as the type of a const generic parameter
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error: generic parameters with a default must be trailing
2+
--> $DIR/issue-105631.rs:4:16
3+
|
4+
LL | struct A<const B: str = 1, C>;
5+
| ^
6+
7+
error[E0277]: the size for values of type `str` cannot be known at compilation time
8+
--> $DIR/issue-105631.rs:4:25
9+
|
10+
LL | struct A<const B: str = 1, C>;
11+
| ^ doesn't have a size known at compile-time
12+
|
13+
= help: the trait `Sized` is not implemented for `str`
14+
= note: constant expressions must have a statically known size
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/issue-105631.rs:4:25
18+
|
19+
LL | struct A<const B: str = 1, C>;
20+
| ^ expected `str`, found integer
21+
22+
error[E0392]: parameter `C` is never used
23+
--> $DIR/issue-105631.rs:4:28
24+
|
25+
LL | struct A<const B: str = 1, C>;
26+
| ^ unused parameter
27+
|
28+
= help: consider removing `C`, referring to it in a field, or using a marker such as `PhantomData`
29+
= help: if you intended `C` to be a const parameter, use `const C: usize` instead
30+
31+
error: `str` is forbidden as the type of a const generic parameter
32+
--> $DIR/issue-105631.rs:4:19
33+
|
34+
LL | struct A<const B: str = 1, C>;
35+
| ^^^
36+
|
37+
= note: the only supported types are integers, `bool` and `char`
38+
= help: more complex types are supported with `#![feature(adt_const_params)]`
39+
40+
error: aborting due to 5 previous errors
41+
42+
Some errors have detailed explanations: E0277, E0308, E0392.
43+
For more information about an error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(generic_const_exprs)]
2+
#![allow(incomplete_features)]
3+
4+
const DEFAULT: u32 = 1;
5+
6+
struct V<const U: usize = DEFAULT> //~ ERROR mismatched types
7+
where
8+
[(); U]:;
9+
10+
trait Tr {}
11+
12+
impl Tr for V {}
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-106473.rs:6:27
3+
|
4+
LL | struct V<const U: usize = DEFAULT>
5+
| ^^^^^^^ expected `usize`, found `u32`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)