Skip to content

Conversation

@dtolnay
Copy link
Owner

@dtolnay dtolnay commented May 22, 2019

Ref #1. Try cargo check and observe that this code compiles successfully despite the assertions being violated. Both generated consts are visible in the output of cargo expand.

#![feature(prelude_import)]
#![no_std]
#![feature(const_panic, underscore_const_names)]
#[prelude_import]
use ::std::prelude::v1::*;
#[macro_use]
extern crate std as std;
use bitfield::*;
fn __bitfield() {
    const _: () = [()][(0
        + <B1 as bitfield::Field>::BITS
        + <B3 as bitfield::Field>::BITS
        + <B4 as bitfield::Field>::BITS
        + <B23 as bitfield::Field>::BITS)
        % 8];
    const _: () = {
        ::std::rt::begin_panic(
            "Hello world at compile-time!",
            &("bitfield-assertion/demo/main.rs", 5u32, 1u32),
        )
    };
}
fn main() {}

@rodrimati1992
Copy link

rodrimati1992 commented May 22, 2019

Using these Rust versions:

  • nightly-2019-04-01-i686-unknown-linux-gnu

  • nightly-2019-04-11-i686-unknown-linux-gnu

  • nightly-2019-05-01-i686-unknown-linux-gnu

  • nightly-i686-unknown-linux-gnu rustc 1.36.0-nightly (50a0defd5 2019-05-21)

The output of cargo check using each Rust version
(every version has the exact same output):

   Compiling proc-macro2 v0.4.30
   Compiling unicode-xid v0.1.0
   Compiling syn v0.15.34
   Compiling quote v0.6.12
   Compiling bitfield-impl v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo/impl)
    Checking bitfield v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo/bitfield)
    Checking testing v0.1.0 (/home/matias/Documents/eclipse_workspace/tmp/testing)
warning: unused import: `::std::prelude::v1::*`
 --> src/lib.rs:6:5
  |
6 | use ::std::prelude::v1::*;
  |     ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_imports)] on by default

warning: unused `#[macro_use]` import
 --> src/lib.rs:7:1
  |
7 | #[macro_use]
  | ^^^^^^^^^^^^

warning: function is never used: `main`
  --> src/lib.rs:28:1
   |
28 | fn main() {}
   | ^^^^^^^^^
   |
   = note: #[warn(dead_code)] on by default

error: any use of this value will cause an error
  --> src/lib.rs:15:19
   |
15 |        const _: () = [()][(0
   |   _____-_____________^
   |  |_____|
   | ||
16 | ||         + <B1 as bitfield::Field>::BITS
17 | ||         + <B3 as bitfield::Field>::BITS
18 | ||         + <B4 as bitfield::Field>::BITS
19 | ||         + <B23 as bitfield::Field>::BITS)
20 | ||         % 8];
   | ||____________^-
   |  |____________|
   |               index out of bounds: the len is 1 but the index is 7
   |
   = note: #[deny(const_err)] on by default

error: any use of this value will cause an error
  --> src/lib.rs:22:9
   |
21 |  /     const _: () = {
22 |  |         ::std::rt::begin_panic(
   |  |_________^
23 | ||             "Hello world at compile-time!",
24 | ||             &("bitfield-assertion/demo/main.rs", 5u32, 1u32),
25 | ||         )
   | ||_________^ the evaluated program panicked at 'Hello world at compile-time!', bitfield-assertion/demo/main.rs:5:1
26 |  |     };
   |  |______-

error: aborting due to 2 previous errors

Cargo.toml:

[package]
name = "testing"
version = "0.1.0"
authors = []
edition = "2018"

[dependencies]
bitfield = {path="../case-studies/bitfield-assertion/demo/bitfield/"}

Ùsed git clone to get case-studies.

Code in lib.rs:

#![feature(libstd_sys_internals)]
#![feature(prelude_import)]
#![no_std]
#![feature(const_panic, underscore_const_names)]
#[prelude_import]
use ::std::prelude::v1::*;
#[macro_use]
extern crate std as std;
use bitfield::*;




fn __bitfield() {
    const _: () = [()][(0
        + <B1 as bitfield::Field>::BITS
        + <B3 as bitfield::Field>::BITS
        + <B4 as bitfield::Field>::BITS
        + <B23 as bitfield::Field>::BITS)
        % 8];
    const _: () = {
        ::std::rt::begin_panic(
            "Hello world at compile-time!",
            &("bitfield-assertion/demo/main.rs", 5u32, 1u32),
        )
    };
}
fn main() {}

