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 2342, "Allow if and match in constants" #49146

Closed
3 of 4 tasks
Centril opened this issue Mar 18, 2018 · 86 comments · Fixed by #72437
Closed
3 of 4 tasks

Tracking issue for RFC 2342, "Allow if and match in constants" #49146

Centril opened this issue Mar 18, 2018 · 86 comments · Fixed by #72437
Labels
A-const-eval Area: constant evaluation (mir interpretation) A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. B-RFC-approved Feature: Approved by a merged RFC but not yet implemented. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@Centril
Copy link
Contributor

Centril commented Mar 18, 2018

This is a tracking issue for the RFC "Allow if and match in constants" (rust-lang/rfcs#2342).

Please redirect constification of specific functions or issues you want to report to fresh issues and label them appropriately with F-const_if_match so that this issues doesn't get flooded with ephemeral comments obscuring important developments.

Steps:

Unresolved questions:

None

@Centril Centril added B-RFC-approved Feature: Approved by a merged RFC but not yet implemented. T-lang Relevant to the language team, which will review and decide on the PR/issue. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. labels Mar 18, 2018
@oli-obk
Copy link
Contributor

oli-obk commented Mar 19, 2018

  1. add a feature gate for it
  2. switch and switchInt terminators in https://github.com/rust-lang/rust/blob/master/src/librustc_mir/transform/qualify_consts.rs#L347 need to have custom code in case the feature gate is active
  3. instead of having a single current basic block (https://github.com/rust-lang/rust/blob/master/src/librustc_mir/transform/qualify_consts.rs#L328) this needs to be some container that has a list of basic blocks it still has to process.

@eddyb
Copy link
Member

eddyb commented Mar 19, 2018

@oli-obk It's a bit trickier because the complex control-flow means dataflow analysis needs to be employed. I need to get back to @alexreg and figure out how to integrate their changes.

@alexreg
Copy link
Contributor

alexreg commented Mar 19, 2018

@eddyb A good starting point would probably be to take my const-qualif branch (minus the top commit), rebase it over master (not going to be fun), and then add data annotation stuff, right?

@mark-i-m

This comment has been minimized.

@alexreg
Copy link
Contributor

alexreg commented Apr 26, 2018

@mark-i-m Alas no. I think @eddyb has been very busy indeed, because I've not even been able to ping him on IRC for the last few weeks hah. Sadly my const-qualif branch doesn't even compile since I last rebased it over master. (I don't believe I've pushed yet though.)

thread 'main' panicked at 'assertion failed: position <= slice.len()', libserialize/leb128.rs:97:1
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: Could not compile `rustc_llvm`.

Caused by:
  process didn't exit successfully: `/Users/alex/Software/rust/build/bootstrap/debug/rustc --crate-name build_script_build librustc_llvm/build.rs --error-format json --crate-type bin --emit=dep-info,link -C opt-level=2 -C metadata=74f2a810ad96be1d -C extra-filename=-74f2a810ad96be1d --out-dir /Users/alex/Software/rust/build/x86_64-apple-darwin/stage1-rustc/release/build/rustc_llvm-74f2a810ad96be1d -L dependency=/Users/alex/Software/rust/build/x86_64-apple-darwin/stage1-rustc/release/deps --extern build_helper=/Users/alex/Software/rust/build/x86_64-apple-darwin/stage1-rustc/release/deps/libbuild_helper-89aaac40d3077cd7.rlib --extern cc=/Users/alex/Software/rust/build/x86_64-apple-darwin/stage1-rustc/release/deps/libcc-ead7d4af4a69e776.rlib` (exit code: 101)
warning: build failed, waiting for other jobs to finish...
error: build failed
command did not execute successfully: "/Users/alex/Software/rust/build/x86_64-apple-darwin/stage0/bin/cargo" "build" "--target" "x86_64-apple-darwin" "-j" "8" "--release" "--manifest-path" "/Users/alex/Software/rust/src/librustc_trans/Cargo.toml" "--features" " jemalloc" "--message-format" "json"
expected success, got: exit code: 101
thread 'main' panicked at 'cargo must succeed', bootstrap/compile.rs:1085:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
failed to run: /Users/alex/Software/rust/build/bootstrap/debug/bootstrap -i build

@alexreg
Copy link
Contributor

alexreg commented Apr 26, 2018

Okay, funnily enough, I rebased again just today and it seems to be building all fine now! Looks like there was a regression, and it just got fixed. All over to @eddyb now.

@eddyb
Copy link
Member

eddyb commented Apr 26, 2018

@alexreg Sorry, I've switched to a local sleep schedule and I see you've pinged me when I wake up but then you're offline all day when I'm awake (ugh timezones).
Should I just make a PR out of your branch? I forgot what we were supposed to do with it?

@alexreg
Copy link
Contributor

alexreg commented Apr 26, 2018

@eddyb That's alright heh. You must be off to bed early, since I'm usually on from 8:00PM GMT, but it's all good! :-)

kennytm added a commit to kennytm/rust that referenced this issue Apr 30, 2018
Make `Vec::new` a `const fn`

`RawVec::empty/_in` are a hack. They're there because `if size_of::<T> == 0 { !0 } else { 0 }` is not allowed in `const` yet. However, because `RawVec` is unstable, the `empty/empty_in` constructors can be removed when rust-lang#49146 is done...
@eddyb
Copy link
Member

eddyb commented May 4, 2018

I'm really sorry, took me a while to realize that the series of patches in question requires removing Qualif::STATIC{,_REF}, i.e. the errors about accessing statics at compile-time. OTOH, this is already broken in terms of const fns and access to statics:

#![feature(const_fn)]
const fn read<T: Copy>(x: &T) -> T { *x }
static FOO: u32 = read(&BAR);
static BAR: u32 = 5;
fn main() {
    println!("{}", FOO);
}

This is not detected statically, instead miri complains that "dangling pointer was dereferenced" (which should really say something about statics instead of "dangling pointer").

So I think reading statics at compile-time should be fine, but some people want const fn to be "pure" (i.e. "referentially transparent" or thereabouts) at runtime, which would mean that a const fn reading from behind a reference it got as an argument is fine, but a const fn should never be able to obtain a reference to a static out of thin air (including from consts).

I think then we can keep statically denying mentioning statics (even if only to take their reference) in consts, const fn, and other constant contexts (including promoteds).
But we still have to remove the STATIC_REF hack which allows statics to take the reference of other statics but (poorly tries and fails to) deny reading from behind those references.

Do we need an RFC for this?

@alexreg
Copy link
Contributor

alexreg commented May 4, 2018

Sounds fair w.r.t. reading from statics. Doubt it needs an RFC, maybe just a crater run, but then I’m probably not the best one to say.

@eddyb
Copy link
Member

eddyb commented May 4, 2018

Note that we wouldn't be restricting anything, we'd be relaxing a restriction that's already broken.

@alexreg
Copy link
Contributor

alexreg commented May 4, 2018

Oh, I misread. So const evaluation would still be sound, just not referentially transparent?

@eddyb
Copy link
Member

eddyb commented May 4, 2018

The last paragraph describes a referentially transparent approach (but we lose that property if we start allowing mentioning statics in consts and const fns). I don't think soundness was really under discussion.

@alexreg
Copy link
Contributor

alexreg commented May 4, 2018

Well, "dangling pointer" sure sounds like a soundness issue, but I'll trust you on this!

@eddyb
Copy link
Member

eddyb commented May 4, 2018

"dangling pointer" is a bad error message, that's just miri forbidding reading from statics. The only constant contexts that can even refer to statics are other statics, so we could "just" allow those reads, since all of that code always runs once, at compile-time.

(from IRC) To summarize, referentially transparent const fn could only ever reach frozen allocations, without going through arguments, which means const needs the same restriction, and non-frozen allocations can only come from statics.

@Centril
Copy link
Contributor Author

Centril commented May 4, 2018

I do like preserving referential transparency so @eddyb's idea sounds fantastic!

@alexreg
Copy link
Contributor

alexreg commented May 4, 2018

Yeah I’m pro making const fns pure as well.

@eddyb
Copy link
Member

eddyb commented May 4, 2018

Please note that certain seemingly harmless plans could ruin referential transparency, e.g.:

let x = 0;
let non_deterministic = &x as *const _ as usize;
if non_deterministic.count_ones() % 2 == 0 {
    // do one thing
} else {
    // do a completely different thing
}

This would fail with a miri error at compile-time, but would be non-deterministic at runtime (because we can't mark that memory address as "abstract" like miri can).

EDIT: @Centril had the idea of making certain raw pointer operations (such as comparisons and casts to integers) unsafe within const fn (which we can do up until we stabilize const fn), and state that they can only be used in ways that miri would allow at compile-time.
For example, subtracting two pointers into the same local should be fine (you get a relative distance that only depends on the type layout, array indices, etc.), but formatting the address of a reference (via {:p}) is an incorrect use and therefore fmt::Pointer::fmt can't be marked const fn.
Also none of the Ord / Eq trait impls for raw pointers can be marked as const (whenever we get the ability to annotate them as such), because they're safe but the operation is unsafe in const fn.

@alexreg
Copy link
Contributor

alexreg commented May 4, 2018

Depends what you mean by "harmless"... I can certainly see reason we'd want to ban such non-deterministic behaviour.

bors added a commit that referenced this issue May 8, 2018
lint: deny incoherent_fundamental_impls by default

Warn the ecosystem of the pending intent-to-disallow in #49799.

There are 4 ICEs on my machine, look unrelated (having happened before in #49146 (comment))

```rust
thread 'main' panicked at 'assertion failed: position <= slice.len()', libserialize/leb128.rs:97:1
```

```
    [run-pass] run-pass/allocator/xcrate-use2.rs
    [run-pass] run-pass/issue-12133-3.rs
    [run-pass] run-pass/issue-32518.rs
    [run-pass] run-pass/trait-default-method-xc-2.rs
```

r? @nikomatsakis
@lachlansneff
Copy link

It would be fantastic if work were continued on this.

r-bk added a commit to r-bk/rsdns that referenced this issue Mar 20, 2021
async-std started failing to compile on 1.45 due to a new indirect
dependency 'socket2' which in version 0.4.0 fails with the following
error:

   Compiling socket2 v0.4.0
error[E0658]: `match` is not allowed in a `const fn`
   --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/socket2-0.4.0/src/lib.rs:156:9
    |
156 | /         match address {
157 | |             SocketAddr::V4(_) => Domain::IPV4,
158 | |             SocketAddr::V6(_) => Domain::IPV6,
159 | |         }
    | |_________^
    |
    = note: see issue #49146 <rust-lang/rust#49146> for more information

   Compiling signal-hook-registry v1.3.0
error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
error: could not compile `socket2`.
r-bk added a commit to r-bk/rsdns that referenced this issue Mar 21, 2021
async-std started failing to compile on 1.45 due to a new indirect
dependency 'socket2' which in version 0.4.0 fails with the following
error:

   Compiling socket2 v0.4.0
error[E0658]: `match` is not allowed in a `const fn`
   --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/socket2-0.4.0/src/lib.rs:156:9
    |
156 | /         match address {
157 | |             SocketAddr::V4(_) => Domain::IPV4,
158 | |             SocketAddr::V6(_) => Domain::IPV6,
159 | |         }
    | |_________^
    |
    = note: see issue #49146 <rust-lang/rust#49146> for more information

   Compiling signal-hook-registry v1.3.0
error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
error: could not compile `socket2`.
StormRat referenced this issue in rust-lang/crates.io-index Mar 26, 2021
timvisee added a commit to timvisee/ffsend that referenced this issue Apr 9, 2021
fishilico added a commit to fishilico/shared that referenced this issue Apr 26, 2021
socket crate became incompatible with Alpine 3.12 toolchain (rust 1.44)

    error[E0658]: `match` is not allowed in a `const fn`
       --> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/socket2-0.4.0/src/lib.rs:156:9
        |
    156 | /         match address {
    157 | |             SocketAddr::V4(_) => Domain::IPV4,
    158 | |             SocketAddr::V6(_) => Domain::IPV6,
    159 | |         }
        | |_________^
        |
        = note: see issue #49146 <rust-lang/rust#49146> for more information
mauriciojost added a commit to mauriciojost/rust-esp-nix that referenced this issue May 29, 2021
I need it to enable some attributes that are otherwise not available,
this all is to avoid

error[E0658]: `if` is not allowed in a `const`
-->
/home/mjost/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.43/src/int/specialized_div_rem/mod.rs:84:12
   |
84 |       } else if cfg!(any(target_arch = "sparc", target_arch =
"sparc64")) {
   |  ____^
85 | |         // LZD or LZCNT on SPARC only exists for the VIS 3
extension and later.
86 | |         cfg!(target_feature = "vis3")
87 | |     } else if cfg!(any(target_arch = "riscv32", target_arch =
"riscv64")) {
...  |
92 | |         true
93 | |     }
   | |___^
|
= note: see issue #49146
<rust-lang/rust#49146> for more information
= help: add `#![feature(const_if_match)]` to the crate attributes to
enable
@nickfarrow
Copy link

I was able to fix this error by running rustup update

kodiakhq bot pushed a commit to sbdchd/squawk that referenced this issue Oct 31, 2021
For some reason ran into rust-lang/rust#65721 and rust-lang/rust#49146 along with some other misc compiler errors and lints

Feels like every time I come back to this project the rust versions get out of wack
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: constant evaluation (mir interpretation) A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. B-RFC-approved Feature: Approved by a merged RFC but not yet implemented. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.