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
E0492: borrow of an interior mutable value may end up in the final value
during const eval when no inner mutability is involved
#121250
Comments
This is probably a regression introduced by #120932. However, the error is right: this is a reference to #120932 fixed a bug in our interior-mutablity-checking code. I think what this actually shows is that the code never should have been accepted in the first place. But we may need a crater run to figure out how bad this regression is. Is there a way to retroactively do a crater run for #120932? Cc @oli-obk |
is there a trait bound or something similar that can be added to tell the compiler that there won't be any internal mutability? |
Unfortunately not on stable -- see #60715. |
Interestingly I think there is no soundness issue on stable here: in @sarah-ek is there a reason why you wrote Without curly braces, the code still works fine on nightly with the fixed checks: #[derive(Copy, Clone)]
pub struct S<T>(T);
#[doc(hidden)]
pub trait DynTrait {
type VTable: Copy + 'static;
const VTABLE: &'static Self::VTable;
}
impl<T: DynTrait> DynTrait for S<T> {
type VTable = T::VTable;
const VTABLE: &'static Self::VTable = &*T::VTABLE;
} |
this is a simplification of a different scenario. the actual code is here https://github.com/sarah-ek/equator/blob/444beec918bb83e6c9e400a1849dcf015795a7b0/equator/src/lib.rs#L581-L584 the reason i want to borrow is so i can force the promotion to static when used as a part of my own |
But promotion to static is exactly what we don't want to do when there might be interior mutability. So that kind of code is definitely not intended to work. I don't know how constrained you are with the types you can use here; would something like this work for you? impl<Lhs: DynDebug, Rhs: DynDebug> DynDebug for AndExpr<Lhs, Rhs> {
type VTable = (&'static Lhs::VTable, &'static Rhs::VTable);
const VTABLE: &'static Self::VTable = &(Lhs::VTABLE, Rhs::VTABLE);
} |
yeah, i ended up going with that |
Okay, glad to hear you have a work-around. We still need to decide what to do with this accidental regression though. It is IMO a bugfix in our analysis, even though the stars align to make it not obviously unsound -- though it's also possible that I missed something in my analysis above. Let's see what Oli says. |
I think the right thing would be to error out as TooGeneric if we encounter such a constant. Or just not intern generic constants at all, but error out as TooGeneric before interning and validation in order to still get the const eval coverage of the rest. Evaluating generic constants is best effort anyway, and repeated from scratch for every monomorphization, at which point we'll only error if there is an actual mutable allocation there |
This is not an interpreter error, it is a const-checking error (i.e., it is raised in |
Oh 🤦 I was wondering how we got that error wording from interning. I'll need to think about this some more. |
I just stumbled across the same issue in my weekly CI. In my nightly crate, I am at one point building a HList that will be layout-equivalent to an array. The following code now fails (this is somewhat simplified to collapse helper traits): pub trait ComputeSet {
type TyHList: 'static + Copy;
const TYS: &'static Self::TyHList;
}
impl<H2: TypeLayout, T: ComputeSet> ComputeSet for Cons<H2, T> {
type TyHList = Cons<&'static crate::TypeLayoutInfo<'static>, T::TyHList>;
const TYS: &'static Self::TyHList = &Cons {
head: &H2::TYPE_LAYOUT,
tail: *T::TYS,
};
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Cons<H, T> {
head: H,
tail: T,
}
pub unsafe trait TypeLayout: Sized {
const TYPE_LAYOUT: TypeLayoutInfo<'static>;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TypeLayoutInfo<'a> {
...
} Error:
The complete version can be found here:
|
WG-prioritization assigning priority (Zulip discussion). @rustbot label -I-prioritize +P-medium |
Crater results are in. The equator crate (the crate of the OP) is the only regression across all of crates.io. So I am inclined to classify this as a bugfix -- we shouldn't have allowed such temporaries with potentially interior mutable data to be creates in the first place. We should prioritize letting people write generic code while preserving the information that a type has no interior mutability, i.e., letting people use |
@rust-lang/lang We accidentally fixed a bug (by cleaning up const checking code in a way that inherently forbade the bug). This bug has been found to have a single regression. The issue is already being worked around. The bug fix is that we now correctly forbid using associated constants that have generic parameters (either themselves whenever we get GACs, or from their trait), if those constants are used behind references. This was a hole in our checks for preventing interior mutability behind references in constants. These are not stable yet, and if the constant is generic, we cannot know whether it has interior mutability and need to reject it. |
What workaround could I use for my usage of this pattern? In my case, I need to use the associated type alias to hide a generic array length and instead use an hlist, which is made up of a reference to a type that is non-generic and has no interior mutability, and the existing hlist (which is another hlist). The hlist is stored behind a reference since it is eventually converted into a slice (still inside const code), for which it already needs to be a valid allocation. |
Since you are using a nightly crate anyway, you can enable the |
No the feature is not sufficient. The problem isn't that we allowed something that should be unstable, the problem is that we allowed something unsound. (Or at least our soundness argument was wrong. There turns out to be a much more complicated soundness argument, but that relies on an accidental invariant that we do not intend to maintain. And we have a second line of defense during interning and validity checking, but that is post-monomorphization and so far we've generally avoided relying on it for these things.) Even with @juntyr I'm afraid I don't know a work-around for your usage. Sorry for that. :( We never intended to allow the code you wrote, it was an accident. Now we asked the lang team evaluate whether the existing usage of this accident is sufficient precedent to make us contort the language so that we can keep accepting this code in a proper, non-accidental way -- or whether we're better off rejecting such code. |
I should have said -- with current compilers. Your usecase will be possible once #60715 is resolved. |
Thank you @RalfJung for the clarification! I'll revert to pinning my nightly again (which in this crate has happened before when the const trait rework started). Hopefully we get |
We discussed this in today's lang meeting, and concluded that we do want to keep the behavior of current nightly. Starting an FCP to confirm that consensus: @rfcbot merge |
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. 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. |
@rfcbot reviewed |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
@rustbot labels -I-lang-nominated As reflected above, we discussed this in lang triage today. It's now in FCP, so let's unnominate. |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
This code works on stable, but not latest nightly
Error:
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: