-
Notifications
You must be signed in to change notification settings - Fork 50
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
OwningRef is in conflict with noalias
#49
Comments
@RalfJung is rental affected, too? |
I don't know, haven't looked at that yet. |
But given it mentions "self-referential structs", I heavily expect it to be affected, just like self-referential generators. (For the latter we have UB but no "miscompilation" due to that, yet.) |
Here is a playground link showing how to fix The main lines of the solution are:
It passes MIRI and generates the following LLVM IR for ; Function Attrs: nounwind nonlazybind uwtable
define i8 @helper(i8* nonnull, i8*) unnamed_addr #2 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
bb10:
store i8 10, i8* %0, align 1
store i8 20, i8* %1, align 1
%.val5 = load i8, i8* %0, align 1
tail call void @__rust_dealloc(i8* nonnull %0, i64 1, i64 1) #5
ret i8 %.val5
}
|
Cool! That sounds like it brings the right ingredients.
Notice that Miri is currently very permissive for raw pointers. It allows more than LLVM |
Sorry to ask here, but would the same problem exist if the Box was replaced with a Vec (of one element)? Or does the Vec count as an aliasable owner? |
AFAIK, it should but currently doesn't. In theory it should be possible to apply |
If it is not possible to store and pass a meaningful pointer next to a 'noalias' tagged original pointer, maybe a way to handle this would be to utilize the 'stability' of the dereference operation and store a typed offset from the dereferenced value instead. Then the pointer stored right now would instead be restored by dereferencing the original pointer and then offsetting it with the stored offset. Troubles: The offset is not a pure offset for ; Function Attrs: nounwind nonlazybind uwtable
define i8 @helper(i8* noalias align 1 dereferenceable(1), i64) unnamed_addr #2 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
bb8:
store i8 10, i8* %0, align 1
%2 = getelementptr i8, i8* %0, i64 %1
store i8 20, i8* %2, align 1
%.val = load i8, i8* %0, align 1
tail call void @__rust_dealloc(i8* nonnull %0, i64 1, i64 1) #5
ret i8 %.val
} |
@HeroicKatora that's, by the way, what |
Agreed. |
Hello folks. Kimundi has very kindly given me control over his repository. |
Interestingly, this code works as intended: use owning_ref::OwningRef;
use std::cell::Cell;
fn helper(r: &mut OwningRef<Box<Cell<i32>>, Cell<i32>>) -> i32 {
r.as_owner().set(20);
r.set(10);
r.as_owner().get()
}
fn main() {
assert_eq!(helper(&mut OwningRef::new(Box::new(Cell::new(0)))), 10);
} Also this: use owning_ref::OwningRef;
use std::cell::Cell;
fn helper(r: Box<OwningRef<Box<Cell<i32>>, Cell<i32>>>) -> i32 {
r.as_owner().set(20);
r.set(10);
r.as_owner().get()
}
fn main() {
assert_eq!(helper(Box::new(OwningRef::new(Box::new(Cell::new(0))))), 10);
} So it looks like the UB is gone when passing by pointer. |
All I can see is that the compiler doesn't exploit the UB any more. How do you conclude that there is no UB? |
See the discussion starting here: It is possible to trigger UB in safe code using owning-ref.
Specifically, the assertion in the following snippet by @comex fails, even though it should succeed:
The text was updated successfully, but these errors were encountered: