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
20 changes: 17 additions & 3 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,9 +775,23 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
if has_default {
// need to store default and type of default
let ct = tcx.const_param_default(param.def_id).skip_binder();
if let ty::ConstKind::Alias(_, alias_const) = ct.kind()
&& let Some(def_id) = alias_const.kind.opt_def_id()
{
if let ty::ConstKind::Alias(_, alias_const) = ct.kind() {
let def_id = match alias_const.kind {
ty::AliasConstKind::Projection { def_id } => def_id,
ty::AliasConstKind::InherentSelf { def_id } => {
// NOTE: typically, InherentSelf is illegal to pass to type_of,
// because the generic args are incorrect (type_of expects impl-form
// arguments). However, we are just checking ensure_ok().type_of(),
// we are not instantiating the result, so it's OK here.
def_id
}
ty::AliasConstKind::InherentImpl { .. } => span_bug!(
tcx.def_span(param.def_id),
"const_param_default should return an unnormalized constant, which should always be InherentSelf, not InherentImpl"
),
ty::AliasConstKind::Free { def_id } => def_id,
ty::AliasConstKind::Anon { def_id } => def_id,
};
tcx.ensure_ok().type_of(def_id);
}
}
Expand Down
48 changes: 24 additions & 24 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1480,9 +1480,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
)? {
TypeRelativePath::AssocItem(alias_term) => {
let alias_ct = alias_term.expect_ct();
if let Some(def_id) = alias_ct.kind.opt_def_id() {
self.check_const_item_in_type_system(def_id, span)?;
}
self.check_const_item_in_type_system(alias_ct.kind, span)?;
let ct = Const::new_alias(tcx, ty::IsRigid::No, alias_ct);
let ct = self.check_param_uses_if_mcg(ct, span, false);
Ok(ct)
Expand Down Expand Up @@ -1948,13 +1946,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
item_segment,
ty::AssocTag::Const,
)?;
self.check_const_item_in_type_system(item_def_id, span)?;
let alias_const = ty::AliasConst::new(
tcx,
ty::AliasConstKind::Projection { def_id: item_def_id },
item_args,
);
Ok(Const::new_alias(tcx, ty::IsRigid::No, alias_const))
let kind = ty::AliasConstKind::Projection { def_id: item_def_id };
self.check_const_item_in_type_system(kind, span)?;
let alias = ty::AliasConst::new(tcx, kind, item_args);
Ok(Const::new_alias(tcx, ty::IsRigid::No, alias))
}

/// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path.
Expand Down Expand Up @@ -2879,7 +2874,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
self.lower_const_param(def_id, hir_id)
}
Res::Def(DefKind::Const, did) => {
if let Err(guar) = self.check_const_item_in_type_system(did, span) {
let kind = ty::AliasConstKind::Free { def_id: did };
if let Err(guar) = self.check_const_item_in_type_system(kind, span) {
return Const::new_error(self.tcx(), guar);
}

Expand All @@ -2888,11 +2884,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
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_alias(
tcx,
ty::IsRigid::No,
ty::AliasConst::new(tcx, ty::AliasConstKind::Free { def_id: did }, args),
)
let alias = ty::AliasConst::new(tcx, kind, args);
ty::Const::new_alias(tcx, ty::IsRigid::No, alias)
}
Res::Def(kind @ DefKind::Ctor(ctor_of, CtorKind::Const), did) => {
assert_eq!(opt_self_ty, None);
Expand Down Expand Up @@ -3126,18 +3119,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// `def_id` is a const item used in the type system. Checks if that's OK.
fn check_const_item_in_type_system(
&self,
def_id: DefId,
alias_const: ty::AliasConstKind<'tcx>,
span: Span,
) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx();
if tcx.features().generic_const_args() || tcx.is_direct_const(def_id) {
if tcx.features().generic_const_args() || alias_const.is_direct_const(tcx) {
Ok(())
} else {
let mut err = self
.dcx()
.struct_span_err(span, "use of `const` in the type system not marked as direct");
if let Some(local_def_id) = def_id.as_local() {
if let Some(body_id) = tcx.hir_node_by_def_id(local_def_id).body_id() {
let hir_node = match alias_const {
ty::AliasConstKind::Projection { def_id }
| ty::AliasConstKind::InherentSelf { def_id }
| ty::AliasConstKind::InherentImpl { def_id }
| ty::AliasConstKind::Free { def_id }
| ty::AliasConstKind::Anon { def_id } => {
def_id.as_local().map(|id| tcx.hir_node_by_def_id(id))
}
};
if let Some(hir_node) = hir_node {
if let Some(body_id) = hir_node.body_id() {
let body_span = tcx.hir_body(body_id).value.span;

err.multipart_suggestion(
Expand All @@ -3148,10 +3150,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
],
Applicability::MaybeIncorrect,
);
} else if let DefKind::AssocConst = tcx.def_kind(def_id)
&& let DefKind::Trait = tcx.def_kind(tcx.parent(def_id))
{
let node = tcx.hir_node_by_def_id(local_def_id).expect_trait_item();
} else if let ty::AliasConstKind::Projection { .. } = alias_const {
let node = hir_node.expect_trait_item();
let sp = node.span.shrink_to_lo();
err.span_suggestion_verbose(
sp,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ pub struct PatExtra<'tcx> {
///
/// This is used by some diagnostics for non-exhaustive matches, to map
/// the pattern node back to the `DefId` of its original constant.
pub expanded_const: Option<DefId>,
pub expanded_const: Option<ty::AliasConstKind<'tcx>>,

/// User-written types that must be preserved into MIR so that they can be
/// checked.
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_middle/src/ty/abstract_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,14 @@ impl<'tcx> TyCtxt<'tcx> {
}
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
let ct = match c.kind() {
ty::ConstKind::Alias(_, alias_const)
if let Some(def_id) = alias_const.kind.opt_def_id() =>
{
ty::ConstKind::Alias(_, alias_const) => {
let def_id = match alias_const.kind {
ty::AliasConstKind::Projection { def_id }
| ty::AliasConstKind::InherentSelf { def_id }
| ty::AliasConstKind::InherentImpl { def_id }
| ty::AliasConstKind::Free { def_id }
| ty::AliasConstKind::Anon { def_id } => def_id,
};
match self.tcx.thir_abstract_const(def_id) {
Err(e) => ty::Const::new_error(self.tcx, e),
Ok(Some(bac)) => {
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1229,8 +1229,7 @@ fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx>
// The pattern must be a named constant, and the name that appears in
// the pattern's source text must resemble a plain identifier without any
// `::` namespace separators or other non-identifier characters.
if let Some(def_id) = try { pat.extra.as_deref()?.expanded_const? }
&& tcx.def_kind(def_id) == DefKind::Const
if let ty::AliasConstKind::Free { def_id } = pat.extra.as_deref()?.expanded_const?
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(pat.span)
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
{
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ impl<'tcx> ConstToPat<'tcx> {

// Mark the pattern to indicate that it is the result of lowering a named
// constant. This is used for diagnostics.
thir_pat.extra.get_or_insert_default().expanded_const = alias_const.kind.opt_def_id();
thir_pat.extra.get_or_insert_default().expanded_const = Some(alias_const.kind);
thir_pat
}

Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_public/src/unstable/convert/stable/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,9 +557,13 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
}
ty::ConstKind::Param(param) => crate::ty::TyConstKind::Param(param.stable(tables, cx)),
ty::ConstKind::Alias(_, alias_const) => {
let Some(def_id) = alias_const.kind.opt_def_id() else {
// FIXME: implement (both AliasTy and AliasConst will be needing this soon)
panic!("non-defid alias consts are not supported by rustc_public at the moment")
// rustc_public must change its API once we introduce a variant without a def_id.
let def_id = match alias_const.kind {
ty::AliasConstKind::Projection { def_id }
| ty::AliasConstKind::InherentSelf { def_id }
| ty::AliasConstKind::InherentImpl { def_id }
| ty::AliasConstKind::Free { def_id }
| ty::AliasConstKind::Anon { def_id } => def_id,
};
crate::ty::TyConstKind::Unevaluated(
tables.const_def(def_id),
Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_type_ir/src/const_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,6 @@ impl<I: Interner> AliasConstKind<I> {
AliasConstKind::Anon { def_id } => interner.def_span(def_id.into()),
}
}

pub fn opt_def_id(self) -> Option<I::DefId> {
match self {
AliasConstKind::Projection { def_id } => Some(def_id.into()),
AliasConstKind::InherentSelf { def_id } => Some(def_id.into()),
AliasConstKind::InherentImpl { def_id } => Some(def_id.into()),
AliasConstKind::Free { def_id } => Some(def_id.into()),
AliasConstKind::Anon { def_id } => Some(def_id.into()),
}
}
}

rustc_index::newtype_index! {
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/const-generics/mgca/inherent-alias-default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ check-pass
//! rustc_hir_analysis::check_item_type does type_of() on the default value. This is wonky, because
//! the generic args are in Self format at that point, not in impl format, so the result can't be
//! used with the Self-format args. However, it does not instantiate the result, it just does
//! ensure_ok(). This test just makes sure that codepath is hit in tests.
#![feature(min_generic_const_args, inherent_associated_types)]

struct Struct<T1, T2, T3>(T1, T2, T3);
impl<T1, T2, T3> Struct<T1, T2, T3> {
const INHERENT: usize = core::direct_const_arg!(2);
}

struct WithDefault<const N: usize = { core::direct_const_arg!(Struct::<u8, u16, u32>::INHERENT) }>;

fn main() {}
4 changes: 3 additions & 1 deletion tests/ui/thir-print/str-patterns.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ Thir {
extra: Some(
PatExtra {
expanded_const: Some(
DefId(0:4 ~ str_patterns[fc71]::CONSTANT),
Free {
def_id: DefId(0:4 ~ str_patterns[fc71]::CONSTANT),
},
),
ascriptions: [],
},
Expand Down
Loading