Skip to content

Commit 108442b

Browse files
committed
type system const via direct rhs
1 parent edc52f8 commit 108442b

47 files changed

Lines changed: 318 additions & 201 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎compiler/rustc_ast_lowering/src/lib.rs‎

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2683,19 +2683,41 @@ impl<'hir> LoweringContext<'_, 'hir> {
26832683
) -> hir::ConstItemRhs<'hir> {
26842684
match (body, kind) {
26852685
(body, ConstItemKind::Body) => {
2686-
hir::ConstItemRhs::Body(self.lower_const_body(span, body.as_deref()))
2687-
}
2688-
(Some(body), ConstItemKind::TypeConst) => {
2689-
hir::ConstItemRhs::TypeConst(self.arena.alloc(
2690-
match self.can_lower_expr_to_const_arg_direct(
2691-
&body,
2692-
DirectConstArgContext::MacrolessMinGenericConstArgs,
2693-
) {
2694-
Ok(()) => self.lower_expr_to_const_arg_direct(&body, None),
2695-
Err(err) => err.emit(self),
2696-
},
2697-
))
2686+
let is_direct = |body| {
2687+
if self.tcx.features().macroless_generic_const_args() {
2688+
self.can_lower_expr_to_const_arg_direct(
2689+
body,
2690+
DirectConstArgContext::MacrolessMinGenericConstArgs,
2691+
)
2692+
.is_ok()
2693+
} else {
2694+
// do not check can_lower_expr_to_const_arg_direct, but rather just
2695+
// ExprKind::DirectConstArg, because we don't want e.g.
2696+
// `impl<const N: u8> { const C: u8 = N; }` to be a direct-rhs const
2697+
matches!(body, Expr { kind: ExprKind::DirectConstArg(_), .. })
2698+
}
2699+
};
2700+
// N.B.: the feature gate for this is generic_const_args, not min_generic_const_args
2701+
if self.tcx.features().generic_const_args()
2702+
&& let Some(body) = body
2703+
&& is_direct(body)
2704+
{
2705+
hir::ConstItemRhs::Direct(
2706+
self.arena.alloc(self.lower_expr_to_const_arg_direct(&body, None)),
2707+
)
2708+
} else {
2709+
hir::ConstItemRhs::Body(self.lower_const_body(span, body.as_deref()))
2710+
}
26982711
}
2712+
(Some(body), ConstItemKind::TypeConst) => hir::ConstItemRhs::Direct(self.arena.alloc(
2713+
match self.can_lower_expr_to_const_arg_direct(
2714+
&body,
2715+
DirectConstArgContext::MacrolessMinGenericConstArgs,
2716+
) {
2717+
Ok(()) => self.lower_expr_to_const_arg_direct(&body, None),
2718+
Err(err) => err.emit(self),
2719+
},
2720+
)),
26992721
(None, ConstItemKind::TypeConst) => {
27002722
let const_arg = ConstArg {
27012723
hir_id: self.next_id(),
@@ -2704,7 +2726,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
27042726
),
27052727
span: DUMMY_SP,
27062728
};
2707-
hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg))
2729+
hir::ConstItemRhs::Direct(self.arena.alloc(const_arg))
27082730
}
27092731
}
27102732
}

‎compiler/rustc_const_eval/src/const_eval/eval_queries.rs‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,15 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
440440
typing_env: ty::TypingEnv<'tcx>,
441441
) -> Result<R, ErrorHandled> {
442442
let def = cid.instance.def.def_id();
443-
// `type const` don't have bodys
444-
debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def);
443+
// directly represented consts don't have bodies
444+
if cfg!(debug_assertions)
445+
&& matches!(tcx.def_kind(def), DefKind::Const { .. } | DefKind::AssocConst { .. })
446+
{
447+
debug_assert!(
448+
tcx.const_of_item(def).is_none(),
449+
"CTFE tried to evaluate directly represented const item: {def:?}"
450+
);
451+
}
445452

446453
let is_static = tcx.is_static(def);
447454
let mut ecx = InterpCx::new(

‎compiler/rustc_hir/src/hir.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,21 +416,21 @@ impl<'hir> PathSegment<'hir> {
416416
#[derive(Clone, Copy, Debug, StableHash)]
417417
pub enum ConstItemRhs<'hir> {
418418
Body(BodyId),
419-
TypeConst(&'hir ConstArg<'hir>),
419+
Direct(&'hir ConstArg<'hir>),
420420
}
421421

422422
impl<'hir> ConstItemRhs<'hir> {
423423
pub fn hir_id(&self) -> HirId {
424424
match self {
425425
ConstItemRhs::Body(body_id) => body_id.hir_id,
426-
ConstItemRhs::TypeConst(ct_arg) => ct_arg.hir_id,
426+
ConstItemRhs::Direct(ct_arg) => ct_arg.hir_id,
427427
}
428428
}
429429

430430
pub fn span<'tcx>(&self, tcx: impl crate::intravisit::HirTyCtxt<'tcx>) -> Span {
431431
match self {
432432
ConstItemRhs::Body(body_id) => tcx.hir_body(*body_id).value.span,
433-
ConstItemRhs::TypeConst(ct_arg) => ct_arg.span,
433+
ConstItemRhs::Direct(ct_arg) => ct_arg.span,
434434
}
435435
}
436436
}

‎compiler/rustc_hir/src/intravisit.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ pub fn walk_const_item_rhs<'v, V: Visitor<'v>>(
10821082
) -> V::Result {
10831083
match ct_rhs {
10841084
ConstItemRhs::Body(body_id) => visitor.visit_nested_body(body_id),
1085-
ConstItemRhs::TypeConst(const_arg) => visitor.visit_const_arg_unambig(const_arg),
1085+
ConstItemRhs::Direct(const_arg) => visitor.visit_const_arg_unambig(const_arg),
10861086
}
10871087
}
10881088

‎compiler/rustc_hir_analysis/src/check/check.rs‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -953,10 +953,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
953953
tcx.require_lang_item(LangItem::Sized, ty_span),
954954
);
955955
check_where_clauses(wfcx, def_id);
956-
957-
if tcx.is_type_const(def_id) {
958-
wfcheck::check_type_const(wfcx, def_id, ty, true)?;
959-
}
956+
wfcheck::check_const_item(wfcx, def_id, ty);
960957
Ok(())
961958
}));
962959

‎compiler/rustc_hir_analysis/src/check/compare_impl_item.rs‎

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,23 +2157,18 @@ fn compare_type_const<'tcx>(
21572157
impl_const_item: ty::AssocItem,
21582158
trait_const_item: ty::AssocItem,
21592159
) -> Result<(), ErrorGuaranteed> {
2160-
let impl_is_type_const = tcx.is_type_const(impl_const_item.def_id);
2161-
let trait_type_const_span = tcx.type_const_span(trait_const_item.def_id);
2160+
let impl_is_type_const = tcx.is_type_const_syntax(impl_const_item.def_id);
2161+
let trait_is_type_const = tcx.is_type_const_syntax(trait_const_item.def_id);
21622162

2163-
if let Some(trait_type_const_span) = trait_type_const_span
2164-
&& !impl_is_type_const
2165-
{
2163+
if trait_is_type_const && !impl_is_type_const {
21662164
return Err(tcx
21672165
.dcx()
21682166
.struct_span_err(
21692167
tcx.def_span(impl_const_item.def_id),
21702168
"implementation of a `type const` must also be marked as `type const`",
21712169
)
21722170
.with_span_note(
2173-
MultiSpan::from_spans(vec![
2174-
tcx.def_span(trait_const_item.def_id),
2175-
trait_type_const_span,
2176-
]),
2171+
tcx.def_span(trait_const_item.def_id),
21772172
"trait declaration of const is marked as `type const`",
21782173
)
21792174
.emit());

‎compiler/rustc_hir_analysis/src/check/wfcheck.rs‎

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -928,13 +928,9 @@ pub(crate) fn check_associated_item(
928928
let ty = tcx.type_of(def_id).instantiate_identity();
929929
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
930930
wfcx.register_wf_obligation(span, loc, ty.into());
931+
check_const_item(wfcx, def_id, ty);
931932

932-
let has_value = item.defaultness(tcx).has_value();
933-
if tcx.is_type_const(def_id) {
934-
check_type_const(wfcx, def_id, ty, has_value)?;
935-
}
936-
937-
if has_value {
933+
if item.defaultness(tcx).has_value() {
938934
let code = ObligationCauseCode::SizedConstOrStatic;
939935
wfcx.register_bound(
940936
ObligationCause::new(span, def_id, code),
@@ -1263,17 +1259,17 @@ pub(crate) fn check_static_item<'tcx>(
12631259
})
12641260
}
12651261

1262+
/// Runs checks common to both free consts and associated consts
12661263
#[instrument(level = "debug", skip(wfcx))]
1267-
pub(super) fn check_type_const<'tcx>(
1264+
pub(super) fn check_const_item<'tcx>(
12681265
wfcx: &WfCheckingCtxt<'_, 'tcx>,
12691266
def_id: LocalDefId,
12701267
item_ty: Ty<'tcx>,
1271-
has_value: bool,
1272-
) -> Result<(), ErrorGuaranteed> {
1268+
) {
12731269
let tcx = wfcx.tcx();
12741270
let span = tcx.def_span(def_id);
12751271

1276-
if !tcx.features().const_param_ty_unchecked() {
1272+
if tcx.is_direct_const(def_id.into()) && !tcx.features().const_param_ty_unchecked() {
12771273
wfcx.register_bound(
12781274
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),
12791275
wfcx.param_env,
@@ -1282,8 +1278,8 @@ pub(super) fn check_type_const<'tcx>(
12821278
);
12831279
}
12841280

1285-
if has_value {
1286-
let raw_ct = tcx.const_of_item(def_id).instantiate_identity();
1281+
if let Some(direct_rhs) = tcx.const_of_item(def_id) {
1282+
let raw_ct = direct_rhs.instantiate_identity();
12871283
let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct);
12881284
wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into());
12891285

@@ -1294,7 +1290,6 @@ pub(super) fn check_type_const<'tcx>(
12941290
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)),
12951291
));
12961292
}
1297-
Ok(())
12981293
}
12991294

