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

Stabilize underscore_const_names in 1.37.0 #61347

Merged
merged 3 commits into from Jun 16, 2019

Conversation

@Centril
Copy link
Member

commented May 30, 2019

You are now permitted to write:

const _: $type_expression = $term_expression;

That is, we change the grammar of items, as written in the .lyg notation, from:

Item = attrs:OuterAttr* vis:Vis? kind:ItemKind;
ItemKind =
  | ...
  | Const:{ "const" name:IDENT ":" ty:Type "=" value:Expr ";" }
  | ...
  ;

into:

Item = attrs:OuterAttr* vis:Vis? kind:ItemKind;
ItemKind =
  | ...
  | Const:{ "const" name:IdentOrUnderscore ":" ty:Type "=" value:Expr ";" }
  | ...
  ;

IdentOrUnderscore =
  | Named:IDENT
  | NoName:"_"
  ;

r? @petrochenkov

@Centril Centril added this to the 1.37 milestone May 30, 2019

@Centril Centril changed the title Stabilize underscore_const_names in 1.37.0 [WIP] Stabilize underscore_const_names in 1.37.0 May 30, 2019

@Centril Centril force-pushed the Centril:stabilize-underscore_const_names branch from e998227 to 85b1489 May 30, 2019

@rust-highfive

This comment was marked as resolved.

Copy link
Collaborator

