Skip to content

Commit 1240be2

Browse files
committed
Register ConstArgHasType when normalizing free const aliases
1 parent 1f9a514 commit 1240be2

11 files changed

Lines changed: 99 additions & 11 deletions

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ where
4949
kind => panic!("expected free alias, found {kind:?}"),
5050
};
5151

52-
self.instantiate_normalizes_to_term(goal, actual);
52+
self.instantiate_normalizes_to_term_with_type_check(goal, actual);
5353
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
5454
}
5555
}

compiler/rustc_trait_selection/src/traits/normalize.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
339339
}),
340340
);
341341
self.depth += 1;
342-
let res = if free.kind.is_type() {
342+
let res: ty::Term<'tcx> = if free.kind.is_type() {
343343
infcx
344344
.tcx
345345
.type_of(free.def_id())
@@ -356,6 +356,19 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
356356
.fold_with(self)
357357
.into()
358358
};
359+
// When normalizing a free const alias, register a `ConstArgHasType`
360+
// obligation to ensure the const value's type matches the declared type.
361+
if let Some(ct) = res.as_const() {
362+
let expected_ty =
363+
infcx.tcx.type_of(free.def_id()).instantiate(infcx.tcx, free.args).skip_norm_wip();
364+
self.obligations.push(Obligation::with_depth(
365+
infcx.tcx,
366+
self.cause.clone(),
367+
self.depth,
368+
self.param_env,
369+
ty::ClauseKind::ConstArgHasType(ct, expected_ty),
370+
));
371+
}
359372
self.depth -= 1;
360373
res
361374
}

compiler/rustc_trait_selection/src/traits/query/normalize.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use rustc_data_structures::sso::SsoHashMap;
66
use rustc_data_structures::stack::ensure_sufficient_stack;
7-
use rustc_infer::traits::PredicateObligations;
7+
use rustc_infer::traits::{Obligation, PredicateObligations};
88
use rustc_macros::extension;
99
pub use rustc_middle::traits::query::NormalizationResult;
1010
use rustc_middle::ty::{
@@ -372,6 +372,18 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> {
372372
} else {
373373
result.normalized_term
374374
};
375+
// When normalizing a const alias, register a `ConstArgHasType` obligation
376+
// to ensure the const value's type matches the declared type.
377+
if let Some(ct) = res.as_const() {
378+
let expected_ty =
379+
tcx.type_of(term.def_id()).instantiate(tcx, term.args).skip_norm_wip();
380+
self.obligations.push(Obligation::new(
381+
tcx,
382+
self.cause.clone(),
383+
self.param_env,
384+
ty::ClauseKind::ConstArgHasType(ct, expected_ty),
385+
));
386+
}
375387
// `tcx.normalize_canonicalized_projection` may normalize to a type that
376388
// still has unevaluated consts, so keep normalizing here if that's the case.
377389
// Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer

compiler/rustc_traits/src/normalize_erasing_regions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Par
6363
fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
6464
match p.kind().skip_binder() {
6565
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
66-
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => false,
66+
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
67+
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => false,
6768
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
6869
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
6970
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
70-
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
7171
| ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_))
7272
| ty::PredicateKind::NormalizesTo(..)
7373
| ty::PredicateKind::AliasRelate(..)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@ compile-flags: -Zvalidate-mir -Znext-solver
2+
3+
#![feature(min_generic_const_args)]
4+
#![expect(incomplete_features)]
5+
6+
type const X: usize = const { N };
7+
//~^ ERROR type annotations needed
8+
9+
type const N: usize = "this isn't a usize";
10+
//~^ ERROR the constant `"this isn't a usize"` is not of type `usize`
11+
12+
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0284]: type annotations needed: cannot normalize `X::{constant#0}`
2+
--> $DIR/type-const-free-anon-const-mismatch.rs:6:1
3+
|
4+
LL | type const X: usize = const { N };
5+
| ^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}`
6+
7+
error: the constant `"this isn't a usize"` is not of type `usize`
8+
--> $DIR/type-const-free-anon-const-mismatch.rs:9:1
9+
|
10+
LL | type const N: usize = "this isn't a usize";
11+
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str`
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0284`.

tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr renamed to tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error: the constant `"this isn't a usize"` is not of type `usize`
2-
--> $DIR/type-const-free-value-type-mismatch.rs:7:1
2+
--> $DIR/type-const-free-value-type-mismatch.rs:10:1
33
|
44
LL | type const N: usize = "this isn't a usize";
55
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str`
66

77
error[E0080]: transmuting from $BYTE-byte type to $BYTE-byte type: `&str` -> `usize`
8-
--> $DIR/type-const-free-value-type-mismatch.rs:10:24
8+
--> $DIR/type-const-free-value-type-mismatch.rs:13:24
99
|
1010
LL | fn f() -> [u8; const { N }] {}
1111
| ^ evaluation of `f::{constant#0}` failed here
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: the constant `"this isn't a usize"` is not of type `usize`
2+
--> $DIR/type-const-free-value-type-mismatch.rs:10:1
3+
|
4+
LL | type const N: usize = "this isn't a usize";
5+
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str`
6+
7+
error[E0284]: type annotations needed: cannot normalize `f::{constant#0}`
8+
--> $DIR/type-const-free-value-type-mismatch.rs:13:11
9+
|
10+
LL | fn f() -> [u8; const { N }] {}
11+
| ^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}`
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/type-const-free-value-type-mismatch.rs:13:11
15+
|
16+
LL | fn f() -> [u8; const { N }] {}
17+
| - ^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()`
18+
| |
19+
| implicitly returns `()` as its body has no tail or `return` expression
20+
21+
error: aborting due to 3 previous errors
22+
23+
Some errors have detailed explanations: E0284, E0308.
24+
For more information about an error, try `rustc --explain E0284`.
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
#![feature(min_generic_const_args)]
22
#![expect(incomplete_features)]
33

4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
47
//@ compile-flags: -Zvalidate-mir
58
//@ normalize-stderr: "\d+-byte" -> "$$BYTE-byte"
69

710
type const N: usize = "this isn't a usize";
811
//~^ ERROR the constant `"this isn't a usize"` is not of type `usize`
912

1013
fn f() -> [u8; const { N }] {}
11-
//~^ ERROR transmuting from
14+
//[current]~^ ERROR transmuting from
15+
//[next]~^^ ERROR type annotations needed
16+
//[next]~| ERROR mismatched types [E0308]
1217

1318
fn main() {}

tests/ui/const-generics/mgca/type_const-mismatched-types.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ type const FREE: u32 = 5_usize;
55
//~^ ERROR the constant `5` is not of type `u32`
66

77
type const FREE2: isize = FREE;
8-
//~^ ERROR the constant `5` is not of type `isize`
8+
//~^ ERROR the constant `5` is not of type `u32`
9+
//~| ERROR the constant `5` is not of type `isize`
910

1011
trait Tr {
1112
type const N: usize;

0 commit comments

Comments
 (0)