{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/1383","repository_url":"https://api.github.com/repos/rust-lang/rfcs","labels_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1383/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1383/comments","events_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1383/events","html_url":"https://github.com/rust-lang/rfcs/issues/1383","id":119205941,"number":1383,"title":"const fn's should allow (and eval) assert! and debug_assert! statements","user":{"login":"pnkfelix","id":173127,"avatar_url":"https://avatars.githubusercontent.com/u/173127?v=3","gravatar_id":"","url":"https://api.github.com/users/pnkfelix","html_url":"https://github.com/pnkfelix","followers_url":"https://api.github.com/users/pnkfelix/followers","following_url":"https://api.github.com/users/pnkfelix/following{/other_user}","gists_url":"https://api.github.com/users/pnkfelix/gists{/gist_id}","starred_url":"https://api.github.com/users/pnkfelix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pnkfelix/subscriptions","organizations_url":"https://api.github.com/users/pnkfelix/orgs","repos_url":"https://api.github.com/users/pnkfelix/repos","events_url":"https://api.github.com/users/pnkfelix/events{/privacy}","received_events_url":"https://api.github.com/users/pnkfelix/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":21,"created_at":"2015-11-27T14:38:36Z","updated_at":"2016-04-20T00:25:37Z","closed_at":null,"body":"Right now we have ad hoc checks for certain known bad scenarios in our const evaluator ... so for example:\r\n\r\n```rust\r\n#![feature(const_fn)]\r\n\r\nfn add1(x: u32) -> u32 {\r\n    // For non-const, I can inject input checks\r\n    assert!(x < ::std::u32::MAX);\r\n    x + 1\r\n}\r\n\r\n#[cfg(cannot_build_today)]\r\nconst fn const_add1(x: u32) -> u32 {\r\n    // but current rules for `const fn`\r\n    // disallow this variation\r\n    assert!(x < ::std::u32::MAX,\r\n            \"I want this assertion to fire.\");\r\n    x + 1\r\n}\r\n\r\n// So one is forced to instead write this:\r\nconst fn const_add1(x: u32) -> u32 {\r\n    x + 1\r\n}\r\n\r\nfn main() {\r\n    let x = -1i32 as u32;\r\n    println!(\"foo(0): {}\", add1(0));\r\n    println!(\"bar(-1 as u32): {}\",\r\n             const_add1(x));\r\n    println!(\"foo(-1 as u32): {}\",\r\n             add1(x));\r\n}\r\n```\r\n\r\nthe above code today evaluates like so ([playpen](http://is.gd/kevdZQ)) in debug mode:\r\n\r\n```\r\nfoo(0): 1\r\nthread '<main>' panicked at 'arithmetic operation overflowed', <anon>:20\r\nplaypen: application terminated with error code 101\r\n```\r\n\r\nand in release mode:\r\n\r\n```\r\nfoo(0): 1\r\nbar(-1 as u32): 0\r\nthread '<main>' panicked at 'assertion failed: x < ::std::u32::MAX', <anon>:5\r\nplaypen: application terminated with error code 101\r\n```\r\n\r\n(i.e., there is no way to emulate the `foo` behavior within `bar` while compiling in release mode.)\r\n\r\nAnother example: since we made the `NonZero` constructor a const function, we cannot add a `debug_assert!` to its body that checks that the input is actually non-zero. (If it were not a const function, then it is straight-forward to extend the `Zeroable` trait with an `fn is_zero(&self) -> bool` predicate to use as the basis for such a `debug_assert!).\r\n\r\nI don't feel like writing up a formal RFC yet for addressing this, but I think it would be nice to extend the `const fn` sublanguage to allow `assert!` and `debug_assert!` statements where the input text expression is restricted to a const expression, and then have `rustc` actually fail the compilation if it discovers an assertion violation at compile-time."},"comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/comments/212182964","html_url":"https://github.com/rust-lang/rfcs/issues/1383#issuecomment-212182964","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1383","id":212182964,"user":{"login":"tsion","id":26806,"avatar_url":"https://avatars.githubusercontent.com/u/26806?v=3","gravatar_id":"","url":"https://api.github.com/users/tsion","html_url":"https://github.com/tsion","followers_url":"https://api.github.com/users/tsion/followers","following_url":"https://api.github.com/users/tsion/following{/other_user}","gists_url":"https://api.github.com/users/tsion/gists{/gist_id}","starred_url":"https://api.github.com/users/tsion/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tsion/subscriptions","organizations_url":"https://api.github.com/users/tsion/orgs","repos_url":"https://api.github.com/users/tsion/repos","events_url":"https://api.github.com/users/tsion/events{/privacy}","received_events_url":"https://api.github.com/users/tsion/received_events","type":"User","site_admin":false},"created_at":"2016-04-20T00:25:37Z","updated_at":"2016-04-20T00:25:37Z","body":"> Can miri do this right now? If not, what's the blocker there? cc @tsion\r\n\r\n@eddyb The blocker is `Lvalue::Static`, which miri doesn't currently attempt to handle:\r\n\r\n```\r\n    tmp1 = &r::_FILE_LINE\r\nthread '<main>' panicked at 'not yet implemented', src/interpreter.rs:795\r\n```\r\n\r\nSee [line 795](https://github.com/tsion/miri/blob/86d8a07321e5d023ec831355731fd2ddf861ca77/src/interpreter.rs#L795) which is the `Static` case in `eval_lvalue`."}}