13001295
#[instrument(level = "debug", skip(tcx, impl_))]

‎compiler/rustc_hir_analysis/src/collect.rs‎

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,25 +1797,24 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin
17971797
fn const_of_item<'tcx>(
17981798
tcx: TyCtxt<'tcx>,
17991799
def_id: LocalDefId,
1800-
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1800+
) -> Option<ty::EarlyBinder<'tcx, Const<'tcx>>> {
18011801
let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
1802-
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
1803-
hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(_, ct), .. }) => {
1804-
ct.expect("no default value for trait assoc const")
1805-
}
1806-
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
1807-
_ => {
1808-
span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
1802+
hir::Node::Item(&hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => ct,
1803+
hir::Node::TraitItem(&hir::TraitItem {
1804+
kind: hir::TraitItemKind::Const(_, ct), ..
1805+
}) => ct?,
1806+
hir::Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => ct,
1807+
node => {
1808+
span_bug!(
1809+
tcx.def_span(def_id),
1810+
"`const_of_item` expected a const or assoc const item, got {node:?}"
1811+
)
18091812
}
18101813
};
18111814
let ct_arg = match ct_rhs {
1812-
hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
1815+
hir::ConstItemRhs::Direct(ct_arg) => ct_arg,
18131816
hir::ConstItemRhs::Body(_) => {
1814-
let e = tcx.dcx().span_delayed_bug(
1815-
tcx.def_span(def_id),
1816-
"cannot call const_of_item on a non-type_const",
1817-
);
1818-
return ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e));
1817+
return None;
18191818
}
18201819
};
18211820
let icx = ItemCtxt::new(tcx, def_id);
@@ -1827,8 +1826,8 @@ fn const_of_item<'tcx>(
18271826
if let Err(e) = icx.check_tainted_by_errors()
18281827
&& !ct.references_error()
18291828
{
1830-
ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e))
1829+
Some(ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e)))
18311830
} else {
1832-
ty::EarlyBinder::bind(tcx, ct)
1831+
Some(ty::EarlyBinder::bind(tcx, ct))
18331832
}
18341833
}

‎compiler/rustc_hir_analysis/src/collect/clauses_of.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ fn const_evaluatable_clauses_of<'tcx>(
444444
}
445445

