-
Notifications
You must be signed in to change notification settings - Fork 13.3k
rustc: introduce {ast,hir}::AnonConst to consolidate so-called "embedded constants". #50851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/libsyntax/ast.rs
Outdated
@@ -1857,7 +1866,7 @@ pub struct Variant_ { | |||
pub attrs: Vec<Attribute>, | |||
pub data: VariantData, | |||
/// Explicit discriminant, e.g. `Foo = 1` | |||
pub disr_expr: Option<P<Expr>>, | |||
pub disr_expr: Option<Const>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit strange that const
and static
initializers are not treated as Const
and not visited by fn visit_const
, for example, despite being same "constant single-expression bodies".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to introduce Const
in AST, btw?
New node ids can be assigned during lowering to HIR too.
At least from syntax/expansion point of view Const
is "just an expression".
(I see that some stuff in resolve becomes shorter, but I haven't looked in detail yet.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those have items (or trait/impl associated items) they're directly attached to, so they don't need any changes, but also changing them would complicate a bunch of logic that's straight-forward today and would have to jump through an extra hoop.
There's one potential exception to this, which is that static
could be considered to be "more disjoint" from its initializer than const
and separating them could allow better bookkeeping of the "allocation" vs "value the allocation is initialized with" (cc @oli-obk), but even then it seems a bit stretched.
I wanted to avoid calling the type EmbeddedConst
because it's long and potentially even more confusing, but if anyone has a better suggestion, it could use being more explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the static vs its value won't get easier by changing this. Miri's bookkeeping about that is completely sane now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to introduce
Const
in AST, btw?
New node ids can be assigned during lowering to HIR too.
Sadly, yes, because the DefId
tree is built from the AST, and nodes inside a Const
need to be its descendants (this is where some of the ICEs for closures came from).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, what criterion should a constant Expr
satisfy to become Const
then? No direct parent with DefId
?
Discriminants in enums have a direct parent with DefId
to which they are attached - the variant itself, in this sense I don't see how they are different from const
s or static
s. Is preferring Const
just a matter of convenience in this case?
Could all this be documented in a comment for Const
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, expressions in range patterns have very similar properties to array sizes, etc (THIS ... AND_THIS
), but I guess they don't need a body because you can't smuggle arbitrary expressions into them, paths at most.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The criterion is a requirement of separate const-evaluation (which requires separate type-checking).
Array type lengths and enum discriminants don't (necessarily) have a parent body so they need a separate DefId
and body to even be type-checked (array type lengths could have a DefId
attached to the NodeId
of the TyArray
, but enum variants already have a DefId
with a different meaning).
The count of an ExprRepeat
is technically guaranteed to be nested inside another body, but type-checking the ExprRepeat
requires const-evaluating the count, which currently can't be done without the count being a separate body.
In contrast, const
and static
Also, expressions in range patterns have very similar properties to array sizes
It might be a good idea to keep those separate too, but type-checking them could require inference from the outer body (because of associated consts), so it's tricky.
I think long-term we should perhaps keep such constant expressions (including ones from paths involving const generics, in the future), in a separate body but type-check them like closures (sharing the inference context of their parent body), while retaining the ability to const-eval them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh. will this make the difference between a variant's discriminant and it's isize value clearer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will this make the difference between a variant's discriminant and it's isize value clearer?
Doubful.
@@ -129,30 +113,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { | |||
|
|||
self.with_parent(def, |this| { | |||
match i.node { | |||
ItemKind::Enum(ref enum_definition, _) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
huzzah 🎉
src/libsyntax/ast.rs
Outdated
@@ -921,6 +921,15 @@ pub enum UnsafeSource { | |||
UserProvided, | |||
} | |||
|
|||
/// A constant (expression) embedded inside a type, an expression, | |||
/// or used to define the discriminant value of an enum variant. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should call this an AnonymousConst
or something like that? This would address @petrochenkov's concern about const vs static items to some extent, since they are clearly not anonymous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, Const
seems too generic for this thing that has a very specific technical purpose rather than represents constant expressions in general.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of ty::Const
when I picked the name, TBH, but that doesn't make as much sense in the AST/HIR.
I guess AnonConst
would work pretty well, thanks!
r=me once we settle this bikeshed |
@bors r=nikomatsakis |
📌 Commit 26aad25 has been approved by |
rustc: introduce {ast,hir}::AnonConst to consolidate so-called "embedded constants". Previously, constants in array lengths and enum variant discriminants were "merely an expression", and had no separate ID for, e.g. type-checking or const-eval, instead reusing the expression's. That complicated code working with bodies, because such constants were the only special case where the "owner" of the body wasn't the HIR parent, but rather the same node as the body itself. Also, if the body happened to be a closure, we had no way to allocate a `DefId` for both the constant *and* the closure, leading to *several* bugs (mostly ICEs where type errors were expected). This PR rectifies the situation by adding another (`{ast,hir}::AnonConst`) node around every such constant. Also, const generics are expected to rely on the new `AnonConst` nodes, as well (cc @varkor). * fixes #48838 * fixes #50600 * fixes #50688 * fixes #50689 * obsoletes #50623 r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
Previously, constants in array lengths and enum variant discriminants were "merely an expression", and had no separate ID for, e.g. type-checking or const-eval, instead reusing the expression's.
That complicated code working with bodies, because such constants were the only special case where the "owner" of the body wasn't the HIR parent, but rather the same node as the body itself.
Also, if the body happened to be a closure, we had no way to allocate a
DefId
for both the constant and the closure, leading to several bugs (mostly ICEs where type errors were expected).This PR rectifies the situation by adding another (
{ast,hir}::AnonConst
) node around every such constant. Also, const generics are expected to rely on the newAnonConst
nodes, as well (cc @varkor).r? @nikomatsakis