Skip to content

mGCA: Validate const literal against expected type#152001

Draft
reddevilmidzy wants to merge 2 commits intorust-lang:mainfrom
reddevilmidzy:mgca-i
Draft

mGCA: Validate const literal against expected type#152001
reddevilmidzy wants to merge 2 commits intorust-lang:mainfrom
reddevilmidzy:mgca-i

Conversation

@reddevilmidzy
Copy link
Member

@reddevilmidzy reddevilmidzy commented Feb 2, 2026

close: #151625
close: #150983

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 2, 2026
@rust-log-analyzer

This comment has been minimized.

tcx.at(span).lit_to_const(input)
}

fn const_lit_matches_ty(&self, kind: &LitKind, ty: Ty<'tcx>, neg: bool) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in most cases we actually don't want to emit errors during HIR ty lowering for type mismatches here. E.g. if we have a true literal it doesn't really matter if the expected type is u32, we can still lower to a 0x1 valtree of type bool and then get a type checking error later.

Separately from this, we already do these checks in fn lit_to_const (just ICEing if they don't hold instead of a proper error) so it probably doesn't make sense to duplicate them here too 🤔

I think it would make sense for lit_to_const to return an Option<ty::Value<'tcx>> and stop ICEing/erroring altogether.

You could then:

  • Move const_lit_matches_ty to THIR building for patterns (the only place other than const-generics that calls lit_to_const) and create a ty::ConstKind::Error if it's false (or if lit_to_const returns None)
  • Here in HIR ty lowering we can emit a proper error about needing more type information for the literal if lit_to_const returns None. And we can entirely ignore the possibility of type mismatches because type checking should take care of that for us

@BoxyUwU
Copy link
Member

BoxyUwU commented Feb 4, 2026

very cool :) thanks for working on this

@rust-bors

This comment has been minimized.

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 6, 2026
…=oli-obk

Dont strip const blocks in array lengths

r? oli-obk

mGCA now handles const blocks by *always* handling them during `lower_expr_to_const_arg_direct` instead of *sometimes* stripping them out at parse time. This is just generally a lot clearer/nicer but also means parsing isn't lossy which is just straight up wrong.

We now use `MgcaDisambiguation::Direct` for const blocks because we "directly" represent a const block as `hir::ConstArgKind::Anon` :> The only time that an anon const for const generics uses `MgcaDisambiguation::AnonConst` is for unbraced literals.

Once we properly support literals in `hir::ConstArgKind` (see rust-lang#152139 rust-lang#152001) then `MgcaDisambiguation` can be renamed to `AnonConstKind` with `TypeSystem` and `NonTypeSystem` variants. We can also get rid of `mgca_direct_lit_hack`. I expect this to be a very nice cleanup :)

Fixes rust-lang/rustfmt#6788

The diff relating to passing spans around is to avoid a bunch of mGCA diagnostics changing from  `const {}` to `{}`. I'm not entirely sure why this was happening.

cc @rust-lang/rustfmt

How do I run the tests in the rustfmt repo from here? `x test rustfmt` only seems to run like 100 tests and doesn't result in a `target/issue-6788.rs` getting created. I've verified locally that this formats correctly though
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 6, 2026
…=oli-obk

Dont strip const blocks in array lengths

r? oli-obk

mGCA now handles const blocks by *always* handling them during `lower_expr_to_const_arg_direct` instead of *sometimes* stripping them out at parse time. This is just generally a lot clearer/nicer but also means parsing isn't lossy which is just straight up wrong.

We now use `MgcaDisambiguation::Direct` for const blocks because we "directly" represent a const block as `hir::ConstArgKind::Anon` :> The only time that an anon const for const generics uses `MgcaDisambiguation::AnonConst` is for unbraced literals.

Once we properly support literals in `hir::ConstArgKind` (see rust-lang#152139 rust-lang#152001) then `MgcaDisambiguation` can be renamed to `AnonConstKind` with `TypeSystem` and `NonTypeSystem` variants. We can also get rid of `mgca_direct_lit_hack`. I expect this to be a very nice cleanup :)

Fixes rust-lang/rustfmt#6788

The diff relating to passing spans around is to avoid a bunch of mGCA diagnostics changing from  `const {}` to `{}`. I'm not entirely sure why this was happening.

cc @rust-lang/rustfmt

How do I run the tests in the rustfmt repo from here? `x test rustfmt` only seems to run like 100 tests and doesn't result in a `target/issue-6788.rs` getting created. I've verified locally that this formats correctly though
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 6, 2026
…=oli-obk

Dont strip const blocks in array lengths

r? oli-obk

mGCA now handles const blocks by *always* handling them during `lower_expr_to_const_arg_direct` instead of *sometimes* stripping them out at parse time. This is just generally a lot clearer/nicer but also means parsing isn't lossy which is just straight up wrong.

We now use `MgcaDisambiguation::Direct` for const blocks because we "directly" represent a const block as `hir::ConstArgKind::Anon` :> The only time that an anon const for const generics uses `MgcaDisambiguation::AnonConst` is for unbraced literals.

Once we properly support literals in `hir::ConstArgKind` (see rust-lang#152139 rust-lang#152001) then `MgcaDisambiguation` can be renamed to `AnonConstKind` with `TypeSystem` and `NonTypeSystem` variants. We can also get rid of `mgca_direct_lit_hack`. I expect this to be a very nice cleanup :)

Fixes rust-lang/rustfmt#6788

The diff relating to passing spans around is to avoid a bunch of mGCA diagnostics changing from  `const {}` to `{}`. I'm not entirely sure why this was happening.

cc @rust-lang/rustfmt

How do I run the tests in the rustfmt repo from here? `x test rustfmt` only seems to run like 100 tests and doesn't result in a `target/issue-6788.rs` getting created. I've verified locally that this formats correctly though
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 7, 2026
…=oli-obk

Dont strip const blocks in array lengths

r? oli-obk

mGCA now handles const blocks by *always* handling them during `lower_expr_to_const_arg_direct` instead of *sometimes* stripping them out at parse time. This is just generally a lot clearer/nicer but also means parsing isn't lossy which is just straight up wrong.

We now use `MgcaDisambiguation::Direct` for const blocks because we "directly" represent a const block as `hir::ConstArgKind::Anon` :> The only time that an anon const for const generics uses `MgcaDisambiguation::AnonConst` is for unbraced literals.

Once we properly support literals in `hir::ConstArgKind` (see rust-lang#152139 rust-lang#152001) then `MgcaDisambiguation` can be renamed to `AnonConstKind` with `TypeSystem` and `NonTypeSystem` variants. We can also get rid of `mgca_direct_lit_hack`. I expect this to be a very nice cleanup :)

Fixes rust-lang/rustfmt#6788

The diff relating to passing spans around is to avoid a bunch of mGCA diagnostics changing from  `const {}` to `{}`. I'm not entirely sure why this was happening.

cc @rust-lang/rustfmt

How do I run the tests in the rustfmt repo from here? `x test rustfmt` only seems to run like 100 tests and doesn't result in a `target/issue-6788.rs` getting created. I've verified locally that this formats correctly though
rust-timer added a commit that referenced this pull request Feb 7, 2026
Rollup merge of #152234 - BoxyUwU:dont_strip_const_blocks, r=oli-obk

Dont strip const blocks in array lengths

r? oli-obk

mGCA now handles const blocks by *always* handling them during `lower_expr_to_const_arg_direct` instead of *sometimes* stripping them out at parse time. This is just generally a lot clearer/nicer but also means parsing isn't lossy which is just straight up wrong.

We now use `MgcaDisambiguation::Direct` for const blocks because we "directly" represent a const block as `hir::ConstArgKind::Anon` :> The only time that an anon const for const generics uses `MgcaDisambiguation::AnonConst` is for unbraced literals.

Once we properly support literals in `hir::ConstArgKind` (see #152139 #152001) then `MgcaDisambiguation` can be renamed to `AnonConstKind` with `TypeSystem` and `NonTypeSystem` variants. We can also get rid of `mgca_direct_lit_hack`. I expect this to be a very nice cleanup :)

Fixes rust-lang/rustfmt#6788

The diff relating to passing spans around is to avoid a bunch of mGCA diagnostics changing from  `const {}` to `{}`. I'm not entirely sure why this was happening.

cc @rust-lang/rustfmt

How do I run the tests in the rustfmt repo from here? `x test rustfmt` only seems to run like 100 tests and doesn't result in a `target/issue-6788.rs` getting created. I've verified locally that this formats correctly though
let bits = parse_float_into_scalar(n, *fty, neg)?;
ty::ValTree::from_scalar_int(tcx, bits)
}
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, c.into()),
Copy link
Member

@BoxyUwU BoxyUwU Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you change most of the type patterns to be _

Suggested change
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, c.into()),
(ast::LitKind::Char(c), _) => ty::ValTree::from_scalar_int(tcx, c.into()),

I think we should produce a valtree regardless of the expected type if we can. i think the only arms that actually need to know the expected type would be unsuffixed integer literals. ah I guess byte strings also care

each arm should also return a Ty for what the type of the valtree is. I think we should rename the ty local to expected_ty or something to make it clear it could be different from the type of the valtree once you change this

@rust-log-analyzer

This comment has been minimized.

@reddevilmidzy
Copy link
Member Author

Haha, ICE occurs in other tests...

Copy link
Member Author

@reddevilmidzy reddevilmidzy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your quick review. 😊

View changes since this review

Comment on lines +748 to +756
if preceding_args.is_empty()
&& tcx.type_of(param.def_id).skip_binder().has_param()
{
let guar = self.lowerer.dcx().span_delayed_bug(
self.span,
"default type has params but no args",
);
return Ty::new_error(tcx, guar).into();
}
Copy link
Member Author

@reddevilmidzy reddevilmidzy Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added logic to avoid ICE in https://github.com/rust-lang/rust/blob/main/tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.rs

The change in compiler/rustc_trait_selection/src/traits/wf.rs is for the same reason.

#![feature(adt_const_params)]
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

struct A<const B: () = 1, C>(C);
//~^ ERROR: generic parameters with a default must be trailing
//~| ERROR: mismatched types

struct Cond<const B: bool>;

struct Thing<T = Cond<0>>(T);
//~^ ERROR: mismatched types

impl Thing {}

fn main() {}

Comment on lines 9 to 10
const FREE2: isize = FREE;
//~^ ERROR the constant `5` is not of type `isize`

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this error will go away.

@rust-log-analyzer

This comment has been minimized.

Copy link
Member Author

@reddevilmidzy reddevilmidzy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ten crash tests, the ICE disappeared; however, in tests/crashes/117460.rs, tests/crashes/114212-2.rs and tests/crashes/114212.rs, adding the main function caused the ICE to occur again.

View changes since this review

@@ -0,0 +1,23 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/116554>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This issue was closed; is there a need to add further testing?

@@ -1,14 +0,0 @@
//@ known-bug: #101036
#![feature(generic_const_exprs)]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#101036 was a duplicate of #119824.

@reddevilmidzy
Copy link
Member Author

reddevilmidzy commented Feb 8, 2026

Could the following issues also be closed? 🤔

#119824
#133966
#136416

already closed
#94846
#106473
#116554

@rust-log-analyzer

This comment has been minimized.

Co-authored-by: Boxy <rust@boxyuwu.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ICE]: ty::ConstKind::Error constructed but no error reported ICE: ty::ConstKind::Error constructed but no error reported

4 participants