You are overly eager to close issues,didn't even mention my code example compiles for you.

@dtolnay
Copy link
Owner Author

dtolnay commented May 22, 2019

Could you please confirm that the following script does not produce errors when you run it locally?

#!/bin/bash

set -xe
rustup update nightly-2019-05-22
git clone https://github.com/dtolnay/case-studies
cd case-studies/bitfield-assertion/demo
git fetch origin refs/pull/6/head
git checkout FETCH_HEAD
cargo +nightly-2019-05-22 check
cargo expand
echo wow

@rodrimati1992
Copy link

rodrimati1992 commented May 22, 2019

I ran that script,here is the entire output:

+ rustup update nightly-2019-05-22
info: syncing channel updates for 'nightly-2019-05-22-i686-unknown-linux-gnu'

  nightly-2019-05-22-i686-unknown-linux-gnu unchanged - rustc 1.36.0-nightly (50a0defd5 2019-05-21)

info: checking for self-updates
+ git clone https://github.com/dtolnay/case-studies
Cloning into 'case-studies'...
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 176 (delta 1), reused 4 (delta 0), pack-reused 166
Receiving objects: 100% (176/176), 75.41 KiB | 0 bytes/s, done.
Resolving deltas: 100% (58/58), done.
Checking connectivity... done.
+ cd case-studies/bitfield-assertion/demo
+ git fetch origin refs/pull/6/head
remote: Enumerating objects: 15, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 8 (delta 3), reused 8 (delta 3), pack-reused 0
Unpacking objects: 100% (8/8), done.
From https://github.com/dtolnay/case-studies
 * branch            refs/pull/6/head -> FETCH_HEAD
+ git checkout FETCH_HEAD
Note: checking out 'FETCH_HEAD'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 274712c... Const _: () is not evaluated
+ cargo +nightly-2019-05-22 check
    Updating crates.io index
   Compiling proc-macro2 v0.4.30
   Compiling unicode-xid v0.1.0
   Compiling syn v0.15.34
   Compiling quote v0.6.12
   Compiling bitfield-impl v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo/impl)
    Checking bitfield v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo/bitfield)
    Checking case-study-bitfield-assertion v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo)
    Finished dev [unoptimized + debuginfo] target(s) in 43.68s
+ cargo expand
    Checking case-study-bitfield-assertion v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo)
    Finished dev [unoptimized + debuginfo] target(s) in 5.90s

#![feature(prelude_import)]
#![no_std]
#![feature(const_panic, underscore_const_names)]
#[prelude_import]
use ::std::prelude::v1::*;
#[macro_use]
extern crate std as std;
use bitfield::*;
fn __bitfield() {
    const _: () = [()][(0
        + <B1 as bitfield::Field>::BITS
        + <B3 as bitfield::Field>::BITS
        + <B4 as bitfield::Field>::BITS
        + <B23 as bitfield::Field>::BITS)
        % 8];
    const _: () = {
        ::std::rt::begin_panic(
            "Hello world at compile-time!",
            &("bitfield-assertion/demo/main.rs", 5u32, 1u32),
        )
    };
}
fn main() {}
+ echo wow
wow

What's weird is that if I replace main.rs with the output of cargo expand I get this error:

cargo +nightly-2019-05-22 check
    Checking case-study-bitfield-assertion v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo)
warning: unused import: `::std::prelude::v1::*`
 --> bitfield-assertion/demo/main.rs:6:5
  |
6 | use ::std::prelude::v1::*;
  |     ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_imports)] on by default

warning: unused `#[macro_use]` import
 --> bitfield-assertion/demo/main.rs:7:1
  |
7 | #[macro_use]
  | ^^^^^^^^^^^^

error[E0658]: use of unstable library feature 'libstd_sys_internals': used by the panic! macro
  --> bitfield-assertion/demo/main.rs:18:9
   |
18 |         ::std::rt::begin_panic(
   |         ^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: add #![feature(libstd_sys_internals)] to the crate attributes to enable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
error: Could not compile `case-study-bitfield-assertion`.

Ànd if I add #![feature(libstd_sys_internals)] as the first line of the expanded code it produces the const error like in my previous comment:

cargo +nightly-2019-05-22 check
    Checking case-study-bitfield-assertion v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo)
warning: unused import: `::std::prelude::v1::*`
 --> bitfield-assertion/demo/main.rs:6:5
  |
6 | use ::std::prelude::v1::*;
  |     ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_imports)] on by default

warning: unused `#[macro_use]` import
 --> bitfield-assertion/demo/main.rs:7:1
  |
