You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tracking issue for RFC 2526, "Support underscores as constant names" #54912
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.
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)
let _ = is a weird beast, so the following sticks out from the RFC:
Just like let _, this doesn't introduce any new bindings, but still evaluates the rvalue at compile time like any other constant.
That's not "just like let _". let _ evaluates the place but never performs the place-to-rvalue coercion. Specifically, let _ = *v does not access memory, and let _ = mutex.lock().unwrap() does not drop the guard.
It is unfortunate that Rust was designed that way and we do not have a way back. It is really confusing to even experienced users unless they jump into the very deep level of the language.
If this feature could ever be designed again, I would hope that let _ = ... to always performs the place-to-rvalue coercion unless it is no-op, so we have less weirdness.
That's not "just like let _". let _ evaluates the place but never performs the place-to-rvalue coercion. Specifically, let _ = *v does not access memory, and let _ = mutex.lock().unwrap() does not drop the guard.
That's not "just like let _". let _ evaluates the place but never performs the place-to-rvalue coercion. Specifically, let _ = *v does not access memory, and let _ = mutex.lock().unwrap() does not drop the guard.
I think the confusion here is the direction of the conversion. Matching against a pattern always does a "value to place" conversion, as patterns require places to do discriminant checks and field accesses, so:
let _ = place_expr; evaluates but doesn't access the place, so it's close to &raw place_expr
let _ = value_expr; evaluates the value, puts it in a temporary place, which gets dropped, so identical in behavior to drop(value_expr);, value_expr; or many other uses of a value expression where the value gets dropped - including &raw place_expr;!
So depending on some exact details around unsafe code and whatnot, let _ = e; might be equivalent to &raw e; in all cases (ignoring optimizations, or assuming unused address-of are ignored).
If the _ is interpreted as a pattern, and not as a unique identifier like in use foo as _;, then the implementation needs to be changed to not add the names of _ consts into their parent modules.
I think it would be good to fix this so that we treat const _: T = expr; as we do with extern { .. } and foo!(); in an item position right now. That is, it doesn't have a name, and we don't gensym. That might perhaps involve having Option<Ident> in the hir::Item.
You don't need Option because extern {...} and foo!(); already work with ident: Ident in {ast,hir}::Item (via the "Invalid" "keyword", aka Symbol::intern("")).
@petrochenkov Are there any observable differences between _ as PatKind::Wild and using gensyms as it is implemented right now (aside from rustdoc which isn't important here) such that it matters wrt. stability and forward compatibility?
We discussed this on the language team meeting today and gave the green light for a stabilization report and PR (see above). I will be writing the report and adding it to the PR within a few hours.
Activity
petrochenkov commentedon 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 commentedon Oct 8, 2018
Hehe, I agree we should generalize (to patterns) eventually but it seemed that it was much more complex from @eddyb's comments. :)
dsciarra commentedon Oct 9, 2018
looks interesting, I will give it a try!
earthengine commentedon 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 commentedon Oct 11, 2018
We don't need to remove any
MIR. Unused private constants don't end up in metadata.earthengine commentedon Oct 12, 2018
@oli-obk
Fine. There is one "inconsistency" in Rust today:
When implementing this, how do we want to justify
Shall we repeat the inconsistency, or shall we count both valid or invalid?
oli-obk commentedon 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.
Auto merge of #55015 - dsciarra:underscores-constant-names, r=petroch…
Centril commentedon 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 commentedon 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
30 remaining items
RalfJung commentedon May 16, 2019
let _ =is a weird beast, so the following sticks out from the RFC:That's not "just like
let _".let _evaluates the place but never performs the place-to-rvalue coercion. Specifically,let _ = *vdoes not access memory, andlet _ = mutex.lock().unwrap()does not drop the guard.earthengine commentedon May 17, 2019
It is unfortunate that Rust was designed that way and we do not have a way back. It is really confusing to even experienced users unless they jump into the very deep level of the language.
If this feature could ever be designed again, I would hope that
let _ = ...to always performs the place-to-rvalue coercion unless it is no-op, so we have less weirdness.nox commentedon May 17, 2019
Did you mean that it does drop the guard?
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=94047cd4bd5f9e822ad19bdd55c15291
RalfJung commentedon May 17, 2019
Dang, it got me again... this does not drop though:
eddyb commentedon May 22, 2019
I think the confusion here is the direction of the conversion. Matching against a pattern always does a "value to place" conversion, as patterns require places to do discriminant checks and field accesses, so:
let _ = place_expr;evaluates but doesn't access the place, so it's close to&raw place_exprlet _ = value_expr;evaluates the value, puts it in a temporary place, which gets dropped, so identical in behavior todrop(value_expr);,value_expr;or many other uses of a value expression where the value gets dropped - including&raw place_expr;!So depending on some exact details around unsafe code and whatnot,
let _ = e;might be equivalent to&raw e;in all cases (ignoring optimizations, or assuming unused address-of are ignored).Centril commentedon May 23, 2019
I think it would be good to fix this so that we treat
const _: T = expr;as we do withextern { .. }andfoo!();in an item position right now. That is, it doesn't have a name, and we don't gensym. That might perhaps involve havingOption<Ident>in thehir::Item.eddyb commentedon May 24, 2019
You don't need
Optionbecauseextern {...}andfoo!();already work withident: Identin{ast,hir}::Item(via the "Invalid" "keyword", akaSymbol::intern("")).Centril commentedon May 29, 2019
@petrochenkov Are there any observable differences between
_asPatKind::Wildand using gensyms as it is implemented right now (aside from rustdoc which isn't important here) such that it matters wrt. stability and forward compatibility?petrochenkov commentedon May 29, 2019
No, there should be no observable difference after #56392.
They just create some extra work for the resolver and also encoder/decoder, I think.
Centril commentedon May 30, 2019
We discussed this on the language team meeting today and gave the green light for a stabilization report and PR (see above). I will be writing the report and adding it to the PR within a few hours.
Merge #1847
Rollup merge of rust-lang#67877 - dtolnay:const-_, r=nagisa
Rollup merge of rust-lang#67877 - dtolnay:const-_, r=nagisa