commented May 30, 2019

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:01014b7c:start=1559226135180126665,finish=1559226137334986621,duration=2154859956
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
$ export GCP_CACHE_BUCKET=rust-lang-ci-cache
$ export AWS_ACCESS_KEY_ID=AKIA46X5W6CZEJZ6XT55
---
[01:10:18] .................................................................................................... 3800/5598
[01:10:22] ..ii................................................................................................ 3900/5598
[01:10:24] .......................i............................................................................ 4000/5598
[01:10:26] .......................................................................................i............ 4100/5598
[01:10:28] .........................................................................................F.......... 4200/5598
[01:10:47] .................................................................................................... 4400/5598
[01:10:50] .................................................................................................... 4500/5598
[01:10:53] .................................................................................................... 4600/5598
[01:10:57] .................................................................................................... 4700/5598
---
[01:11:34] 1 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:4:11
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:6:11
[01:11:34] 3    |
[01:11:34] 4 LL |     const _: () = ();
[01:11:34] 
[01:11:34] 6 
[01:11:34] 7 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:7:11
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:7:11
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:9:11
[01:11:34] 9    |
[01:11:34] 10 LL |     const _: () = ();
[01:11:34] 
[01:11:34] 12 
[01:11:34] 13 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:10:11
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:10:11
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:12:11
[01:11:34] 15    |
[01:11:34] 16 LL |     const _: () = ();
[01:11:34] 
[01:11:34] 18 
[01:11:34] 19 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:15:8
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:15:8
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:17:8
[01:11:34] 21    |
[01:11:34] 22 LL | static _: () = ();
[01:11:34] 
[01:11:34] 24 
[01:11:34] 25 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:16:8
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:16:8
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:18:8
[01:11:34] 27    |
[01:11:34] 28 LL | struct _();
[01:11:34] 
[01:11:34] 30 
[01:11:34] 31 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:17:6
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:17:6
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:19:6
[01:11:34] 33    |
[01:11:34] 34 LL | enum _ {}
[01:11:34] 
[01:11:34] 36 
[01:11:34] 37 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:18:4
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:18:4
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:20:4
[01:11:34] 39    |
[01:11:34] 40 LL | fn _() {}
[01:11:34] 
[01:11:34] 42 
[01:11:34] 43 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:19:5
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:19:5
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:21:5
[01:11:34] 45    |
[01:11:34] 46 LL | mod _ {}
[01:11:34] 
[01:11:34] 48 
[01:11:34] 49 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:20:6
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:20:6
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:22:6
[01:11:34] 51    |
[01:11:34] 52 LL | type _ = ();
[01:11:34] 
[01:11:34] 54 
[01:11:34] 55 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:21:5
---
[01:11:34] 61 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:22:5
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:24:5
[01:11:34] 63    |
[01:11:34] 64 LL | use _ as g;
[01:11:34] 
[01:11:34] 66 
[01:11:34] 67 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:23:7
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:23:7
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:25:7
[01:11:34] 69    |
[01:11:34] 70 LL | trait _ {}
[01:11:34] 
[01:11:34] 72 
[01:11:34] 73 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:24:7
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:24:7
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:26:7
[01:11:34] 75    |
[01:11:34] 76 LL | trait _ = Copy;
[01:11:34] 
[01:11:34] 78 
[01:11:34] 79 error: expected identifier, found reserved identifier `_`
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:25:14
[01:11:34] -   --> $DIR/underscore_item_not_const.rs:25:14
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:27:14
[01:11:34] 81    |
[01:11:34] 82 LL | macro_rules! _ { () => {} }
[01:11:34] 
[01:11:34] 84 
[01:11:34] 84 
[01:11:34] 85 error: expected one of `!` or `::`, found `_`
[01:11:34] +   --> $DIR/underscore_item_not_const.rs:28:7
[01:11:34] 87    |
[01:11:34] 87    |
[01:11:34] 88 LL | union _ { f: u8 }
[01:11:34] 89    |       ^ expected one of `!` or `::` here
[01:11:34] 
[01:11:34] The actual stderr differed from the expected stderr.
[01:11:34] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/underscore_item_not_const/underscore_item_not_const.stderr
[01:11:34] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/underscore_item_not_const/underscore_item_not_const.stderr
[01:11:34] To update references, rerun the tests and pass the `--bless` flag
[01:11:34] To only update this specific test, also pass `--test-args parser/underscore_item_not_const.rs`
[01:11:34] error: 1 errors occurred comparing output.
[01:11:34] status: exit code: 1
[01:11:34] status: exit code: 1
[01:11:34] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/parser/underscore_item_not_const.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/underscore_item_not_const" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/parser/underscore_item_not_const/auxiliary" "-A" "unused"
[01:11:34] ------------------------------------------
[01:11:34] 
[01:11:34] ------------------------------------------
[01:11:34] stderr:
[01:11:34] stderr:
[01:11:34] ------------------------------------------
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:6:11
[01:11:34]    |
[01:11:34] LL |     const _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:9:11
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL |     const _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:12:11
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL |     const _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:17:8
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | static _: () = (); //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:18:8
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | struct _(); //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:19:6
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | enum _ {} //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:20:4
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | fn _() {} //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:21:5
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | mod _ {} //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:22:6
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | type _ = (); //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:23:5
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | use _; //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:24:5
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | use _ as g; //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:25:7
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | trait _ {} //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:26:7
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | trait _ = Copy; //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] error: expected identifier, found reserved identifier `_`
[01:11:34]   --> /checkout/src/test/ui/parser/underscore_item_not_const.rs:27:14
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | macro_rules! _ { () => {} } //~ ERROR expected identifier, found reserved identifier `_`
[01:11:34] 
[01:11:34] 
[01:11:34] error: expected one of `!` or `::`, found `_`
[01:11:34]    |
[01:11:34]    |
[01:11:34] LL | union _ { f: u8 } //~ ERROR expected one of `!` or `::`, found `_`
[01:11:34]    |       ^ expected one of `!` or `::` here
[01:11:34] error: aborting due to 15 previous errors
[01:11:34] 
[01:11:34] 
[01:11:34] ------------------------------------------
---
[01:11:34] thread 'main' panicked at 'Some tests failed', src/tools/compiletest/src/main.rs:521:22
[01:11:34] note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
[01:11:34] 
[01:11:34] 
[01:11:34] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-6.0/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "6.0.0\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--llvm-cxxflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[01:11:34] 
[01:11:34] 
[01:11:34] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:11:34] Build completed unsuccessfully in 0:04:46
[01:11:34] Build completed unsuccessfully in 0:04:46
[01:11:34] make: *** [check] Error 1
[01:11:34] Makefile:48: recipe for target 'check' failed
The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:003c0f34
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
Thu May 30 15:34:02 UTC 2019
---
travis_time:end:00ccfe56:start=1559230443555786556,finish=1559230443560789183,duration=5002627
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:0d8dfc68
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:224bc0bc
travis_time:start:224bc0bc
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:03e06140
$ dmesg | grep -i kill

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@Centril Centril force-pushed the Centril:stabilize-underscore_const_names branch from 85b1489 to 63829d2 May 30, 2019

@Centril Centril added I-nominated and removed I-nominated labels May 30, 2019

