Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
12 changes: 10 additions & 2 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use super::compare_eii::{compare_eii_function_types, compare_eii_statics};
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
use crate::diagnostics;
use crate::diagnostics::InvalidReceiverTyHint;
use crate::diagnostics::{InvalidReceiverTyHint, ParamInTyOfConstParam};

pub(super) struct WfCheckingCtxt<'a, 'tcx> {
pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,
Expand Down Expand Up @@ -855,7 +855,15 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
let ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();
let span = tcx.def_span(param.def_id);
let def_id = param.def_id.expect_local();

if !tcx.features().generic_const_parameter_types() && ty.has_param() {
let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =
tcx.hir_node_by_def_id(def_id).expect_generic_param().kind
else {
bug!()
};
let err = tcx.dcx().create_err(ParamInTyOfConstParam { span, ty }).emit();
return Err(err);
}
if tcx.features().const_param_ty_unchecked() {
enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
wfcx.register_wf_obligation(span, None, ty.into());
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_hir_analysis/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2000,3 +2000,12 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for UncoveredTyParam<'_> {
diag
}
}

#[derive(Diagnostic)]
#[diag("the type of const parameters must not depend on other generic parameters", code = E0770)]
pub(crate) struct ParamInTyOfConstParam<'tcx> {
#[primary_span]
#[label("the type `{$ty}` must not depend on other generic parameter")]
pub(crate) span: Span,
pub(crate) ty: Ty<'tcx>,
}
5 changes: 4 additions & 1 deletion compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1584,7 +1584,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}

RibKind::ConstParamTy => {

@fmease fmease Jun 16, 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.

IINM you're now accepting this code despite N depending on T which shouldn't be allowed w/o enabling GCPT.

impl<T> Wrap<T> {
    fn f<const N: Self>() {}
}

struct Wrap<T>(T);

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to check if Self depends on generics?

@fmease fmease Jun 18, 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.

I'm not super well-versed in name resolution, so I don't know if there's a good way to do this in rustc_resolve that still nicely leverages the existing rib structure. Boxy probably has an idea.

Calling type_of here on the LocalDefId found in the SelfTyAlias is probably too prone to cycles or hangs; looking at hir_node corresp. to the LocalDefId might be an option but that might not integrate with the visitor.

Naively speaking, I would do it in HIR ty lowering by inspecting the type as returned by type_of and by reusing+generalizing check_assoc_const_binding_type but that's probably also not super ideal. I haven't read a lot of the new mGCA code in HIR ty lowering, maybe there's already a function for that (that's similar to check_assoc_const_binding_type?)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is it okay to check if Self has param in check_param_wf? I saw that we do other checks on const params here, but I think it doesn't belong to the HIR ty lowering process.

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.

we used to have a nice way of handling this and no longer do 😅 previously you could set a flag on the Self to tell hir ty lowering to not support generic parameters on it 🤔

one problem with checking this in HIR ty lowering is we'd not error on this code (probably) due to the fact that the lowered ty wouldn't have the type alias Foo<N> it'd just have Bar... 🤔

#![feature(adt_const_params)]

type Foo<const N: usize> = Bar;

#[derive(Eq, PartialEq, core::marker::ConstParamTy)]
struct Bar;

trait Trait<const N: usize> {
    fn bar<const C: Bar>();
}

impl<const N: usize> Trait<N> for Foo<N> {
    fn bar<const C: Self>() {}
}

i think that's probably just fine... such code will be accepted long term once generic_const_parameter_types is stabilized anyway 🤷‍♀️ though- can you feature gate support for Self under min_adt_const_params/adt_const_params, I don't want to immediately stabilize this but it is something we should just support when stabilizing type aliases here (which we are doing with adt const params)

Is it okay to check if Self has param in check_param_wf?

I would either do this, or do it in fn type_of when lowering the type of const parameters. I think I prefer type_of as you can then return TyKind::Error for the type of the const parameter which should avoid the rest of the compiler needing to handle types of const parameters having generics with GCPT enabled

if !self.features.generic_const_parameter_types() {
// We check whether Self depends on generics parameters during HIR analysis
if !self.features.generic_const_parameter_types()
&& !matches!(res, Res::SelfTyAlias { .. })
{
if let Some(span) = finalize {
self.report_error(
span,
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/resolve/allow-self-in-const-generics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Allow Self in const generics when Self doesn't depends on generics
trait MyTrait {
fn foo<const N: i32>();
}

impl MyTrait for i32 {
fn foo<const N: Self>() {}
}
impl<T> Wrap<T> {
fn f<const N: Self>() {}
//~^ ERROR the type of const parameters must not depend on other generic parameters

}

struct Wrap<T>(T);
fn main(){}
9 changes: 9 additions & 0 deletions tests/ui/resolve/allow-self-in-const-generics.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0770]: the type of const parameters must not depend on other generic parameters
--> $DIR/allow-self-in-const-generics.rs:10:19
|
LL | fn f<const N: Self>() {}
| ^^^^ the type `Wrap<T>` must not depend on other generic parameter

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0770`.
Loading