Skip to content
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

Tracking issue for RFC 2526, "Support underscores as constant names" #54912

Open
Centril opened this Issue Oct 8, 2018 · 19 comments

Comments

Projects
None yet
@Centril
Copy link
Contributor

Centril commented Oct 8, 2018

This is a tracking issue for the RFC "Support underscores as constant names" (rust-lang/rfcs#2526).

Steps:

Unresolved questions:

None

@petrochenkov

This comment has been minimized.

Copy link
Contributor

petrochenkov commented Oct 8, 2018

Ugh, seems like a legitimized hack rather than a... well, any of several proper features to which this can be generalized.

At least this is a very tiny hack.
Implementation strategy is the same as for use Trait as _;.
If we encounter _ instead of the const name identifier, then we create a gensym for it instead of storing it in AST directly (so that different _s do not conflict).
Together with a feature gate and tests that would be all the implementation.

@Centril

This comment has been minimized.

Copy link
Contributor Author

Centril commented Oct 8, 2018

Ugh, seems like a legitimized hack rather than a... well, any of several proper features to which this can be generalized.

Hehe, I agree we should generalize (to patterns) eventually but it seemed that it was much more complex from @eddyb's comments. :)

@dsciarra

This comment has been minimized.

Copy link
Contributor

dsciarra commented Oct 9, 2018

looks interesting, I will give it a try!

@earthengine

This comment has been minimized.

Copy link

earthengine commented Oct 11, 2018

@petrochenkov

Can we also ensure that those gensyms get removed after before codegen? This means, the generated MIR should be removed in some MIR rounds.

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Oct 11, 2018

We don't need to remove any MIR. Unused private constants don't end up in metadata.

@earthengine

This comment has been minimized.

Copy link

earthengine commented Oct 12, 2018

@oli-obk

Fine. There is one "inconsistency" in Rust today:

let _: str = *"123"; //Legal
let _v: str = *"123"; //Illegal unless unsized_rvalues

When implementing this, how do we want to justify

const _: str = *"123";
const _v: str = *"123";

Shall we repeat the inconsistency, or shall we count both valid or invalid?

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Oct 12, 2018

I'd start out with both being disallowed, since that is the current behaviour of constants. But I have no strong opinion.

bors added a commit that referenced this issue Oct 14, 2018

Auto merge of #55015 - dsciarra:underscores-constant-names, r=petroch…
…enkov

Support underscore as constant name

Issue: #54912

@nvzqz nvzqz referenced this issue Nov 1, 2018

Open

Limitations #1

3 of 8 tasks complete
@Centril

This comment has been minimized.

Copy link
Contributor Author

Centril commented Nov 11, 2018

Setting earliest date for stabilization proposal to 25th november 2018 (14 days from now).

We'll likely want to discuss what direction generalizations should go in before stabilizing.

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Nov 15, 2018

The RFC did not discuss static _: T = ...;. Is that supposed to work, too? (the implementation does in fact allow this, accidentally even without a feature gate)

Fix for the stability hole is in #55983

@Centril Centril added the I-nominated label Dec 6, 2018

@scottmcm scottmcm removed the I-nominated label Dec 13, 2018

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Dec 13, 2018

I'm having a bit of second thoughts about this RFC. I feel like (a) the intention of const _: T = { .. } is pretty unclear and (b) it opens some weird questions about e.g. generic constants and how they fit here and (c) it doesn't support full patterns, which it kind of suggests it would support.

The motivation of "ensure some code type-checks" is real though. I sort of like the syntax const { ... } for that purpose. Thoughts?

I guess I'm probably just re-raising thoughts that came up on the RFC.

@RalfJung

This comment has been minimized.

Copy link
Member

RalfJung commented Dec 13, 2018

I sort of like the syntax const { ... } for that purpose. Thoughts?

Could that be re-used for explicit promotion as @oli-obk plans it?

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Dec 13, 2018

@RalfJung seems plausible. The one concern I could see is whether there would be some conflict as const { .. } could be an item and an expression, and we might want the latter to inherit the lexical scope from the surrounding fn, so it can refer to generic constant names -- but we could just say that const { .. } items cannot appear in functions (since...what's the point).

@cramertj

This comment has been minimized.

Copy link
Member

cramertj commented Dec 13, 2018

but we could just say that const { .. } items cannot appear in functions (since...what's the point).

Wouldn't that defeat the purpose of explicit promotion?

@Centril

This comment has been minimized.

Copy link
Contributor Author

Centril commented Dec 13, 2018

With respect to a) the intention of const _: T = { ... }; being unclear I agree with that in isolation. However, in the context of being wrapped in a macro such as const_assert! { ... } or inside a derive macro it feels rather clear what the purpose of this construct is.

My main worry is instead b) and c). That is, would we permit this?

