Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
return GenericArg::Infer(hir::InferArg {
hir_id: self.lower_node_id(ty.id),
span: self.lower_span(ty.span),
kind: hir::InferArgKind::TypeOrConst,
});
}

Expand Down Expand Up @@ -1471,13 +1472,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
Err(e) => e.emit(self),
};
let ct = self.arena.alloc(ct);
// note: this allows direct_const_arg!(_) to be inferred to a type. a little
// wonky.
return match ct.try_as_ambig_ct() {
Some(ct) => GenericArg::Const(ct),
None => GenericArg::Infer(hir::InferArg {
hir_id: ct.hir_id,
span: ct.span,
kind: hir::InferArgKind::Const,
}),
};
}
Expand All @@ -1489,7 +1489,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ct = self.lower_anon_const_to_const_arg_and_alloc(ct);
match ct.try_as_ambig_ct() {
Some(ct) => GenericArg::Const(ct),
None => GenericArg::Infer(hir::InferArg { hir_id: ct.hir_id, span: ct.span }),
None => GenericArg::Infer(hir::InferArg {
hir_id: ct.hir_id,
span: ct.span,
kind: hir::InferArgKind::Const,
}),
}
}
}
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,11 +547,18 @@ pub struct ConstArgArrayExpr<'hir> {
pub elems: &'hir [&'hir ConstArg<'hir>],
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, StableHash)]
pub enum InferArgKind {
TypeOrConst,
Const,
}

@khyperia khyperia Aug 13, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe a short comment here, explaining the purpose of this, if there's no other comment elsewhere in code - "S::<_> is allowed to infer to either a type or a const, but S::<{ _ }> must infer to a constant, so this tracks that" kind of thing, idk exact phrasing. just, having concrete examples of "why is this a thing / when does it happen" is super useful for me personally when reading code!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added a short description.


#[derive(Clone, Copy, Debug, StableHash)]
pub struct InferArg {
#[stable_hash(ignore)]
pub hir_id: HirId,
pub span: Span,
pub kind: InferArgKind,
}

impl InferArg {
Expand Down Expand Up @@ -601,7 +608,8 @@ impl GenericArg<'_> {
GenericArg::Lifetime(_) => "lifetime",
GenericArg::Type(_) => "type",
GenericArg::Const(_) => "constant",
GenericArg::Infer(_) => "placeholder",
GenericArg::Infer(InferArg { kind: InferArgKind::TypeOrConst, .. }) => "placeholder",
GenericArg::Infer(InferArg { kind: InferArgKind::Const, .. }) => "constant",
}
}

