-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
#[contracts::requires(...)] + #[contracts::ensures(...)] #128045
Conversation
r? @fee1-dead rustbot has assigned @fee1-dead. Use |
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
Please add a ui test with an attribute proc-macro aux build that conflicts with |
register( | ||
sym::contracts_requires, | ||
SyntaxExtensionKind::Attr(Box::new(contracts::ExpandRequires)), | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This macro should be able to use register_attr!
above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we actually can, if we want to support arbitrary syntax within the contracts::require(...)
-- doesn't register_attr!
mandate that the requires expression conform to ast::MetaItem
, which imposes restrictions on what the syntax can be, i.e. x > 0
wouldn't work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took a closer look at this, and this is very unfortunate. I don't believe the current builtin macro setup allows for "path segments"-like namespacing (like rustc_contracts::require
). I've tried to change the builtin macro support to allow multiple "segments" via SmallVec<[Symbol; 2]>
, but as one would expect, that change kept propagating outwards to attributes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for my delay in responding here.
@jieyouxu is exactly right.
specifically, register_attr!
expands to a SyntaxExtensionKind::LegacyAttr
, which is where the conformance to ast::MetaItem
is enforced IIRC.
The plan here to support code snippets like x > 0
in a contract form means that we cannot conform to ast::MetaItem
.
(In theory I could try to extend the register_attr!
macro to support expansion to non LegacyAttr
. Is that what you are asking for, @petrochenkov ?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@petrochenkov let me know if you want me to make any changes here. Per @pnkfelix comment, using register_attr!
would restrict the input of the contract attributes which is not desirable here. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that is the reason, at the very least a comment is needed to explain that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are comments in the builtin macro implementation. Would you like me to add comments to this file as well?
r? compiler |
r? compiler |
I don't know that part of the compiler r? @petrochenkov would you like to review this? |
No. |
r? compiler |
I'll ask T-compiler for another suitable reviewer to take a look at the HIR/MIR parts of the PR, or take over the review. In the mean time, I'll also roll a T-libs reviewer for the libs part. r? jieyouxu |
42722b8
to
d280c18
Compare
Check ensures on early return due to Try / Yeet Expand these two expressions to include a call to contract checking
…ostcondition predicate.
The extended syntax for function signature that includes contract clauses should never be user exposed versus the interface we want to ship externally eventually.
Instead of parsing the different components of a function signature, eagerly look for either the `where` keyword or the function body. - Also address feedback to use `From` instead of `TryFrom` in cranelift contract and ubcheck codegen.
1. Document the new intrinsics. 2. Make the intrinsics actually check the contract if enabled, and remove `contract::check_requires` function. 3. Use panic with no unwind in case contract is using to check for safety, we probably don't want to unwind. Following the same reasoning as UB checks.
This is now a valid expected value.
This has now been approved as a language feature and no longer needs a `rustc_` prefix. Also change the `contracts` feature to be marked as incomplete and `contracts_internals` as internal.
d280c18
to
ddbf54b
Compare
#[contracts::requires(...)] + #[contracts::ensures(...)] cc rust-lang#128044 Updated contract support: attribute syntax for preconditions and postconditions, implemented via a series of desugarings that culminates in: 1. a compile-time flag (`-Z contract-checks`) that, similar to `-Z ub-checks`, attempts to ensure that the decision of enabling/disabling contract checks is delayed until the end user program is compiled, 2. invocations of lang-items that handle invoking the precondition, building a checker for the post-condition, and invoking that post-condition checker at the return sites for the function, and 3. intrinsics for the actual evaluation of pre- and post-condition predicates that third-party verification tools can intercept and reinterpret for their own purposes (e.g. creating shims of behavior that abstract away the function body and replace it solely with the pre- and post-conditions). Known issues: * My original intent, as described in the MCP (rust-lang/compiler-team#759) was to have a rustc-prefixed attribute namespace (like rustc_contracts::requires). But I could not get things working when I tried to do rewriting via a rustc-prefixed builtin attribute-macro. So for now it is called `contracts::requires`. * Our attribute macro machinery does not provide direct support for attribute arguments that are parsed like rust expressions. I spent some time trying to add that (e.g. something that would parse the attribute arguments as an AST while treating the remainder of the items as a token-tree), but its too big a lift for me to undertake. So instead I hacked in something approximating that goal, by semi-trivially desugaring the token-tree attribute contents into internal AST constucts. This may be too fragile for the long-term. * (In particular, it *definitely* breaks when you try to add a contract to a function like this: `fn foo1(x: i32) -> S<{ 23 }> { ... }`, because its token-tree based search for where to inject the internal AST constructs cannot immediately see that the `{ 23 }` is within a generics list. I think we can live for this for the short-term, i.e. land the work, and continue working on it while in parallel adding a new attribute variant that takes a token-tree attribute alongside an AST annotation, which would completely resolve the issue here.) * the *intent* of `-Z contract-checks` is that it behaves like `-Z ub-checks`, in that we do not prematurely commit to including or excluding the contract evaluation in upstream crates (most notably, `core` and `std`). But the current test suite does not actually *check* that this is the case. Ideally the test suite would be extended with a multi-crate test that explores the matrix of enabling/disabling contracts on both the upstream lib and final ("leaf") bin crates.
Rollup of 9 pull requests Successful merges: - rust-lang#128045 (#[contracts::requires(...)] + #[contracts::ensures(...)]) - rust-lang#136263 (rustdoc: clean up a bunch of ts-expected-error declarations in main) - rust-lang#136375 (cg_llvm: Replace some DIBuilder wrappers with LLVM-C API bindings (part 1)) - rust-lang#136392 (bootstrap: add wrapper macros for `feature = "tracing"`-gated `tracing` macros) - rust-lang#136405 (rustdoc-book: Clean up section on `--output-format`) - rust-lang#136497 (Report generic mismatches when calling bodyless trait functions) - rust-lang#136502 (Mark `std::fmt::from_fn` as `#[must_use]`) - rust-lang#136509 (Add tests for nested macro_rules edition behavior) - rust-lang#136526 (mir_build: Rename `thir::cx::Cx` to `ThirBuildCx` and remove `UserAnnotatedTyHelpers`) r? `@ghost` `@rustbot` modify labels: rollup
Rollup of 8 pull requests Successful merges: - rust-lang#128045 (#[contracts::requires(...)] + #[contracts::ensures(...)]) - rust-lang#136263 (rustdoc: clean up a bunch of ts-expected-error declarations in main) - rust-lang#136375 (cg_llvm: Replace some DIBuilder wrappers with LLVM-C API bindings (part 1)) - rust-lang#136392 (bootstrap: add wrapper macros for `feature = "tracing"`-gated `tracing` macros) - rust-lang#136396 (rustdoc-json-types: Document that crate name isn't package name.) - rust-lang#136405 (rustdoc-book: Clean up section on `--output-format`) - rust-lang#136502 (Mark `std::fmt::from_fn` as `#[must_use]`) - rust-lang#136509 (Add tests for nested macro_rules edition behavior) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#128045 - pnkfelix:rustc-contracts, r=oli-obk #[contracts::requires(...)] + #[contracts::ensures(...)] cc rust-lang#128044 Updated contract support: attribute syntax for preconditions and postconditions, implemented via a series of desugarings that culminates in: 1. a compile-time flag (`-Z contract-checks`) that, similar to `-Z ub-checks`, attempts to ensure that the decision of enabling/disabling contract checks is delayed until the end user program is compiled, 2. invocations of lang-items that handle invoking the precondition, building a checker for the post-condition, and invoking that post-condition checker at the return sites for the function, and 3. intrinsics for the actual evaluation of pre- and post-condition predicates that third-party verification tools can intercept and reinterpret for their own purposes (e.g. creating shims of behavior that abstract away the function body and replace it solely with the pre- and post-conditions). Known issues: * My original intent, as described in the MCP (rust-lang/compiler-team#759) was to have a rustc-prefixed attribute namespace (like rustc_contracts::requires). But I could not get things working when I tried to do rewriting via a rustc-prefixed builtin attribute-macro. So for now it is called `contracts::requires`. * Our attribute macro machinery does not provide direct support for attribute arguments that are parsed like rust expressions. I spent some time trying to add that (e.g. something that would parse the attribute arguments as an AST while treating the remainder of the items as a token-tree), but its too big a lift for me to undertake. So instead I hacked in something approximating that goal, by semi-trivially desugaring the token-tree attribute contents into internal AST constucts. This may be too fragile for the long-term. * (In particular, it *definitely* breaks when you try to add a contract to a function like this: `fn foo1(x: i32) -> S<{ 23 }> { ... }`, because its token-tree based search for where to inject the internal AST constructs cannot immediately see that the `{ 23 }` is within a generics list. I think we can live for this for the short-term, i.e. land the work, and continue working on it while in parallel adding a new attribute variant that takes a token-tree attribute alongside an AST annotation, which would completely resolve the issue here.) * the *intent* of `-Z contract-checks` is that it behaves like `-Z ub-checks`, in that we do not prematurely commit to including or excluding the contract evaluation in upstream crates (most notably, `core` and `std`). But the current test suite does not actually *check* that this is the case. Ideally the test suite would be extended with a multi-crate test that explores the matrix of enabling/disabling contracts on both the upstream lib and final ("leaf") bin crates.
Uses the contracts syntax introduced in rust-lang#128045.
Uses the contracts syntax introduced in rust-lang#128045.
Refactor FnKind variant to hold &Fn Pulling the change suggested in rust-lang#128045 to reduce the impact of changing `Fn` item. r? `@oli-obk`
#[contracts::requires(...)] + #[contracts::ensures(...)] cc rust-lang#128044 Updated contract support: attribute syntax for preconditions and postconditions, implemented via a series of desugarings that culminates in: 1. a compile-time flag (`-Z contract-checks`) that, similar to `-Z ub-checks`, attempts to ensure that the decision of enabling/disabling contract checks is delayed until the end user program is compiled, 2. invocations of lang-items that handle invoking the precondition, building a checker for the post-condition, and invoking that post-condition checker at the return sites for the function, and 3. intrinsics for the actual evaluation of pre- and post-condition predicates that third-party verification tools can intercept and reinterpret for their own purposes (e.g. creating shims of behavior that abstract away the function body and replace it solely with the pre- and post-conditions). Known issues: * My original intent, as described in the MCP (rust-lang/compiler-team#759) was to have a rustc-prefixed attribute namespace (like rustc_contracts::requires). But I could not get things working when I tried to do rewriting via a rustc-prefixed builtin attribute-macro. So for now it is called `contracts::requires`. * Our attribute macro machinery does not provide direct support for attribute arguments that are parsed like rust expressions. I spent some time trying to add that (e.g. something that would parse the attribute arguments as an AST while treating the remainder of the items as a token-tree), but its too big a lift for me to undertake. So instead I hacked in something approximating that goal, by semi-trivially desugaring the token-tree attribute contents into internal AST constucts. This may be too fragile for the long-term. * (In particular, it *definitely* breaks when you try to add a contract to a function like this: `fn foo1(x: i32) -> S<{ 23 }> { ... }`, because its token-tree based search for where to inject the internal AST constructs cannot immediately see that the `{ 23 }` is within a generics list. I think we can live for this for the short-term, i.e. land the work, and continue working on it while in parallel adding a new attribute variant that takes a token-tree attribute alongside an AST annotation, which would completely resolve the issue here.) * the *intent* of `-Z contract-checks` is that it behaves like `-Z ub-checks`, in that we do not prematurely commit to including or excluding the contract evaluation in upstream crates (most notably, `core` and `std`). But the current test suite does not actually *check* that this is the case. Ideally the test suite would be extended with a multi-crate test that explores the matrix of enabling/disabling contracts on both the upstream lib and final ("leaf") bin crates.
Uses the contracts syntax introduced in rust-lang#128045.
Uses the contracts syntax introduced in rust-lang#128045.
cc #128044
Updated contract support: attribute syntax for preconditions and postconditions, implemented via a series of desugarings that culminates in:
-Z contract-checks
) that, similar to-Z ub-checks
, attempts to ensure that the decision of enabling/disabling contract checks is delayed until the end user program is compiled,Known issues:
My original intent, as described in the MCP (Contracts: Experimental attributes and language intrinsics compiler-team#759) was to have a rustc-prefixed attribute namespace (like rustc_contracts::requires). But I could not get things working when I tried to do rewriting via a rustc-prefixed builtin attribute-macro. So for now it is called
contracts::requires
.Our attribute macro machinery does not provide direct support for attribute arguments that are parsed like rust expressions. I spent some time trying to add that (e.g. something that would parse the attribute arguments as an AST while treating the remainder of the items as a token-tree), but its too big a lift for me to undertake. So instead I hacked in something approximating that goal, by semi-trivially desugaring the token-tree attribute contents into internal AST constucts. This may be too fragile for the long-term.
fn foo1(x: i32) -> S<{ 23 }> { ... }
, because its token-tree based search for where to inject the internal AST constructs cannot immediately see that the{ 23 }
is within a generics list. I think we can live for this for the short-term, i.e. land the work, and continue working on it while in parallel adding a new attribute variant that takes a token-tree attribute alongside an AST annotation, which would completely resolve the issue here.)the intent of
-Z contract-checks
is that it behaves like-Z ub-checks
, in that we do not prematurely commit to including or excluding the contract evaluation in upstream crates (most notably,core
andstd
). But the current test suite does not actually check that this is the case. Ideally the test suite would be extended with a multi-crate test that explores the matrix of enabling/disabling contracts on both the upstream lib and final ("leaf") bin crates.