@Centril Centril changed the title [WIP] Stabilize underscore_const_names in 1.37.0 Stabilize underscore_const_names in 1.37.0 May 31, 2019

@Centril

This comment has been minimized.

Copy link
Member Author

commented May 31, 2019

Stabilization proposal

I propose that we stabilize #![feature(underscore_const_names)].

@rfcbot merge

Tracking issue: #54912
Version target: 1.37 (2019-07-04 => beta, 2019-08-15 => stable).

What is stabilized

You are now permitted to write:

const _: $type_expression = $term_expression;

That is, we change the grammar of items, as written in the .lyg notation, from:

Item = attrs:OuterAttr* vis:Vis? kind:ItemKind;
ItemKind =
  | ...
  | Const:{ "const" name:IDENT ":" ty:Type "=" value:Expr ";" }
  | ...
  ;

into:

Item = attrs:OuterAttr* vis:Vis? kind:ItemKind;
ItemKind =
  | ...
  | Const:{ "const" name:IdentOrUnderscore ":" ty:Type "=" value:Expr ";" }
  | ...
  ;

IdentOrUnderscore =
  | Named:IDENT
  | NoName:"_"
  ;

When name = NoName occurs then there are no run-time semantics because an unnamed constant cannot be referred to. With respect to compile-time dynamic semantics, the same rules apply as an unused constant has today. E.g., if you have const _: () = <diverges>; then #[deny(const_err)] will trigger. As for static semantics, an unnamed constant item behaves as normal with respect to type checking.

What is not stabilized

  • Only a free const item may use _ as its name. Associated ones may not.
  • Non-const items may not use _ as a name. Notably, static items may not.
  • const items may not use arbitrary irrefutable patterns. E.g., we do not permit const (A, B): (u8, u8) = (1, 2);

Divergences from RFC and unresolved questions

None.

Tests

The tests can be primarily seen in the PR itself. Here are some of them:

History

  • In #48922 import renaming with _ was implemented.
    The PR was written by @petrochenkov, reviewed by @nikomatsakis, and was merged on 2018-03-16.
    The PR added the now stabilized underscore_imports feature under which you may write e.g.

    extern crate foo as _;
    use bar as _;
  • RFC 2526 by @joshlf then proposed to add const _: $type = $expr; and was merged on 2018-10-08 after which the tracking issue #54912 was filed.

  • The underscore_const_names feature was then implemented in #55015 on 2018-10-14 by @dsciarra. The PR was reviewed by @petrochenkov.

  • In #54912 (comment), @oli-obk found a stability hole which allowed static _: $type = $expr;. @oli-obk plugged this stability hole in #55983 which was then subsequently beta-backported. This PR, merged on 2019-11-20 was reviewed by @nikomatsakis.

  • In #56392, @petrochenkov adjusted underscore_imports and underscore_const_names such that gensym creation happens first after name resolution. Moreover, the PR, merged on 2018-12-06 and reviewed by @oli-obk, prohibited accidentally implemented static _: $type = $expr.

  • This PR stabilizes underscore_const_names and hardens the tests in some respects.

Motivation

The general motivation for const _: $type = $expr; is to facilitate writing well-behaved macros.
For example, procedural macros such as serde_derive generate a constant item to wrap the implementation into. Another example of this is proptest_derive which generates roughly:

#[allow(non_upper_case_globals)]
const _IMPL_ARBITRARY_FOR_MyType: () = {
    impl proptest::arbitrary::Arbitrary for MyType {
        ...
    }
};

Instead, it would be better to generate:

const _: () = {
    impl proptest::arbitrary::Arbitrary for MyType {
        ...
    }
};

This not only has the advantage of generating less code, but also produces better diagnostics.

Other motivational examples include:

More generally, const _: () = $expr; is an idiom allowing users to type check a piece of code but not necessarily more than that.

Potential concerns

There is some concern that underscore_const_names is an ad-hoc way to achieve the desired outcomes. In particular, instead of supporting identifiers or an underscore, we could support arbitrary irrefutable patterns for const items. Moreover, stabilizing const _ would further diverge constant items from static items which could ostensibly also support underscores or even arbitrary irrefutable patterns. However, there are open semantic questions with static _ and arbitrary irrefutable patterns for const requires more work in the compiler. In any case, the stabilization of const _ still keeps us forward compatible with such extensions and therefore these concerns may be put aside for the time being.

There is also some concern of how const _ would compose with associated constants as well as generic ones. Presumably, something like const (A, _)<T>... does not make sense but we also do not have to support the combination of arbitrary irrefutable patterns and generic constants. As for associated constants, one could imagine defining or providing multiple associated constants through pattern matching one constant expression inside an implementation. All in all, the generalization problems do not seem insurmountable.

Some considered alternatives

Unnamed modules, mod _ { ... }

As an alternative to const _: $type = $expr; one could allow mod _ { ... } instead.
The grammar for mod items would use the same IdentOrUnderscore production. When considering mod _ { ... } note that:

  • It is often the point of const _: $type = $expr; to check that an $expression satisfies some condition, e.g., that it is an expression that does not diverge (const_assert!(...)). In these cases, mod _ { ... } is at a disadvantage because the body accepts items and not expressions. To remedy this, you'd need a const item inside the mod item thus unnecessarily generating more tokens. Meanwhile, fitting an item inside an expr requires less.

  • mod _ { ... } has the same problems wrt. generics as const _: $type = $expr; has. Namely, one could consider generic modules mod _<T, ...> { ... }. However, there's no strange interactions between pattern matching and generics here.

  • mod _ { ... } has fewer interactions and is less generalizable. This can both be a good thing because it is more "complete" sooner but it can also feel more ad-hoc. However, we already have use foo as _; so the production IndentOrUnderscore already exists in stable Rust.

Overall, we believe const _ to be a better fit because it has a natural generalization and works better with macros overall.

const { ... } blocks

Another alternative would be some sort of const { ... } block. This would take the grammatical form:

ItemKind =
  | ...
  | ConstBlock:{ "const" value:Block }
  | ...
  ;

ExprKind =
  | ...
  | ConstBlock:{ "const" value:Block }
  | ...
  ;

Notably, const { ... } would have the double duty as an expression and item form.
Assigning unsurprising semantics to const { ... } as an expression is easy: the block is a const context and as any block it may contain a series of statements followed by an optional tail expression which is the value of the block. As an item, it is less clear what the tail expression would be. Would we require that the tail expression be implicitly coercible to ()? Would we allow a tail expression at all? Overall, a const { ... } is probably a better fit solely as an expression form and not as an item.

Possible future work

As aforementioned, natural extensions to const _: $type = $expr; primarily includes:

  • Extending _ to $pat.
  • Extending _ or $pat to static items as well. In this case we should figure out what consistent, useful, and expected dynamic semantics are for situations such as static (A, _): (u8, u8) = (1, 2);.
  • Finally, we should consider whether it would make sense to extend const _ to associated constants as well and what implications this has for static items.
@rfcbot

This comment has been minimized.

Copy link

commented May 31, 2019

Team member @Centril has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@Centril

This comment has been minimized.

Copy link
Member Author

commented May 31, 2019

N.B. Aaron is on leave so I've checked his box.

@petrochenkov

This comment has been minimized.

Copy link
Contributor

commented May 31, 2019

Implementation LGMT, marking as waiting on team.

@rfcbot

This comment has been minimized.

Copy link

commented Jun 6, 2019

🔔 This is now entering its final comment period, as per the review above. 🔔

@Centril Centril removed the I-nominated label Jun 6, 2019

@bors

This comment was marked as resolved.

Copy link
Contributor

commented Jun 10, 2019