Expand Down Expand Up @@ -5142,7 +5150,7 @@ mod size_asserts {
static_assert_size!(FnDecl<'_>, 40);
static_assert_size!(ForeignItem<'_>, 88);
static_assert_size!(ForeignItemKind<'_>, 56);
static_assert_size!(GenericArg<'_>, 16);
static_assert_size!(GenericArg<'_>, 24);
static_assert_size!(GenericBound<'_>, 64);
static_assert_size!(Generics<'_>, 56);
static_assert_size!(Impl<'_>, 48);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(
GenericArg::Type(ty) => visitor.visit_ty(ty),
GenericArg::Const(ct) => visitor.visit_const_arg(ct),
GenericArg::Infer(inf) => {
let InferArg { hir_id, span } = inf;
let InferArg { hir_id, span, kind: _ } = inf;
visitor.visit_infer(*hir_id, *span, InferKind::Ambig(inf))
}
}
Expand Down Expand Up @@ -1446,7 +1446,7 @@ pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) -> V::R
}

pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) -> V::Result {
let InferArg { hir_id, span: _ } = inf;
let InferArg { hir_id, span: _, kind: _ } = inf;
visitor.visit_id(*hir_id)
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
"synthetic HIR should have its `generics_of` explicitly fed"
),

Node::ConstArg(..) => {
Node::ConstArg(..) | Node::Infer(hir::InferArg { kind: hir::InferArgKind::Const, .. }) => {
// These can show up in mGCA when representing "direct" const arguments. The
// DefCollector cannot know whether an anon const will be represented by an actual HIR
// Node::AnonConst, or whether it will be represented directly, so it must generate a
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,11 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
match (arg, &param.kind, arg_count.explicit_late_bound) {
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
| (
GenericArg::Type(_) | GenericArg::Infer(_),
GenericArg::Type(_)
| GenericArg::Infer(hir::InferArg {
kind: hir::InferArgKind::TypeOrConst,
..
}),
GenericParamDefKind::Type { .. },
_,
)
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1428,7 +1428,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// anywhere so we don't need to encode it for other crates.
// FIXME(mgca): This probably isn't true, they probably are accessed, but, test case?
if def_kind == DefKind::AnonConst
&& matches!(tcx.hir_node_by_def_id(local_id), hir::Node::ConstArg(_))
&& matches!(
tcx.hir_node_by_def_id(local_id),
hir::Node::ConstArg(_)
| hir::Node::Infer(hir::InferArg { kind: hir::InferArgKind::Const, .. })
)
{
continue;
}
Expand Down
23 changes: 23 additions & 0 deletions tests/ui/const-generics/mgca/braced-const-infer-in-body.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//! Regression test for: https://github.com/rust-lang/rust/issues/160798
#![crate_type = "lib"]
#![feature(min_generic_const_args)]
#![feature(macroless_generic_const_args)]

trait Trait<T> {}

impl Trait<i32> for i32 {}

struct S<const N: usize>;

fn main() {
// Const-only infer args used for a type parameter are rejected.
let _z: &[&dyn Trait<{ _ }>] = &[&0i32];
//~^ ERROR: constant provided when a type was expected
let _y: &dyn Trait<core::direct_const_arg!(_)> = &0i32;
//~^ ERROR: constant provided when a type was expected

let _a: S<{ _ }> = S::<3>;
let _b: S<core::direct_const_arg!(_)> = S::<3>;
let _c: S<{ core::direct_const_arg!(_) }> = S::<3>;
let _d: S<_> = S::<3>;
}
15 changes: 15 additions & 0 deletions tests/ui/const-generics/mgca/braced-const-infer-in-body.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0747]: constant provided when a type was expected
--> $DIR/braced-const-infer-in-body.rs:14:28
|
LL | let _z: &[&dyn Trait<{ _ }>] = &[&0i32];
| ^

error[E0747]: constant provided when a type was expected
--> $DIR/braced-const-infer-in-body.rs:16:48
|
LL | let _y: &dyn Trait<core::direct_const_arg!(_)> = &0i32;
| ^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0747`.
2 changes: 1 addition & 1 deletion tests/ui/const-generics/mgca/braced-const-infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

trait Trait<T> {}

impl dyn Trait<{_}> {} //~ ERROR: the placeholder `_` is not allowed within types on item signatures
impl dyn Trait<{_}> {} //~ ERROR: constant provided when a type was expected

fn main() {}
6 changes: 3 additions & 3 deletions tests/ui/const-generics/mgca/braced-const-infer.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations
error[E0747]: constant provided when a type was expected
--> $DIR/braced-const-infer.rs:7:17
|
LL | impl dyn Trait<{_}> {}
| ^ not allowed in type signatures
| ^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0121`.
For more information about this error, try `rustc --explain E0747`.
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//@ check-pass
//! It is very weird and mostly a compiler implementation quirk that direct_const_arg!(_) is allowed
//! to infer to a type rather than forcing it to be a constant. This test simply tracks/asserts the
//! current behavior.
//! `direct_const_arg!(_)` used to be allowed to infer to a type as a compiler
//! implementation quirk. Since it uses explicit const argument syntax,
//! it is now rejected when passed as a type argument
#![feature(min_generic_const_args)]

struct S<T>(T);

fn main() {
let _: S<core::direct_const_arg!(_)> = S(2u32);
//~^ ERROR: constant provided when a type was expected
let _: S<{ core::direct_const_arg!(_) }> = S(2u32);
//~^ ERROR: constant provided when a type was expected
}
15 changes: 15 additions & 0 deletions tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0747]: constant provided when a type was expected
--> $DIR/direct_const_arg-infer-as-type.rs:9:38
|
LL | let _: S<core::direct_const_arg!(_)> = S(2u32);
| ^

error[E0747]: constant provided when a type was expected
--> $DIR/direct_const_arg-infer-as-type.rs:11:40
|
LL | let _: S<{ core::direct_const_arg!(_) }> = S(2u32);
| ^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0747`.
5 changes: 3 additions & 2 deletions tests/ui/const-generics/mgca/macro-const-arg-infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#![allow(incomplete_features)]
macro_rules! y {
( $($matcher:tt)*) => {
_ //~ ERROR: the placeholder `_` is not allowed within types on item signatures
_ //~ ERROR: constant provided when a type was expected
//~^ ERROR: the placeholder `_` is not allowed within types on item signatures
};
}

Expand All @@ -15,6 +16,6 @@ const y: A<
x
}
},
> = 1; //~ ERROR: mismatched types
> = 1;

fn main() {}
25 changes: 10 additions & 15 deletions tests/ui/const-generics/mgca/macro-const-arg-infer.stderr
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
error[E0392]: type parameter `T` is never used
--> $DIR/macro-const-arg-infer.rs:10:10
--> $DIR/macro-const-arg-infer.rs:11:10
|
LL | struct A<T>;
| ^ unused type parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead

error[E0308]: mismatched types
--> $DIR/macro-const-arg-infer.rs:18:5
error[E0747]: constant provided when a type was expected
--> $DIR/macro-const-arg-infer.rs:6:9
|
LL | const y: A<
| __________-
LL | | {
LL | | y! {
LL | _
| ^
...
LL | / y! {
LL | | x
LL | | }
LL | | },
LL | | > = 1;
| | - ^ expected `A<_>`, found integer
| |_|
| expected because of the type of the constant
| |_________- in this macro invocation
|
= note: expected struct `A<_>`
found type `{integer}`
= note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
--> $DIR/macro-const-arg-infer.rs:6:9
Expand All @@ -40,5 +35,5 @@ LL | | }

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0121, E0308, E0392.
Some errors have detailed explanations: E0121, E0392, E0747.
For more information about an error, try `rustc --explain E0121`.
8 changes: 4 additions & 4 deletions tests/ui/stats/input-stats.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,22 @@ hir-stats Stmt 96 (NN.N%) 3 32
hir-stats - Expr 32 (NN.N%) 1
hir-stats - Let 32 (NN.N%) 1
hir-stats - Semi 32 (NN.N%) 1
hir-stats GenericArg 96 (NN.N%) 4 24
hir-stats - Type 24 (NN.N%) 1
hir-stats - Lifetime 72 (NN.N%) 3
hir-stats Arm 80 (NN.N%) 2 40
hir-stats WherePredicate 72 (NN.N%) 3 24
hir-stats - BoundPredicate 72 (NN.N%) 3
hir-stats InlineAsm 72 (NN.N%) 1 72
hir-stats Body 72 (NN.N%) 3 24
hir-stats Param 64 (NN.N%) 2 32
hir-stats Local 64 (NN.N%) 1 64
hir-stats GenericArg 64 (NN.N%) 4 16
hir-stats - Type 16 (NN.N%) 1
hir-stats - Lifetime 48 (NN.N%) 3
hir-stats ExprField 40 (NN.N%) 1 40
hir-stats Mod 32 (NN.N%) 1 32
hir-stats Lifetime 28 (NN.N%) 1 28
hir-stats TraitItemId 8 (NN.N%) 2 4
hir-stats ImplItemId 8 (NN.N%) 2 4
hir-stats ForeignItemId 4 (NN.N%) 1 4
hir-stats ----------------------------------------------------------------
hir-stats Total 8_592 172
hir-stats Total 8_624 172
hir-stats ================================================================
Loading