Skip to content

Commit 756c549

Browse files
committed
Register ConstArgHasType obligation when normalizing trait projection consts
1 parent 9602bda commit 756c549

5 files changed

Lines changed: 129 additions & 2 deletions

File tree

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,16 @@ where
388388
kind => panic!("expected projection, found {kind:?}"),
389389
};
390390

391-
ecx.instantiate_normalizes_to_term(goal, term.instantiate(cx, target_args));
391+
let instantiated_term: I::Term = term.instantiate(cx, target_args);
392+
if let Some(ct) = instantiated_term.as_const() {
393+
let expected_ty = cx.type_of(target_item_def_id).instantiate(cx, target_args);
394+
ecx.add_goal(
395+
GoalSource::Misc,
396+
goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)),
397+
);
398+
}
399+
400+
ecx.instantiate_normalizes_to_term(goal, instantiated_term);
392401
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
393402
})
394403
}

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2061,7 +2061,18 @@ fn confirm_impl_candidate<'cx, 'tcx>(
20612061
Progress { term: err, obligations: nested }
20622062
} else {
20632063
assoc_term_own_obligations(selcx, obligation, &mut nested);
2064-
Progress { term: term.instantiate(tcx, args), obligations: nested }
2064+
let instantiated_term: Term<'tcx> = term.instantiate(tcx, args);
2065+
if let Some(ct) = instantiated_term.as_const() {
2066+
let expected_ty = tcx.type_of(assoc_term.item.def_id).instantiate(tcx, args);
2067+
nested.push(Obligation::with_depth(
2068+
tcx,
2069+
obligation.cause.clone(),
2070+
obligation.recursion_depth + 1,
2071+
obligation.param_env,
2072+
ty::ClauseKind::ConstArgHasType(ct, expected_ty),
2073+
));
2074+
}
2075+
Progress { term: instantiated_term, obligations: nested }
20652076
};
20662077
Ok(Projected::Progress(progress))
20672078
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error[E0053]: method `arr` has an incompatible type for trait
2+
--> $DIR/type-const-value-type-mismatch.rs:23:5
3+
|
4+
LL | fn arr() -> [u8; const { Self::LEN }] {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a size of 0, found one with a size of const { Self::LEN }
6+
|
7+
note: type in trait
8+
--> $DIR/type-const-value-type-mismatch.rs:15:5
9+
|
10+
LL | fn arr() -> [u8; Self::LEN];
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= note: expected signature `fn() -> [u8; 0]`
13+
found signature `fn() -> [u8; const { Self::LEN }]`
14+
15+
error: the constant `0` is not of type `usize`
16+
--> $DIR/type-const-value-type-mismatch.rs:20:5
17+
|
18+
LL | type const LEN: usize = 0u8;
19+
| ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8`
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/type-const-value-type-mismatch.rs:23:17
23+
|
24+
LL | fn arr() -> [u8; const { Self::LEN }] {}
25+
| --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Self::LEN }]`, found `()`
26+
| |
27+
| implicitly returns `()` as its body has no tail or `return` expression
28+
29+
error: aborting due to 3 previous errors
30+
31+
Some errors have detailed explanations: E0053, E0308.
32+
For more information about an error, try `rustc --explain E0053`.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
error[E0271]: type mismatch resolving `<A as Array>::LEN normalizes-to 0`
2+
--> $DIR/type-const-value-type-mismatch.rs:23:5
3+
|
4+
LL | fn arr() -> [u8; const { Self::LEN }] {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
6+
|
7+
note: the requirement `<A as Array>::LEN normalizes-to 0` appears on the `impl`'s associated function `arr` but not on the corresponding trait's associated function
8+
--> $DIR/type-const-value-type-mismatch.rs:15:8
9+
|
10+
LL | pub trait Array {
11+
| ----- in this trait
12+
LL | type const LEN: usize;
13+
LL | fn arr() -> [u8; Self::LEN];
14+
| ^^^ this trait's associated function doesn't have the requirement `<A as Array>::LEN normalizes-to 0`
15+
16+
error: the constant `0` is not of type `usize`
17+
--> $DIR/type-const-value-type-mismatch.rs:20:5
18+
|
19+
LL | type const LEN: usize = 0u8;
20+
| ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8`
21+
22+
error[E0284]: type annotations needed: cannot normalize `<A as Array>::arr::{constant#0}`
23+
--> $DIR/type-const-value-type-mismatch.rs:23:17
24+
|
25+
LL | fn arr() -> [u8; const { Self::LEN }] {}
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `<A as Array>::arr::{constant#0}`
27+
28+
error[E0284]: type annotations needed: cannot satisfy `the constant `<Self as Array>::LEN` can be evaluated`
29+
--> $DIR/type-const-value-type-mismatch.rs:15:17
30+
|
31+
LL | fn arr() -> [u8; Self::LEN];
32+
| ^^^^^^^^^^^^^^^ cannot satisfy `the constant `<Self as Array>::LEN` can be evaluated`
33+
34+
error[E0308]: mismatched types
35+
--> $DIR/type-const-value-type-mismatch.rs:23:17
36+
|
37+
LL | fn arr() -> [u8; const { Self::LEN }] {}
38+
| --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Self::LEN }]`, found `()`
39+
| |
40+
| implicitly returns `()` as its body has no tail or `return` expression
41+
42+
error: aborting due to 5 previous errors
43+
44+
Some errors have detailed explanations: E0271, E0284, E0308.
45+
For more information about an error, try `rustc --explain E0271`.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Regression test for https://github.com/rust-lang/rust/issues/152962
2+
3+
//@ revisions: current next
4+
//@ ignore-compare-mode-next-solver (explicit revisions)
5+
//@[next] compile-flags: -Znext-solver
6+
//@ compile-flags: -Zvalidate-mir
7+
8+
#![feature(min_generic_const_args)]
9+
#![expect(incomplete_features)]
10+
11+
pub struct A;
12+
13+
pub trait Array {
14+
type const LEN: usize;
15+
fn arr() -> [u8; Self::LEN];
16+
//[next]~^ ERROR type annotations needed
17+
}
18+
19+
impl Array for A {
20+
type const LEN: usize = 0u8;
21+
//~^ ERROR the constant `0` is not of type `usize`
22+
23+
fn arr() -> [u8; const { Self::LEN }] {}
24+
//~^ ERROR mismatched types [E0308]
25+
//[current]~| ERROR method `arr` has an incompatible type for trait [E0053]
26+
//[next]~| ERROR type annotations needed
27+
//[next]~| ERROR type mismatch resolving `<A as Array>::LEN normalizes-to 0` [E0271]
28+
}
29+
30+
fn main() {}

0 commit comments

Comments
 (0)