-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Make sure interned constants are immutable #63955
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
r? @oli-obk |
) -> InterpResult<'tcx> { | ||
let tcx = ecx.tcx; | ||
// this `mutability` is the mutability of the place, ignoring the type | ||
let (mutability, base_intern_mode) = match tcx.static_mutability(def_id) { | ||
let (base_mutability, base_intern_mode) = match tcx.static_mutability(def_id) { | ||
Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static), | ||
None => (Mutability::Immutable, InternMode::ConstBase), | ||
// `static mut` doesn't care about interior mutability, it's mutable anyway | ||
Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static), | ||
}; |
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.
Does this correctly compute ConstBase
for things like array sizes and non-Copy
array initializers? What does it do for promoteds?
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
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.
the DefId is of the function of the promoted, which
But what if we are promoting inside the body of a static
?
not sure what happens to non-Copy array initializers, as that's promotion happening inside a static
@eddyb do you know more here?
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.
Do we actually create implicit promoteds inside statics? I don't think so. I think we just nuke a bunch of storage statements
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.
Hm... seems like that is the case, and also for const
:
const fn id<T>(x: T) -> T { x }
const FOO: &'static usize = {
let v = id(&std::mem::size_of::<i32>());
v
};
But... @eddyb isn't that in contradiction to what you told me about the "enclosing scope" stuff?
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.
Are there other cases we have to worry about here in terms of classifying CTFE-evaluated "stuff" into (explicit) statics and consts ("everything but (explicit) statics")?
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.
Kind of related is that consts can't refer to statics
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.
How is that related? Even if they would, that memory would already be interned.
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.
It was the only thing I could come up with where we decide only on explict static vs not
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.
"explict static vs not"?
) -> InterpResult<'tcx> { | ||
let tcx = ecx.tcx; | ||
// this `mutability` is the mutability of the place, ignoring the type | ||
let (mutability, base_intern_mode) = match tcx.static_mutability(def_id) { | ||
let (base_mutability, base_intern_mode) = match tcx.static_mutability(def_id) { | ||
Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static), | ||
None => (Mutability::Immutable, InternMode::ConstBase), | ||
// `static mut` doesn't care about interior mutability, it's mutable anyway | ||
Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static), | ||
}; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
☔ The latest upstream changes (presumably #63561) made this pull request unmergeable. Please resolve the merge conflicts. |
I'm on vacation, will rebase when I have time. Other than that I think I addressed all comments, though this question here for @oli-obk and @eddyb is still open. |
… always intern constants as immutable
Rebased, ready for review. |
@bors r+ |
📌 Commit 5462ecb has been approved by |
Make sure interned constants are immutable This makes sure that interning for constants (not statics) creates only immutable allocations. Previously, the "main" allocation of `const FOO: Cell<i32> = Cell::new(0);` was marked as mutable, but I don't think we want that. It can be only copied, not written to. Also, "leftover" allocations (behind raw pointers etc) were left mutable. I don't think we want to support that. I tried asserting that these are all already immutable (to double-check our static checks), but that failed in this one: ```rust const NON_NULL_PTR2: NonNull<u8> = unsafe { mem::transmute(&0) }; ``` Seems like maybe we want more precise mutability annotation inside Miri for locals (like `&0` here) so that this would actually become immutable to begin with? I also factored `intern_shallow` out of the visitor so that we don't have to construct a visitor when we do not plan to visit anything. That confused me at first.
Rollup of 10 pull requests Successful merges: - #63955 (Make sure interned constants are immutable) - #64028 (Stabilize `Vec::new` and `String::new` as `const fn`s) - #64119 (ci: ensure all tool maintainers are assignable on issues) - #64444 (fix building libstd without backtrace feature) - #64446 (Fix build script sanitizer check.) - #64451 (when Miri tests are not passing, do not add Miri component) - #64467 (Hide diagnostics emitted during --cfg parsing) - #64497 (Don't print the "total" `-Ztime-passes` output if `--prints=...` is also given) - #64499 (Use `Symbol` in two more functions.) - #64504 (use println!() instead of println!("")) Failed merges: r? @ghost
This makes sure that interning for constants (not statics) creates only immutable allocations.
Previously, the "main" allocation of
const FOO: Cell<i32> = Cell::new(0);
was marked as mutable, but I don't think we want that. It can be only copied, not written to.Also, "leftover" allocations (behind raw pointers etc) were left mutable. I don't think we want to support that. I tried asserting that these are all already immutable (to double-check our static checks), but that failed in this one:
Seems like maybe we want more precise mutability annotation inside Miri for locals (like
&0
here) so that this would actually become immutable to begin with?I also factored
intern_shallow
out of the visitor so that we don't have to construct a visitor when we do not plan to visit anything. That confused me at first.