type system const items via direct rhs - #162179
Conversation
|
Some changes occurred to the CTFE machinery
cc @rust-lang/clippy Some changes occurred in match checking cc @Nadrieril HIR ty lowering was modified cc @fmease changes to the core type system cc @lcnr |
|
|
| @@ -2683,19 +2683,41 @@ impl<'hir> LoweringContext<'_, 'hir> { | |||
| ) -> hir::ConstItemRhs<'hir> { | |||
| match (body, kind) { | |||
| (body, ConstItemKind::Body) => { | |||
There was a problem hiding this comment.
In the long tail of history I suppose we wont have a ConstItemKind to match on because they'll all be the same kind?
There was a problem hiding this comment.
correct, ConstItemKind gets nuked, and this method, lower_const_item_rhs, will only be this arm of this match statement.
| def_id: LocalDefId, | ||
| item_ty: Ty<'tcx>, | ||
| has_value: bool, | ||
| ) -> Result<(), ErrorGuaranteed> { |
There was a problem hiding this comment.
no reason, there was no ? or return Err or anything in this method, we were always returning Ok(()), so why not yeet Result
| Ty::new_error_with_message( | ||
| tcx, | ||
| ty_span, | ||
| "constant with `type const` requires an explicit type", |
There was a problem hiding this comment.
I assume this isn't necessarily always a type const nowadays?
There was a problem hiding this comment.
yeahh. bunch of comments that need to be updated too, but with so much up in the air right now, I've kind of put off changing this wording to after type const is fully yeeted, and we can just talk about consts with a gca!() rhs. kind of a pain to try to invent some wording like "constant with type const or direct_const_arg!() rhs or is a macroless direct const requires an explicit type" that's not a mouthful, but if you think it's worth it I can poke around~
| kind: hir::TraitItemKind::Const(_, ct), .. | ||
| }) => ct?, | ||
| hir::Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => ct, | ||
| hir::Node::AnonConst(..) | hir::Node::ConstBlock(..) => { |
There was a problem hiding this comment.
why for anon const/const block 🤔 I would expect us to not call this query on these defkinds but I guess we do in practice for some reason?
There was a problem hiding this comment.
yeah, like, the debug assert in eval_in_interpreter, thir_body, the par_hir_body_owners call in rustc_hir_analysis/lib.rs, the rustc_monomorphize/collector.rs, buncha wonky places that don't particularly care about const items vs anon consts, and it just clutters the caller to check for anon consts. but also totally reasonable to guard against anon consts there too, and ICE in const_of_item for anon consts instead.
| record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id)); | ||
| } | ||
| if should_encode_const_of_item(self.tcx, def_id, def_kind) { | ||
| if let DefKind::Const { .. } | DefKind::AssocConst { .. } | DefKind::AnonConst = |
There was a problem hiding this comment.
I guess this is the same question as above, why encode it for AnonConst :3
There was a problem hiding this comment.
yeah, also, related comment in the PR description:
should we serialize the const_of_item query for anon consts, or just guard against the DefKind in some helper that returns the actually serialized query impl? Behavior is the same, idk perf jank or whatever.
| /// | ||
| /// This is NOT the same as whether the `def_id` can be represented in/used by the type system. | ||
| /// For that, you probably want to ask `const_of_item().is_some()`. | ||
| pub fn is_type_const(self, def_id: impl IntoQueryKey<DefId>) -> bool { |
There was a problem hiding this comment.
U changed elsewhere to be is_type_const_syntax right? I would do similar here to make it clear this is not so much a semantic thing any longer (though it may not matter much since type const yeet soon)
There was a problem hiding this comment.
mm yeah, when developing this PR I had this called is_type_const_syntax to make sure I looked at all callsites, but I renamed it back just before submit. (grepping is_type_const_syntax is zero hits, it's not a thing in this PR)
but yea, tbh reasonable to keep that change instead of reverting it, if it's useful in this PR's development it's probably just straight up useful always and should be kept :P
| if tcx.is_type_const(def_id) { | ||
| // Under generic_const_args, `def_id` might be a trait alias that is a regular const, | ||
| // 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. |
There was a problem hiding this comment.
In theory we could only do this for projections, not free/inherent consts since those we can just look at const_of_item for during MIR building. But I don't think that matters 🤔
I'm not confident in whether I consider this to be a hack or a principled fix tbh 😅 It's probably a bit in the middle I suppose... Can you add a FIXME to revisit this before stabilization even if it's fine for now and may even wind up being the long term thing we do
There was a problem hiding this comment.
o though pls use a term other than "trait alias" since that means something else
| { | ||
| debug_assert!( | ||
| tcx.const_of_item(owner_def.to_def_id()).is_none(), | ||
| "thir_body queried for type_const" |
There was a problem hiding this comment.
probably not always a type const right?
| { | ||
| debug_assert!( | ||
| tcx.const_of_item(def).is_none(), | ||
| "CTFE tried to evaluate type-const: {:?}", |
There was a problem hiding this comment.
probably not always a type const right?
| let const_value = if alias_const.kind.is_type_const(self.tcx) { | ||
| // Under generic_const_args, `alias_const` might be a trait alias that is a regular const, | ||
| // 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. |
There was a problem hiding this comment.
| // must use type system normalization for all consts under generic_const_args. | |
| // must use type system normalization for all consts under generic_const_args. | |
| // | |
| // We probably want to always use type system norm on stable too | |
| // but that would be a breaking change so right now we limit it to | |
| // just GCA. |
maybe 🤔
There was a problem hiding this comment.
it would be worth linking to something but im not sure what, i dont know that I have a good write up anywhere of plans for const patterns. but I should write one
There was a problem hiding this comment.
you made an issue for this here, maybe this link? rust-lang/project-const-generics#105 (there's nothing really in this issue at the moment though)
There was a problem hiding this comment.
on a tangent, more than just const patterns, I think a writeup for the uuuh compiler/rustc_mir_build/src/builder/expr/as_constant.rs change would be lovely. when I was yapping with lcnr about this, that one in particular took a lot to communicate/sync on. like, all the stuff around padding bytes and multiple value representations and whatever and more importantly, how we plan to address those issues, big oof, rough times. (lcnr had the idea to spec const items as roundtripping their result through a valtree or something, but yea, no clue myself)
|
@rustbot author |
View all comments
fixes #161264
see also zulip thread: #project-const-generics > implementing assoc consts as direct args
a const item with a
direct!rhs is now a type system transparent direct const, similar to a type const:if the macroless feature is enabled, the macroless heuristic also applies here
this PR puts us in an awkward middle ground, between the present world with
type const, and the future of GCA as discussed in this zulip thread: #project-const-generics > talkies at lasttl;dr we're yeeting
type constand replacing it withconst C: T = gca!(V);, and with this PR, both syntaxes are supported at the same time, which is weird and awkward. But, incremental improvement is good, doing the whole thing at once is too much!some notes on the change:
type constsyntax is used, not whether it is a type system transparent constconst_of_itemquery now returnsOption, and isSomewhen it is a type system transparent direct const.const_of_itemreturnsNoneif there is no RHS rather than panicing - if it panics, it's vaguely annoying to guard against this in callsites, returningNoneis a bit more convenient. API design is hard, idk.TyCtxtmethodis_direct_constis true if it's either atype const, or if it's a direct const#[always_gca]attribute, or if it has agca!rhs.const_of_itemquery for anon consts, or just guard against the DefKind in some helper that returns the actually serialized query impl? Behavior is the same, idk perf jank or whatever.r? @BoxyUwU