Uh oh!
There was an error while loading. Please reload this page.
Remove 'static bound on contract ensures closure - #148595
Conversation
rustbot
commented
Nov 6, 2025
r? @davidtwco rustbot has assigned @davidtwco. Use |
This comment has been minimized.
This comment has been minimized.
857b066 to
75caeabCompare| | ^^^^^^^^^ | ||
| | | ||
| = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information | ||
| = note: `#[warn(incomplete_features)]` on by default |
There was a problem hiding this comment.
you may add #![allow(incomplete_features)] to suppress this warning.
There was a problem hiding this comment.
Thanks for pointing this out! So far all the other contract UI tests have included this warning in the stderr, so I followed that pattern.
tautschnig
commented
Nov 7, 2025
Brilliant, this will enable adding a lot more contracts that #147148 currently has commented out. |
celinval
commented
Nov 9, 2025
@dawidl022, I don't recall why the build ensures had 'static. I can see if I can find my notes when @pnkfelix handed contacts over to me. |
davidtwco
commented
Nov 11, 2025
bors
commented
Nov 11, 2025
✌️ @celinval, you can now approve this pull request! If @davidtwco told you to " |
celinval
commented
Nov 13, 2025
I couldn't find any notes on this, but I took a closer look at it. I believe the reason why there's a 'static is because we haven't decided yet whether ensures should run before or after dropping local variables. Removing the 'static would allow ensures clauses that rely on local variables being alive by the time |
dawidl022
commented
Nov 13, 2025
Wouldn't these local variables really just be function parameters? The way contracts are scoped, they can only refer to It seems to me that it should be fine for the |
celinval
commented
Nov 13, 2025
Yes, at least in theory. You are correct, that without |
dawidl022
commented
Nov 13, 2025
I think that is a valid concern to raise. Nonetheless, I'm not sure However, I get the same type error: |
celinval
commented
Nov 13, 2025
I'm not saying it is great, but what I'm saying is that if we remove the If you change the signature of owned to: fnowned<T>(p:*const()) -> T{// Stub implementation for ownership assertion. Ignore this. unsafe{ std::ptr::read(p as*constT)}}I believe you should be able to use the following contract: #[ensures({let ptr = dst as*const(); move |_| { owned::<T>(ptr);true}})]This is not very ergonomic, and makes contracts with generic parameters harder. Do you have any other suggestion that we could implement to reject parameters in ensure clauses and remove the |
dawidl022
commented
Nov 14, 2025
Thank you! I was not aware of this workaround.
I'm not sure how easy it is to implement, but we could remove the lexical scope of function parameters from the ensures clause. I feel it would be a bit challanging, since we still want access to variables declared in the |
The `'static` bound on the closure of `build_check_ensures` prevented some patterns of contracts from type checking, without a clear reason for doing so. As such, this change removes the `'static` bound.
75caeab to
133bfbeComparedawidl022
commented
Nov 15, 2025
I realise this would not prevent users from creating references to parameters in the |
dawidl022
commented
Nov 15, 2025
The borrow checker would flag any borrow-rule violations, so e.g. if we did decide that the
|
dawidl022
commented
Nov 30, 2025
@celinval May we please move forward with this change? I understand the concerns regarding the assumption of parameters being alive in the In the meantime, I suggest we allow the |
celinval
commented
Nov 30, 2025
@dawidl022, I was wondering if we could change contracts implementation to add one layer of indirection, and do the following: If contracts is disabled: fnfunc(args:Args) -> Ret{iffalse{
<precond>;
<build_post>;let ret = func(args);
<postcode>(&ret);
ret
}else{
<body>
}}If contracts enabled: fnfunc(args:Args) -> Ret{
<precond>;
<build_post>;let ret = move | | { body }();
<postcode>(&ret);
ret
} |
celinval
commented
Nov 30, 2025
I don't think we should accept invalid contracts in favor of a slightly better ergonomic. The experiment is not blocked on this, is it? |
dawidl022
commented
Dec 11, 2025
@celinval what would be the advantages/rationale for the lowering you suggested? How does it compare to the lowering proposed in the re-architecture section of your document? Could we go straight for the latter instead? |
celinval
commented
Dec 12, 2025
The only advantage would be to unblock you earlier. It would still be temporary |
apiraino
commented
Feb 19, 2026
removing t-compiler since this looks like t-llibs @rustbot label -t-compiler |
The
'staticbound on the closure ofbuild_check_ensuresprevented some patterns of contracts from type checking, without a clear reason for doing so. As such, this change removes the'staticbound.While working on the proposal for
ownedandblockfor contracts, I came across a pattern that was rejected by type checker while attempting to specifystd::ptr::write:Eventually, I was able to track down the issue to a trait bound in
core::contracts::build_check_ensures, which puts a'staticbound on theensuresclosure. Remvoing the'staticbound allows the above contract to type-check, and additionally removes the need for themovein theensuresclosure.I have reduced the problem down to some minimal reproducible examples, which I included as part of this change as regression tests. The error messages for the regression tests before the change were as follows:
@celinval are you aware of any reason why the
'staticbound was put onbuild_check_ensuresin the first place?I have checked that the contracts in #136578 and #147148 still type check with this change.
Contracts tracking issue: #128044