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
48 changes: 35 additions & 13 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2672,19 +2672,41 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> hir::ConstItemRhs<'hir> {
match (body, kind) {
(body, ConstItemKind::Body) => {

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.

In the long tail of history I suppose we wont have a ConstItemKind to match on because they'll all be the same kind?

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.

correct, ConstItemKind gets nuked, and this method, lower_const_item_rhs, will only be this arm of this match statement.

hir::ConstItemRhs::Body(self.lower_const_body(span, body.as_deref()))
}
(Some(body), ConstItemKind::TypeConst) => {
hir::ConstItemRhs::TypeConst(self.arena.alloc(
match self.can_lower_expr_to_const_arg_direct(
&body,
DirectConstArgContext::MacrolessMinGenericConstArgs,
) {
Ok(()) => self.lower_expr_to_const_arg_direct(&body, None),
Err(err) => err.emit(self),
},
))
let is_direct = |body| {
if self.tcx.features().macroless_generic_const_args() {
self.can_lower_expr_to_const_arg_direct(
body,
DirectConstArgContext::MacrolessMinGenericConstArgs,
)
.is_ok()
} else {
// do not check can_lower_expr_to_const_arg_direct, but rather just
// ExprKind::DirectConstArg, because we don't want e.g.
// `impl<const N: u8> { const C: u8 = N; }` to be a direct-rhs const
matches!(body, Expr { kind: ExprKind::DirectConstArg(_), .. })
}
};
// N.B.: the feature gate for this is generic_const_args, not min_generic_const_args
if self.tcx.features().generic_const_args()
&& let Some(body) = body
&& is_direct(body)
{
hir::ConstItemRhs::Direct(
self.arena.alloc(self.lower_expr_to_const_arg_direct(&body, None)),
)
} else {
hir::ConstItemRhs::Body(self.lower_const_body(span, body.as_deref()))
}
}
(Some(body), ConstItemKind::TypeConst) => hir::ConstItemRhs::Direct(self.arena.alloc(
match self.can_lower_expr_to_const_arg_direct(
&body,
DirectConstArgContext::MacrolessMinGenericConstArgs,
) {
Ok(()) => self.lower_expr_to_const_arg_direct(&body, None),
Err(err) => err.emit(self),
},
)),
(None, ConstItemKind::TypeConst) => {
let const_arg = ConstArg {
hir_id: self.next_id(),
Expand All @@ -2693,7 +2715,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
),
span: DUMMY_SP,
};
hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg))
hir::ConstItemRhs::Direct(self.arena.alloc(const_arg))
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,15 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
typing_env: ty::TypingEnv<'tcx>,
) -> Result<R, ErrorHandled> {
let def = cid.instance.def.def_id();
// `type const` don't have bodys
debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def);
// directly represented consts don't have bodies
if cfg!(debug_assertions)
&& matches!(tcx.def_kind(def), DefKind::Const { .. } | DefKind::AssocConst { .. })
{
debug_assert!(
tcx.const_of_item(def).is_none(),
"CTFE tried to evaluate directly represented const item: {def:?}"
);
}

let is_static = tcx.is_static(def);
let mut ecx = InterpCx::new(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,21 +416,21 @@ impl<'hir> PathSegment<'hir> {
#[derive(Clone, Copy, Debug, StableHash)]
pub enum ConstItemRhs<'hir> {
Body(BodyId),
TypeConst(&'hir ConstArg<'hir>),
Direct(&'hir ConstArg<'hir>),
}

impl<'hir> ConstItemRhs<'hir> {
pub fn hir_id(&self) -> HirId {
match self {
ConstItemRhs::Body(body_id) => body_id.hir_id,
ConstItemRhs::TypeConst(ct_arg) => ct_arg.hir_id,
ConstItemRhs::Direct(ct_arg) => ct_arg.hir_id,
}
}

pub fn span<'tcx>(&self, tcx: impl crate::intravisit::HirTyCtxt<'tcx>) -> Span {
match self {
ConstItemRhs::Body(body_id) => tcx.hir_body(*body_id).value.span,
ConstItemRhs::TypeConst(ct_arg) => ct_arg.span,
ConstItemRhs::Direct(ct_arg) => ct_arg.span,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,7 @@ pub fn walk_const_item_rhs<'v, V: Visitor<'v>>(
) -> V::Result {
match ct_rhs {
ConstItemRhs::Body(body_id) => visitor.visit_nested_body(body_id),
ConstItemRhs::TypeConst(const_arg) => visitor.visit_const_arg_unambig(const_arg),
ConstItemRhs::Direct(const_arg) => visitor.visit_const_arg_unambig(const_arg),
}
}

Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -953,10 +953,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
tcx.require_lang_item(LangItem::Sized, ty_span),
);
check_where_clauses(wfcx, def_id);

if tcx.is_type_const(def_id) {
wfcheck::check_type_const(wfcx, def_id, ty, true)?;
}
wfcheck::check_const_item(wfcx, def_id, ty);
Ok(())
}));

Expand Down
13 changes: 4 additions & 9 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2157,23 +2157,18 @@ fn compare_type_const<'tcx>(
impl_const_item: ty::AssocItem,
trait_const_item: ty::AssocItem,
) -> Result<(), ErrorGuaranteed> {
let impl_is_type_const = tcx.is_type_const(impl_const_item.def_id);
let trait_type_const_span = tcx.type_const_span(trait_const_item.def_id);
let impl_is_type_const = tcx.is_type_const_syntax(impl_const_item.def_id);
let trait_is_type_const = tcx.is_type_const_syntax(trait_const_item.def_id);

if let Some(trait_type_const_span) = trait_type_const_span
&& !impl_is_type_const
{
if trait_is_type_const && !impl_is_type_const {
return Err(tcx
.dcx()
.struct_span_err(
tcx.def_span(impl_const_item.def_id),
"implementation of a `type const` must also be marked as `type const`",
)
.with_span_note(
MultiSpan::from_spans(vec![
tcx.def_span(trait_const_item.def_id),
trait_type_const_span,
]),
tcx.def_span(trait_const_item.def_id),
"trait declaration of const is marked as `type const`",
)
.emit());
Expand Down
21 changes: 8 additions & 13 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,13 +929,9 @@ pub(crate) fn check_associated_item(
let ty = tcx.type_of(def_id).instantiate_identity();
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
check_const_item(wfcx, def_id, ty);

let has_value = item.defaultness(tcx).has_value();
if tcx.is_type_const(def_id) {
check_type_const(wfcx, def_id, ty, has_value)?;
}

if has_value {
if item.defaultness(tcx).has_value() {
let code = ObligationCauseCode::SizedConstOrStatic;
wfcx.register_bound(
ObligationCause::new(span, def_id, code),
Expand Down Expand Up @@ -1264,17 +1260,17 @@ pub(crate) fn check_static_item<'tcx>(
})
}

/// Runs checks common to both free consts and associated consts
#[instrument(level = "debug", skip(wfcx))]
pub(super) fn check_type_const<'tcx>(
pub(super) fn check_const_item<'tcx>(
wfcx: &WfCheckingCtxt<'_, 'tcx>,
def_id: LocalDefId,
item_ty: Ty<'tcx>,
has_value: bool,
) -> Result<(), ErrorGuaranteed> {

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.

why yeet the Result?

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.

no reason, there was no ? or return Err or anything in this method, we were always returning Ok(()), so why not yeet Result

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.

oh lmao

) {
let tcx = wfcx.tcx();
let span = tcx.def_span(def_id);

if !tcx.features().const_param_ty_unchecked() {
if tcx.is_direct_const(def_id.into()) && !tcx.features().const_param_ty_unchecked() {
wfcx.register_bound(
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),
wfcx.param_env,
Expand All @@ -1283,8 +1279,8 @@ pub(super) fn check_type_const<'tcx>(
);
}

if has_value {
let raw_ct = tcx.const_of_item(def_id).instantiate_identity();
if let Some(direct_rhs) = tcx.const_of_item(def_id) {
let raw_ct = direct_rhs.instantiate_identity();
let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct);
wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into());

Expand All @@ -1295,7 +1291,6 @@ pub(super) fn check_type_const<'tcx>(
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)),
));
}
Ok(())
}

#[instrument(level = "debug", skip(tcx, impl_))]
Expand Down
31 changes: 15 additions & 16 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1804,25 +1804,24 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin
fn const_of_item<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
) -> Option<ty::EarlyBinder<'tcx, Const<'tcx>>> {
let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(_, ct), .. }) => {
ct.expect("no default value for trait assoc const")
}
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
_ => {
span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
hir::Node::Item(&hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => ct,
hir::Node::TraitItem(&hir::TraitItem {
kind: hir::TraitItemKind::Const(_, ct), ..
}) => ct?,
hir::Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => ct,
node => {
span_bug!(
tcx.def_span(def_id),
"`const_of_item` expected a const or assoc const item, got {node:?}"
)
}
};
let ct_arg = match ct_rhs {
hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
hir::ConstItemRhs::Direct(ct_arg) => ct_arg,
hir::ConstItemRhs::Body(_) => {
let e = tcx.dcx().span_delayed_bug(
tcx.def_span(def_id),
"cannot call const_of_item on a non-type_const",
);
return ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e));
return None;
}
};
let icx = ItemCtxt::new(tcx, def_id);
Expand All @@ -1834,8 +1833,8 @@ fn const_of_item<'tcx>(
if let Err(e) = icx.check_tainted_by_errors()
&& !ct.references_error()
{
ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e))
Some(ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e)))
} else {
ty::EarlyBinder::bind(tcx, ct)
Some(ty::EarlyBinder::bind(tcx, ct))
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/clauses_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ fn const_evaluatable_clauses_of<'tcx>(
}

// Skip type consts as mGCA doesn't support evaluatable clauses.
if alias_const.kind.is_type_const(self.tcx) {
if alias_const.kind.is_direct_const(self.tcx) {
return;
}

Expand Down
50 changes: 31 additions & 19 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
TraitItemKind::Const(ty, rhs) => rhs
.and_then(|rhs| {
ty.is_suggestable_infer_ty().then(|| {
let hir_body_id = match rhs {
ConstItemRhs::Body(body) => Some(body.hir_id),
ConstItemRhs::Direct(_) => None,
};
infer_placeholder_type(
icx.lowerer(),
def_id,
rhs.hir_id(),
hir_body_id,
ty.span,
rhs.span(tcx),
item.ident,
Expand All @@ -109,10 +113,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
ImplItemKind::Fn(_, _) => new_bound_fn_def(item.hir_id(), def_id.to_def_id()),
ImplItemKind::Const(ty, rhs) => {
if ty.is_suggestable_infer_ty() {
let hir_body_id = match rhs {
ConstItemRhs::Body(body) => Some(body.hir_id),
ConstItemRhs::Direct(_) => None,
};
infer_placeholder_type(
icx.lowerer(),
def_id,
rhs.hir_id(),
hir_body_id,
ty.span,
rhs.span(tcx),
item.ident,
Expand All @@ -137,7 +145,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
infer_placeholder_type(
icx.lowerer(),
def_id,
body_id.hir_id,
Some(body_id.hir_id),
ty.span,
tcx.hir_body(body_id).value.span,
ident,
Expand All @@ -157,10 +165,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
}
ItemKind::Const(ident, _, ty, rhs) => {
if ty.is_suggestable_infer_ty() {
let hir_body_id = match rhs {
ConstItemRhs::Body(body) => Some(body.hir_id),
ConstItemRhs::Direct(_) => None,
};
infer_placeholder_type(
icx.lowerer(),
def_id,
rhs.hir_id(),
hir_body_id,
ty.span,
rhs.span(tcx),
ident,
Expand Down Expand Up @@ -431,28 +443,28 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S
fn infer_placeholder_type<'tcx>(
cx: &dyn HirTyLowerer<'tcx>,
def_id: LocalDefId,
hir_id: HirId,
hir_body_id: Option<HirId>,
ty_span: Span,
body_span: Span,
item_ident: Ident,
kind: &'static str,
) -> Ty<'tcx> {
let tcx = cx.tcx();
// If the type is omitted on a `type const` we can't run
// type check on since that requires the const have a body
// which `type const`s don't.
let ty = if tcx.is_type_const(def_id.to_def_id()) {
if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) {
tcx.type_of(trait_item_def_id).instantiate_identity().skip_norm_wip()
} else {
Ty::new_error_with_message(
tcx,
ty_span,
"constant with `type const` requires an explicit type",
)
// If the type is omitted on const with `ConstItemRhs::Direct`, we can't run type check on it,
// since that requires the const have a body, i.e. `ConstItemRhs::Body`.
let ty = match hir_body_id {
Some(hir_id) => tcx.typeck(def_id).node_type(hir_id),
None => {
if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) {
tcx.type_of(trait_item_def_id).instantiate_identity().skip_norm_wip()
} else {
Ty::new_error_with_message(
tcx,
ty_span,
"directly represented const requires an explicit type",
)
}
}
} else {
tcx.typeck(def_id).node_type(hir_id)
};

// If this came from a free `const` or `static mut?` item,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
});

if let ty::AssocTag::Const = assoc_tag
&& !self.tcx().is_type_const(assoc_item.def_id)
&& !self.tcx().is_direct_const(assoc_item.def_id)
&& !tcx.features().generic_const_args()
{
if tcx.features().min_generic_const_args() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3153,7 +3153,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span: Span,
) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx();
if tcx.is_type_const(def_id) || tcx.features().generic_const_args() {
if tcx.is_type_const_syntax(def_id) || tcx.features().generic_const_args() {
Ok(())
} else {
let mut err = self.dcx().struct_span_err(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
}
DefKind::Const { .. }
if !tcx.generics_of(item_def_id).own_requires_monomorphization()
&& !tcx.is_type_const(item_def_id) =>
&& tcx.const_of_item(item_def_id).is_none() =>
{
// FIXME(generic_const_items): Passing empty instead of identity args is fishy but
// seems to be fine for now. Revisit this!
Expand Down
Loading
Loading