7 | #[macro_use]
  | ^^^^^^^^^^^^

error: any use of this value will cause an error
  --> bitfield-assertion/demo/main.rs:11:19
   |
11 |        const _: () = [()][(0
   |   _____-_____________^
   |  |_____|
   | ||
12 | ||         + <B1 as bitfield::Field>::BITS
13 | ||         + <B3 as bitfield::Field>::BITS
14 | ||         + <B4 as bitfield::Field>::BITS
15 | ||         + <B23 as bitfield::Field>::BITS)
16 | ||         % 8];
   | ||____________^-
   |  |____________|
   |               index out of bounds: the len is 1 but the index is 7
   |
   = note: #[deny(const_err)] on by default

error: any use of this value will cause an error
  --> bitfield-assertion/demo/main.rs:18:9
   |
17 |  /     const _: () = {
18 |  |         ::std::rt::begin_panic(
   |  |_________^
19 | ||             "Hello world at compile-time!",
20 | ||             &("bitfield-assertion/demo/main.rs", 5u32, 1u32),
21 | ||         )
   | ||_________^ the evaluated program panicked at 'Hello world at compile-time!', bitfield-assertion/demo/main.rs:5:1
22 |  |     };
   |  |______-

error: aborting due to 2 previous errors

error: Could not compile `case-study-bitfield-assertion`.


Fixed macro expanded main.rs(which produces the const error):

#![feature(libstd_sys_internals)]
#![feature(prelude_import)]
#![no_std]
#![feature(const_panic, underscore_const_names)]
#[prelude_import]
use ::std::prelude::v1::*;
#[macro_use]
extern crate std as std;
use bitfield::*;
fn __bitfield() {
    const _: () = [()][(0
        + <B1 as bitfield::Field>::BITS
        + <B3 as bitfield::Field>::BITS
        + <B4 as bitfield::Field>::BITS
        + <B23 as bitfield::Field>::BITS)
        % 8];
    const _: () = {
        ::std::rt::begin_panic(
            "Hello world at compile-time!",
            &("bitfield-assertion/demo/main.rs", 5u32, 1u32),
        )
    };
}
fn main() {}

@rodrimati1992
Copy link

rodrimati1992 commented May 22, 2019

The problem seems to be that the constants outputed by proc-macros are not evaluated in cargo check unless they are used in types.

I got the macro to error with :

TokenStream::from(quote! {
    fn _bitfield() {
        const E0: usize = [0][(0 #(+ <#fields as bitfield::Field>::BITS)*) % 8];
        const E1: usize = panic!("Hello world at compile-time!");
        let _:[();E0];
        let _:[();E1];
    }
})

But I get an unhelpful error:

   Compiling bitfield-impl v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo/impl)
    Checking bitfield v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo/bitfield)
    Checking case-study-bitfield-assertion v0.0.0 (/home/matias/Documents/eclipse_workspace/tmp/case-studies/bitfield-assertion/demo)
error[E0080]: evaluation of constant value failed
 --> bitfield-assertion/demo/main.rs:5:1
  |
5 | #[bitfield] // (1+3+4+23)%8 != 0
  | ^^^^^^^^^^^ referenced constant has errors

error: aborting due to previous error

@dtolnay
Copy link
Owner Author

dtolnay commented May 22, 2019

Right. It looks like what you are showing is basically First attempt but now with two extra unstable features. This is the behavior described in that section and the error message shown in that section.

@rodrimati1992
Copy link

rodrimati1992 commented May 22, 2019

This entire thing looks like a bug that needs to be reported,I don't understand why expanding a macro would change whether a constant is evaluated,or why it wouldn't report the error that the generated code produces(rather than just saying "referenced constant has errors" without any details).

@dtolnay
Copy link
Owner Author

dtolnay commented May 22, 2019

Possibly! Want to follow up with a compiler bug report? Let me know if it ends up getting fixed in a way that would make it possible to do an error message that is better than the solution in the case study.

@rodrimati1992
Copy link

Yes,I will start by looking for similar issues,and if I don't find any recent report of this I will create an issue for "macro generated code doesn't evaluate panicking consts when the expanded code does".

@dtolnay
Copy link
Owner Author

dtolnay commented May 22, 2019

Nice, thanks a lot!

@rodrimati1992
Copy link

Filed an issue for the different behavior in constants:rust-lang/rust#61058

@CreepySkeleton
Copy link

CreepySkeleton commented Jan 22, 2020

For the sake of history: this seems to be fixed by rust-lang/rust@643261a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants