Skip to content

const-eval: allow constants to refer to mutable/external memory, but reject such constants as patterns #140942

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

RalfJung
Copy link
Member

@RalfJung RalfJung commented May 12, 2025

This fixes #140653 by accepting code such as this:

static FOO: AtomicU32 = AtomicU32::new(0);
const C: &'static AtomicU32 = &FOO;

This can be written entirely in safe code, so there can't really be anything wrong with it.

We also accept the much more questionable following code, since it looks very similar to the interpreter:

static mut FOO2: u32 = 0;
const C2: &'static u32 = unsafe { &mut FOO };

Using this without causing UB is at least very hard (the details are unclear since it is related to how the aliasing model deals with the staging of const-eval vs runtime code).

If a constant like C2 is used as a pattern, we emit an error:

error: constant BAD_PATTERN cannot be used as pattern
  --> $DIR/const_refs_to_static_fail.rs:30:9
   |
LL |         BAD_PATTERN => {},
   |         ^^^^^^^^^^^
   |
   = note: constants that reference mutable or external memory cannot be used as pattern

(If you somehow manage to build a pattern with constant C, you'd get the same error, but that should be impossible: we don't have a type that can be used in patterns and that has interior mutability.)

The same treatment is afforded for shared references to extern static, for the same reason: the const evaluation is entirely fine with it, we just can't build a pattern for it -- and when using interior mutability, this can be totally sound.

We do still not accept anything where there is an &mut in the final value of the const, as that should always require unsafe code and it's hard to imagine a sound use-case that would require this.

@rustbot
Copy link
Collaborator

rustbot commented May 12, 2025

r? @jieyouxu

rustbot has assigned @jieyouxu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 12, 2025
@rustbot
Copy link
Collaborator

rustbot commented May 12, 2025

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

@RalfJung RalfJung added T-lang Relevant to the language team, which will review and decide on the PR/issue. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). I-lang-nominated Nominated for discussion during a lang team meeting. labels May 12, 2025
@RalfJung
Copy link
Member Author

@rust-lang/lang nominating for FCP following prior discussion in #140653.

@rust-log-analyzer

This comment has been minimized.

@RalfJung RalfJung force-pushed the const-ref-to-mut branch from f619969 to 9767f96 Compare May 12, 2025 12:13
@rust-log-analyzer

This comment has been minimized.

@RalfJung RalfJung force-pushed the const-ref-to-mut branch from 9767f96 to 160cee0 Compare May 12, 2025 12:37
@rustbot
Copy link
Collaborator

rustbot commented May 12, 2025

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

Self::is_value_unfrozen_raw(cx, result, ty)
}

pub fn const_eval_resolve(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rust-lang/clippy I could not figure out why clippy has its own version of this function, and there's no comment giving any hint. The easiest way to fix the build failure was to remove the function so I did that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jarcho might know.

Copy link
Member Author

@RalfJung RalfJung May 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this does seem to change some of the tests. I have no clue why that is, apparently some detail of the old code was load-bearing. The total lack of comments in the code makes this rather painful to debug... (and that's on top of #78717 which already makes clippy more painful to deal with than basically every other part of this repository :/ )

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The entire logic of this lint seems off to me. Why is this using valtrees in the first place? That seems to be a misuse of the valtree APIs. I think what you really want here is to use a value visitor to walk the value of the const and search for UnsafeCell, similar to this. That will then also work with non-valtree-compatible constants.

Please consult with the stakeholders of an API before using it in creative ways in clippy. Long-term that saves a lot of maintenance work. :)

Copy link
Member Author

@RalfJung RalfJung May 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think somehow previously clippy managed to convince the valtree evaluation machinery to evaluate generic consts without throwing TooGeneric. I have no idea why that worked, but it was never supposed to work -- constants must be monomorphic to be evaluated. Furthermore, whenever it did encounter TooGeneric, clippy interprets that as an unfrozen value -- with a long comment for why that's the better choice (which I don't agree with, since TooGeneric really means you have no idea at all about the contents of the constant). However, now that more TooGeneric errors appear (and as far as I can tell, those errors are correct), this is no longer the better choice, so I changed it. That means the lint fires much less than before (it never fires on generic consts any more, which affects the majority of testcases), but I don't think it makes sense to even attempt to lint on generic consts -- rustc is not designed for that, and trying to misuse its APIs is not long a long-term viable strategy.

