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
53 changes: 33 additions & 20 deletions compiler/rustc_mir_build/src/builder/expr/as_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,28 +74,41 @@ pub(crate) fn as_constant_inner<'tcx>(
ExprKind::NamedConst { def_id, args, ref user_ty } => {
let user_ty = user_ty.as_ref().and_then(push_cuta);

// Under generic_const_args, `def_id` might be a regular const declared in a trait, but
// is `impl`d as a directly represented const. We do not know whether it is here, so we
// must use type system normalization for all consts under generic_const_args.
// FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses valtrees
// and `Const::Unevaluated` does not, we should revisit this before stabilization.
let def_kind = tcx.def_kind(def_id);
if tcx.features().generic_const_args()
|| matches!(def_kind, DefKind::Const | DefKind::AssocConst)
&& tcx.is_direct_const(def_id)
{
let kind = match def_kind {
DefKind::AssocConst => {
if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(def_id))
{
ty::AliasConstKind::InherentImpl { def_id }
} else {
ty::AliasConstKind::Projection { def_id }
}
let get_kind = |def_id, def_kind| match def_kind {
DefKind::AssocConst => {
if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(def_id)) {
ty::AliasConstKind::InherentImpl { def_id }
} else {
ty::AliasConstKind::Projection { def_id }
}
DefKind::Const => ty::AliasConstKind::Free { def_id },
_ => unreachable!(),
}
DefKind::Const => ty::AliasConstKind::Free { def_id },
kind => bug!("unexpected DefKind in THIR ExprKind::NamedConst: {kind:?}"),
};

let could_be_direct_const = |def_id| {
let def_kind = tcx.def_kind(def_id);
let (DefKind::Const | DefKind::AssocConst) = def_kind else {
Comment thread
BoxyUwU marked this conversation as resolved.
return None;
};
if tcx.is_direct_const(def_id) {
return Some(get_kind(def_id, def_kind));
}
// Under generic_const_args, `def_id` might be a regular const declared in a trait,
// but is `impl`d as a directly represented const. We do not know whether it is
// here, so we must use type system normalization for all const projections.
// FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses
// valtrees and `Const::Unevaluated` does not, we should revisit this before
// stabilization.
if tcx.features().generic_const_args()
&& let kind @ ty::AliasConstKind::Projection { .. } = get_kind(def_id, def_kind)
Comment thread
BoxyUwU marked this conversation as resolved.
{
return Some(kind);
}
None
};

if let Some(kind) = could_be_direct_const(def_id) {
let alias = ty::AliasConst::new(tcx, kind, args);
let ct = ty::Const::new_alias(tcx, ty::IsRigid::No, alias);
let const_ = Const::Ty(ty, ct);
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/const-generics/gca/const-reference-to-constructor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//@ check-pass
//@ compile-flags: -Znext-solver
//! https://github.com/rust-lang/rust/issues/162923
#![feature(min_generic_const_args)]
#![feature(generic_const_args)]
enum T<const N: u8 = { T::<0>::B as u8 }> {
A = 2,
B,
}
fn main() {}
Loading