Skip to content
Merged
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
58 changes: 53 additions & 5 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1415,9 +1415,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let ct = self.check_param_uses_if_mcg(ct, span, false);
Ok(ct)
}
TypeRelativePath::Ctor { ctor_def_id, args } => {
return Ok(ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, ctor_def_id, args)));
}
TypeRelativePath::Ctor { ctor_def_id, args } => match tcx.def_kind(ctor_def_id) {
DefKind::Ctor(_, CtorKind::Fn) => {
Ok(ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, ctor_def_id, args)))
}
DefKind::Ctor(ctor_of, CtorKind::Const) => {
Ok(self.construct_const_ctor_value(ctor_def_id, ctor_of, args))
}
_ => unreachable!(),
},
// FIXME(mgca): implement support for this once ready to support all adt ctor expressions,
// not just const ctors
TypeRelativePath::Variant { .. } => {
Expand Down Expand Up @@ -1452,7 +1458,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// FIXME(mgca): do we want constructor resolutions to take priority over
// other possible resolutions?
if matches!(mode, LowerTypeRelativePathMode::Const)
&& let Some((CtorKind::Fn, ctor_def_id)) = variant_def.ctor
&& let Some((_, ctor_def_id)) = variant_def.ctor
{
tcx.check_stability(variant_def.def_id, Some(qpath_hir_id), span, None);
let _ = self.prohibit_generic_args(
Expand Down Expand Up @@ -2597,14 +2603,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
self.lower_const_param(def_id, hir_id)
}
Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
Res::Def(DefKind::Const, did) => {
assert_eq!(opt_self_ty, None);
let [leading_segments @ .., segment] = path.segments else { bug!() };
let _ = self
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
let args = self.lower_generic_args_of_path_segment(span, did, segment);
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
}
Res::Def(DefKind::Ctor(ctor_of, CtorKind::Const), did) => {
assert_eq!(opt_self_ty, None);
let [leading_segments @ .., segment] = path.segments else { bug!() };
let _ = self
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);

let parent_did = tcx.parent(did);
let generics_did = match ctor_of {
CtorOf::Variant => tcx.parent(parent_did),
CtorOf::Struct => parent_did,
};
let args = self.lower_generic_args_of_path_segment(span, generics_did, segment);

self.construct_const_ctor_value(did, ctor_of, args)
}
Res::Def(DefKind::Ctor(_, CtorKind::Fn), did) => {
assert_eq!(opt_self_ty, None);
let [leading_segments @ .., segment] = path.segments else { bug!() };
Expand Down Expand Up @@ -3174,4 +3195,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
Some(r)
}

fn construct_const_ctor_value(
&self,
ctor_def_id: DefId,
ctor_of: CtorOf,
args: GenericArgsRef<'tcx>,
) -> Const<'tcx> {
let tcx = self.tcx();
let parent_did = tcx.parent(ctor_def_id);

let adt_def = tcx.adt_def(match ctor_of {
CtorOf::Variant => tcx.parent(parent_did),
CtorOf::Struct => parent_did,
});

let variant_idx = adt_def.variant_index_with_id(parent_did);

let valtree = if adt_def.is_enum() {
let discr = ty::ValTree::from_scalar_int(tcx, variant_idx.as_u32().into());
ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, discr, tcx.types.u32)])
} else {
ty::ValTree::zst(tcx)
};

let adt_ty = Ty::new_adt(tcx, adt_def, args);
ty::Const::new_value(tcx, valtree, adt_ty)
}
}
17 changes: 0 additions & 17 deletions tests/crashes/132985.rs

This file was deleted.

7 changes: 0 additions & 7 deletions tests/crashes/136138.rs

This file was deleted.

10 changes: 0 additions & 10 deletions tests/crashes/139596.rs

This file was deleted.

16 changes: 0 additions & 16 deletions tests/crashes/mgca/ace-with-const-ctor.rs

This file was deleted.

20 changes: 20 additions & 0 deletions tests/rustdoc/constant/ice-associated-const-equality-105952.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/105952>

#![crate_name = "foo"]
#![feature(min_generic_const_args, adt_const_params)]
#![expect(incomplete_features)]
use std::marker::ConstParamTy;

#[derive(PartialEq, Eq, ConstParamTy)]
pub enum ParseMode {
Raw,
}
pub trait Parse {
#[type_const]
const PARSE_MODE: ParseMode;
}
pub trait RenderRaw {}

//@ hasraw foo/trait.RenderRaw.html 'impl'
//@ hasraw foo/trait.RenderRaw.html 'ParseMode::Raw'
impl<T: Parse<PARSE_MODE = { ParseMode::Raw }>> RenderRaw for T {}
19 changes: 19 additions & 0 deletions tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#![feature(min_generic_const_args, adt_const_params)]
#![expect(incomplete_features)]
use std::marker::ConstParamTy;

#[derive(ConstParamTy, PartialEq, Eq)]
struct U;

#[derive(ConstParamTy, PartialEq, Eq)]
//~^ ERROR overflow evaluating the requirement `S<U> well-formed`
//~| ERROR overflow evaluating the requirement `S<U> well-formed`

struct S<const N: U>()
where
S<{ U }>:;
//~^ ERROR overflow evaluating the requirement `S<U> well-formed`
//~| ERROR overflow evaluating the requirement `S<U> well-formed`
//~| ERROR overflow evaluating the requirement `S<U> well-formed`

fn main() {}
80 changes: 80 additions & 0 deletions tests/ui/const-generics/mgca/const-ctor-overflow-eval.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | S<{ U }>:;
| ^^^^^^^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`

error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | S<{ U }>:;
| ^^^^^^^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | S<{ U }>:;
| ^^^^^^^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:8:24
|
LL | #[derive(ConstParamTy, PartialEq, Eq)]
| ^^^^^^^^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`

error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:8:35
|
LL | #[derive(ConstParamTy, PartialEq, Eq)]
| ^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0275`.
19 changes: 19 additions & 0 deletions tests/ui/const-generics/mgca/const-ctor-with-error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// to ensure it does not ices like before

#![feature(min_generic_const_args, adt_const_params)]
#![expect(incomplete_features)]
use std::marker::ConstParamTy;

#[derive(ConstParamTy, PartialEq, Eq)]
enum Option<T> {
#[allow(dead_code)]
Some(T),
None,
}

fn pass_enum<const P: Option<u32>>() {}

fn main() {
pass_enum::<{ None }>();
//~^ ERROR missing generics for enum `std::option::Option`
}
14 changes: 14 additions & 0 deletions tests/ui/const-generics/mgca/const-ctor-with-error.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0107]: missing generics for enum `std::option::Option`
--> $DIR/const-ctor-with-error.rs:17:19
|
LL | pass_enum::<{ None }>();
| ^^^^ expected 1 generic argument
|
help: add missing generic argument
|
LL | pass_enum::<{ None<T> }>();
| +++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0107`.
49 changes: 49 additions & 0 deletions tests/ui/const-generics/mgca/const-ctor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/139596>
//! <https://github.com/rust-lang/rust/issues/136138>
//! <https://github.com/rust-lang/rust/issues/132985>

//@ check-pass

#![feature(
min_generic_const_args,
adt_const_params,
generic_const_parameter_types,
unsized_const_params
)]
#![expect(incomplete_features)]
use std::marker::{ConstParamTy, ConstParamTy_};
#[derive(ConstParamTy, PartialEq, Eq)]
struct Colour;

#[derive(ConstParamTy, PartialEq, Eq)]
enum A {
B,
}

#[derive(ConstParamTy, PartialEq, Eq)]
enum MyOption<T> {
#[allow(dead_code)]
Some(T),
None,
}

#[derive(ConstParamTy, PartialEq, Eq)]
struct Led<const C: Colour>;

#[derive(Eq, PartialEq, ConstParamTy)]
struct Foo<const N: usize>;

fn pass_enum<const P: MyOption<u32>>() {}

fn accepts_foo<const N: usize, const M: Foo<N>>() {}

fn accepts_bar<T: ConstParamTy_, const B: MyOption<T>>() {}

fn test<T: ConstParamTy_, const N: usize>() {
accepts_foo::<N, { Foo::<N> }>();
accepts_bar::<T, { MyOption::None::<T> }>();
}

fn main() {
Led::<{ Colour }>;
}
Loading