☔️ The latest upstream changes (presumably #61229) made this pull request unmergeable. Please resolve the merge conflicts.

@Centril Centril force-pushed the Centril:stabilize-underscore_const_names branch from 286ad9c to e62c9d7 Jun 10, 2019

@brson

This comment has been minimized.

Copy link
Contributor

commented Jun 14, 2019

Looks like quite a hack to achieve the stated outcome. Reminds me of javascript.

@rfcbot

This comment has been minimized.

Copy link

commented Jun 16, 2019

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

The RFC will be merged soon.

@Centril

This comment has been minimized.

Copy link
Member Author

commented Jun 16, 2019

@bors r=petrochenkov

@bors

This comment has been minimized.

Copy link
Contributor

commented Jun 16, 2019

📌 Commit e62c9d7 has been approved by petrochenkov

@bors

This comment has been minimized.

Copy link
Contributor

commented Jun 16, 2019

⌛️ Testing commit e62c9d7 with merge 4edff84...

bors added a commit that referenced this pull request Jun 16, 2019
Auto merge of #61347 - Centril:stabilize-underscore_const_names, r=pe…
…trochenkov

Stabilize underscore_const_names in 1.37.0

You are now permitted to write:

```rust
const _: $type_expression = $term_expression;
```

That is, we change the [grammar of items](https://github.com/rust-lang-nursery/wg-grammar/blob/9d1984d7ae8d6576f943566539a31a5800644c57/grammar/item.lyg#L3-L42), as written in [the *`.lyg`* notation](https://github.com/rust-lang/gll/tree/263bf161dad903e67aa65fc591ced3cab18afa2a#grammar), from:

```java
Item = attrs:OuterAttr* vis:Vis? kind:ItemKind;
ItemKind =
  | ...
  | Const:{ "const" name:IDENT ":" ty:Type "=" value:Expr ";" }
  | ...
  ;
```

into:

```java
Item = attrs:OuterAttr* vis:Vis? kind:ItemKind;
ItemKind =
  | ...
  | Const:{ "const" name:IdentOrUnderscore ":" ty:Type "=" value:Expr ";" }
  | ...
  ;

IdentOrUnderscore =
  | Named:IDENT
  | NoName:"_"
  ;
```

r? @petrochenkov
@bors

This comment has been minimized.

Copy link
Contributor

commented Jun 16, 2019

☀️ Test successful - checks-travis, status-appveyor
Approved by: petrochenkov
Pushing 4edff84 to master...

@bors bors added the merged-by-bors label Jun 16, 2019

@bors bors merged commit e62c9d7 into rust-lang:master Jun 16, 2019

2 checks passed

Travis CI - Pull Request Build Passed
Details
homu Test successful
Details

@Centril Centril deleted the Centril:stabilize-underscore_const_names branch Jun 16, 2019

@nvzqz

This comment has been minimized.

Copy link
Contributor

commented Aug 12, 2019

Thanks @Centril for putting in the work in getting this feature stabilized. With it, I should be able to release 1.0 of static_assertions with the release of 1.37.0 this Thursday! 🎉

@Centril

This comment has been minimized.

Copy link
Member Author

commented Aug 13, 2019

@nvzqz Happy to see this already having a nice impact! :)

Maybe we can start using static_assertions in the compiler as well? -- cc @Zoxc

@eddyb

This comment has been minimized.

Copy link
Member

commented Aug 14, 2019

I think we have our own hacky version in rustc_data_structures?
Besides, const _: () = assert!(...); is the static_assert! we want 😉

@Centril

This comment has been minimized.

Copy link
Member Author

commented Aug 14, 2019

@nvzqz

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2019

The crate offers functionality outside of const_assert! that the compiler could also leverage. Not sure where exactly since I'm not sufficiently familiar with its internals.

@eddyb I hope to make const_assert! wrap around assert! like that someday. It would produce significantly better error messages.

netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Aug 29, 2019
he
Update rust to version 1.37.0
Pkgsrc changes:
 * Add a patch to llvm to deal with const dli_saddr.
 * Adapt two other patches.
 * Cross-build currently fails, so i386, powerpc and sparc64 bootstrap
   kits for 1.37.0 are built natively.  Missing aarch64 hardware, so that's
   not available yet.
 * Bump bootstrap requirements to 1.36.0 except for armv7-unknown-netbsd-eabihf
   which I've not managed to cross-build.

Upstream changes:

Version 1.37.0 (2019-08-15)
==========================

Language
--------
- `#[must_use]` will now warn if the type is contained in a [tuple][61100],
  [`Box`][62228], or an [array][62235] and unused.
- [You can now use the `cfg` and `cfg_attr` attributes on
  generic parameters.][61547]
- [You can now use enum variants through type alias.][61682] e.g. You can
  write the following:
  ```rust
  type MyOption = Option<u8>;

  fn increment_or_zero(x: MyOption) -> u8 {
      match x {
          MyOption::Some(y) => y + 1,
          MyOption::None => 0,
      }
  }
  ```
- [You can now use `_` as an identifier for consts.][61347] e.g. You can write
  `const _: u32 = 5;`.
- [You can now use `#[repr(align(X)]` on enums.][61229]
- [The  `?`/_"Kleene"_ macro operator is now available in the
  2015 edition.][60932]

Compiler
--------
- [You can now enable Profile-Guided Optimization with the `-C profile-generate`
  and `-C profile-use` flags.][61268] For more information on how to use profile
  guided optimization, please refer to the [rustc book][rustc-book-pgo].
- [The `rust-lldb` wrapper script should now work again.][61827]

Libraries
---------
- [`mem::MaybeUninit<T>` is now ABI-compatible with `T`.][61802]

Stabilized APIs
---------------
- [`BufReader::buffer`]
- [`BufWriter::buffer`]
- [`Cell::from_mut`]
- [`Cell<[T]>::as_slice_of_cells`][`Cell<slice>::as_slice_of_cells`]
- [`DoubleEndedIterator::nth_back`]
- [`Option::xor`]
- [`Wrapping::reverse_bits`]
- [`i128::reverse_bits`]
- [`i16::reverse_bits`]
- [`i32::reverse_bits`]
- [`i64::reverse_bits`]
- [`i8::reverse_bits`]
- [`isize::reverse_bits`]
- [`slice::copy_within`]
- [`u128::reverse_bits`]
- [`u16::reverse_bits`]
- [`u32::reverse_bits`]
- [`u64::reverse_bits`]
- [`u8::reverse_bits`]
- [`usize::reverse_bits`]

Cargo
-----
- [`Cargo.lock` files are now included by default when publishing executable crates
  with executables.][cargo/7026]
- [You can now specify `default-run="foo"` in `[package]` to specify the
  default executable to use for `cargo run`.][cargo/7056]

Misc
----

Compatibility Notes
-------------------
- [Using `...` for inclusive range patterns will now warn by default.][61342]
  Please transition your code to using the `..=` syntax for inclusive
  ranges instead.
- [Using a trait object without the `dyn` will now warn by default.][61203]
  Please transition your code to use `dyn Trait` for trait objects instead.

[62228]: rust-lang/rust#62228
[62235]: rust-lang/rust#62235
[61802]: rust-lang/rust#61802
[61827]: rust-lang/rust#61827
[61547]: rust-lang/rust#61547
[61682]: rust-lang/rust#61682
[61268]: rust-lang/rust#61268
[61342]: rust-lang/rust#61342
[61347]: rust-lang/rust#61347
[61100]: rust-lang/rust#61100
[61203]: rust-lang/rust#61203
[61229]: rust-lang/rust#61229
[60932]: rust-lang/rust#60932
[cargo/7026]: rust-lang/cargo#7026
[cargo/7056]: rust-lang/cargo#7056
[`BufReader::buffer`]: https://doc.rust-lang.org/std/io/struct.BufReader.html#method.buffer
[`BufWriter::buffer`]: https://doc.rust-lang.org/std/io/struct.BufWriter.html#method.buffer
[`Cell::from_mut`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.from_mut
[`Cell<slice>::as_slice_of_cells`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_slice_of_cells
[`DoubleEndedIterator::nth_back`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.nth_back
[`Option::xor`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.xor
[`RefCell::try_borrow_unguarded`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.try_borrow_unguarded
[`Wrapping::reverse_bits`]: https://doc.rust-lang.org/std/num/struct.Wrapping.html#method.reverse_bits
[`i128::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i128.html#method.reverse_bits
[`i16::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i16.html#method.reverse_bits
[`i32::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i32.html#method.reverse_bits
[`i64::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i64.html#method.reverse_bits
[`i8::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i8.html#method.reverse_bits
[`isize::reverse_bits`]: https://doc.rust-lang.org/std/primitive.isize.html#method.reverse_bits
[`slice::copy_within`]: https://doc.rust-lang.org/std/primitive.slice.html#method.copy_within
[`u128::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u128.html#method.reverse_bits
[`u16::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u16.html#method.reverse_bits
[`u32::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u32.html#method.reverse_bits
[`u64::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u64.html#method.reverse_bits
[`u8::reverse_bits`]: https://doc.rust-lang.org/std/primitive.u8.html#method.reverse_bits
[`usize::reverse_bits`]: https://doc.rust-lang.org/std/primitive.usize.html#method.reverse_bits
[rustc-book-pgo]: https://doc.rust-lang.org/rustc/profile-guided-optimization.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants
You can’t perform that action at this time.