const (A, B): (AType, BType) = (1, 2);

(this would be the natural extension of const _: Type = expr; because _ acts as a pattern in this context.

but also this?

const A<T>: AType<T> = expr;

and how can these be composed?

If we write:

const (A<T>, B<U>): (AType<U>, BType<T>) = expr;

does that make any sense?

I suppose that we could support generic constants when A<T> is written and patterns otherwise; that likely works syntactically but it could cause confusion (or maybe not... I'm not sure).

Finally, ideally, to keep the language consistent, we should keep const and static items as much as possible in sync syntactically. If we support const _: Type = expr; we should imo support static _: Type = expr; even if we lint on the latter.


As for supporting const { ... }, I think the meaning here isn't clear... there could be 2 different interpretations:

  1. The entire block { ... } is evaluated at compile time. This interpretation is based on const items.
  2. The entire block may be evaluated at compile time if all variables referenced are. Notably, you could write: let x = random(); let y = const { x * x };. This interpretation is based on const fn items. 2. would subsume 1.
@RalfJung

This comment has been minimized.

Copy link
Member

RalfJung commented Dec 14, 2018

Wouldn't that defeat the purpose of explicit promotion?

const expressions would be allowed in function bodies, just const items would not.

@DoumanAsh

This comment has been minimized.

Copy link

DoumanAsh commented Dec 14, 2018

I feel like (a) the intention of const _: T = { .. } is pretty unclear

I believe it is pretty clear to user as we can use let VAR = { ... }

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Dec 14, 2018

The entire block may be evaluated at compile time if all variables referenced are. Notably, you could write: let x = random(); let y = const { x * x };. This interpretation is based on const fn items. 2. would subsume 1.

I don't think that's a useful interpretation. There's absolutely nothing this const block could promise us. It's just regular code.

I agree with everything else. We should just allow constants with patterns and generic constants. We already support them inconveniently by defining a const function without arguments.

@Centril

This comment has been minimized.

Copy link
Contributor Author

Centril commented Jan 13, 2019

It's just regular code.

It's not. Notably, you may only reference existing bindings. Any function calls must still be const fn. For example, let y = const { random() }; would not be allowed.

I don't think that's a useful interpretation. There's absolutely nothing this const block could promise us.

There's plenty this would tell you:

  1. If you reference no bindings from outside you know it is evaluated at compile time.
  2. The block does not admit non-determinism even if bindings referenced are non-deterministically evaluated. This gives you a local way to enforce freedom from certain side-effects.

Now.. it might be confusing to have block form entitled const { .. } behave in this way, but that doesn't mean it isn't useful to behave in this way.

@nox

This comment has been minimized.

Copy link
Contributor

nox commented Mar 2, 2019

I don't really understand how generic constants can cause issues with unnamed consts, and AFAIK supporting _ is fully forwards-compatible with generalising const to fully accept patterns. Is there any chance this could be stabilised? Many derive macros out there currently generate a difficult-to-guess const name to scope extern crate and use statements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.