@oli-obk maybe you have a better idea here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jason is working on a PR rust-lang/rust-clippy#13207 that refactors this lint and removes the ValTree API misuse.

I managed to get one of those cases to fire the lint again by more closely following the original code. No idea why that particular change made a difference for that case, or why all the other cases are still not firing.

So if this PR introduces some false negatives, I would say that isn't too bad.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, as-is the PR adds a bunch of false negatives. Though seems like I'll just have to wait until rust-lang/rust-clippy#13207 syncs to this repo, drop my changes, and rebase.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR missed the sync by 1 day. So the next one will be in just short of 2 weeks.. I can do an out-of-cycle sync if you want it sooner.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up to you -- if my PR lands first, you'll get a conflict when doing the sync. But this PR will not land soon anyway, first we need FCP to start and then wait another 10 days.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next sync is in exactly 10 days. So that (if nothing goes wrong) goes in first.

@RalfJung RalfJung force-pushed the const-ref-to-mut branch from 160cee0 to e316943 Compare May 12, 2025 12:41
@RalfJung RalfJung force-pushed the const-ref-to-mut branch from e316943 to 6722d4d Compare May 12, 2025 13:01
@rust-log-analyzer

This comment has been minimized.

@jieyouxu
Copy link
Member

r? @oli-obk (or someone way more familiar with const-eval)

@rustbot rustbot assigned oli-obk and unassigned jieyouxu May 12, 2025
@RalfJung RalfJung force-pushed the const-ref-to-mut branch 2 times, most recently from 57ea31d to 6e9a7f4 Compare May 12, 2025 16:46
@traviscross traviscross removed the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label May 13, 2025
@traviscross
Copy link
Contributor

traviscross commented May 13, 2025

As discussed in #140653 (comment), this sounds right to me, and I propose that we do it.

@rfcbot fcp merge

@rfcbot
Copy link
Collaborator

rfcbot commented May 13, 2025

Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels May 13, 2025
@traviscross traviscross added the P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang label May 16, 2025
@tmandry
Copy link
Member

tmandry commented May 21, 2025

@rfcbot reviewed

@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels May 21, 2025
@rfcbot
Copy link
Collaborator

rfcbot commented May 21, 2025

🔔 This is now entering its final comment period, as per the review above. 🔔

@tmandry
Copy link
Member

tmandry commented May 21, 2025

@rfcbot concern whole team signoff

The proposal is to allow shared references to mutable memory in consts, but not to allow those consts to be used in patterns. This is a notable expansion and it is (to my knowledge) the first time we are not allowing a const to be used in a pattern, which constrains future decisions. I don't have a problem with it, and I think we probably should do it, but I would like the full team to know about it because it didn't have an RFC.


On a meta note, I keep having the feeling that this cluster of features is being "designed just in time". That is not to criticize anyone. Every decision we make seems reasonable and has good rationale, but it makes me nervous because I can't tell where we will ultimately end up as we go down this road. The path we are committing to here is something I'd ideally love to have considered in an RFC.

On the other hand, maybe this is working as intended? There are a lot of details to work out, and I don't know of anyone with a crystal ball who can foresee every implication. And if we did consider every implication it might overwhelm the lang team into indecision :).

I think we are far enough down this path that there's nothing to be done here, but it's something to think about.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels May 21, 2025
@bors
Copy link
Collaborator

bors commented May 21, 2025

☔ The latest upstream changes (presumably #141343) made this pull request unmergeable. Please resolve the merge conflicts.

@RalfJung
Copy link
Member Author

The proposal is to allow shared references to mutable memory in consts, but not to allow those consts to be used in patterns.

To be fully precise, this is about such shared references in the final value of a const. We already allowed such shared references to appear as temporaries within the computation of a const before.

On the other hand, maybe this is working as intended? There are a lot of details to work out, and I don't know of anyone with a crystal ball who can foresee every implication. And if we did consider every implication it might overwhelm the lang team into indecision :).

That's pretty much how I see it. There are a whole bunch of things one could imagine doing, but it's rather unclear what the trade-offs are, and which ones are worth it. So instead of planning a grand architecture on the whiteboard and then putting it into reality all at once, we're discovering one step at a time what it is that users actually want or need.

@RalfJung RalfJung force-pushed the const-ref-to-mut branch from 6e9a7f4 to 6755065 Compare May 22, 2025 06:04
Co-authored-by: Oli Scherer <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Confusing error when a const contains a shared ref to interior mutable data
10 participants