446446
// Skip type consts as mGCA doesn't support evaluatable clauses.
447-
if alias_const.kind.is_type_const(self.tcx) {
447+
if alias_const.kind.is_direct_const(self.tcx) {
448448
return;
449449
}
450450

‎compiler/rustc_hir_analysis/src/collect/type_of.rs‎

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
8787
TraitItemKind::Const(ty, rhs) => rhs
8888
.and_then(|rhs| {
8989
ty.is_suggestable_infer_ty().then(|| {
90+
let hir_body_id = match rhs {
91+
ConstItemRhs::Body(body) => Some(body.hir_id),
92+
ConstItemRhs::Direct(_) => None,
93+
};
9094
infer_placeholder_type(
9195
icx.lowerer(),
9296
def_id,
93-
rhs.hir_id(),
97+
hir_body_id,
9498
ty.span,
9599
rhs.span(tcx),
96100
item.ident,
@@ -109,10 +113,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
109113
ImplItemKind::Fn(_, _) => new_bound_fn_def(item.hir_id(), def_id.to_def_id()),
110114
ImplItemKind::Const(ty, rhs) => {
111115
if ty.is_suggestable_infer_ty() {
116+
let hir_body_id = match rhs {
117+
ConstItemRhs::Body(body) => Some(body.hir_id),
118+
ConstItemRhs::Direct(_) => None,
119+
};
112120
infer_placeholder_type(
113121
icx.lowerer(),
114122
def_id,
115-
rhs.hir_id(),
123+
hir_body_id,
116124
ty.span,
117125
rhs.span(tcx),
118126
item.ident,
@@ -137,7 +145,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
137145
infer_placeholder_type(
138146
icx.lowerer(),
139147
def_id,
140-
body_id.hir_id,
148+
Some(body_id.hir_id),
141149
ty.span,
142150
tcx.hir_body(body_id).value.span,
143151
ident,
@@ -157,10 +165,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
157165
}
158166
ItemKind::Const(ident, _, ty, rhs) => {
159167
if ty.is_suggestable_infer_ty() {
168+
let hir_body_id = match rhs {
169+
ConstItemRhs::Body(body) => Some(body.hir_id),
170+
ConstItemRhs::Direct(_) => None,
171+
};
160172
infer_placeholder_type(
161173
icx.lowerer(),
162174
def_id,
163-
rhs.hir_id(),
175+
hir_body_id,
164176
ty.span,
165177
rhs.span(tcx),
166178
ident,
@@ -431,28 +443,28 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S
431443
fn infer_placeholder_type<'tcx>(
432444
cx: &dyn HirTyLowerer<'tcx>,
433445
def_id: LocalDefId,
434-
hir_id: HirId,
446+
hir_body_id: Option<HirId>,
435447
ty_span: Span,
436448
body_span: Span,
437449
item_ident: Ident,
438450
kind: &'static str,
439451
) -> Ty<'tcx> {
440452
let tcx = cx.tcx();
441-
// If the type is omitted on a `type const` we can't run
442-
// type check on since that requires the const have a body
443-
// which `type const`s don't.
444-
let ty = if tcx.is_type_const(def_id.to_def_id()) {
445-
if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) {
446-
tcx.type_of(trait_item_def_id).instantiate_identity().skip_norm_wip()
447-
} else {
448-
Ty::new_error_with_message(
449-
tcx,
450-
ty_span,
451-
"constant with `type const` requires an explicit type",
452-
)
453+
// If the type is omitted on const with `ConstItemRhs::Direct`, we can't run type check on it,
454+
// since that requires the const have a body, i.e. `ConstItemRhs::Body`.
455+
let ty = match hir_body_id {
456+
Some(hir_id) => tcx.typeck(def_id).node_type(hir_id),
457+
None => {
458+
if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) {
459+
tcx.type_of(trait_item_def_id).instantiate_identity().skip_norm_wip()
460+
} else {
461+
Ty::new_error_with_message(
462+
tcx,
463+
ty_span,
464+
"directly represented const requires an explicit type",
465+
)
466+
}
453467
}
454-
} else {
455-
tcx.typeck(def_id).node_type(hir_id)
456468
};
457469

458470
// If this came from a free `const` or `static mut?` item,

0 commit comments

Comments
 (0)