jiebi/CodeConvo huggingface dataset:
Code change:
and currently store pointers as , which is not ideal: They should really work with pointers and strict provenance APIs like , , etc. See a PR fixing a similar issue for some context: (note: in that one I ended up rewriting the whole thing, I think this issue requires far less changes). <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
(I do plan to work on this, but if you want to work on this instead — feel free to , I can mentor you) <subcc
claim
Could you briefly describe and , also a comprehensive insight about this issue would greatly help, although I had a look at which currently is an . If I understand correctly, we are building a for this and aim to improve existing implementations as seen in languages like C++ by making it more strict, and there is some discussion that can basically do most of what C++ can and this addition might have some diverging path. Let me know, so I can move forward!
claim
Hi strict provenance means that we aren't doing pointer-int conversions and only operate through pointer types like suggested by OP. and currently use which doesn't work under strict provenance. If you'd like I can work on this issue.
Did you mean to mentor me for the same? I would be happy to learn!
is already working on this issue, is this right? Let's not override other people working on it already unless they agree or it's been several weeks with no response.
Hi yes I am working on this issue. This is my first time contributing so it will take me sometime. I will reassign the issue to me.
claim
Hi Just checking in :) Are you still working on this issue?
Yup I am still working on this issue :)
Let us know on Zulip if you need any help
with this resolved, I think rustc is free from "fuzzy provenance casts" :)
Awesome :-)

Related discussion:
text: TermKind::Ty(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); <del> (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize) </del> <ins> (TYPE_TAG, NonNull::from(ty.0.0).cast()) </ins> } TermKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); <del> (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize) </del> <ins> (CONST_TAG, NonNull::from(ct.0.0).cast()) </ins> } }; <del> Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } </del> <ins> Term { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData } </ins> } }
Code change:
The inliner strategy for dealing with storage statements is simple. If a callee local already has some storage statements, they are preserved as is when integrating callee into the caller. There are no new storage statements for such locals. Turns out this approach is unsound due to peculiar semantics of MIR. It is well defined to return from a function while there are still some live locals. At the same time it is undefined behaviour to execute StorageLive for already live local. Effectively inliner is obliged to end the storage for locals that are still live when callee returns, which it doesn't do at the moment. Arguably this is more of a bug in MIR semantics, then one in the inliner
hey would you like to first T-opsem discuss this? Maybe have this topic on a meeting and figure out a plan to fix this?
Oh, interesting catch. Cc Maybe we should just allow StorageLive on an already live local (and declare it to first implicitly free the local, and then make it live again)...

Related discussion:
text: dividing by zero const_eval_division_overflow = overflow in signed division (dividing MIN by -1) <del> const_eval_double_storage_live = StorageLive on a local that was already live </del> const_eval_dyn_call_not_a_method = `dyn` call trying to call something that is not a method
Code change:
The inliner strategy for dealing with storage statements is simple. If a callee local already has some storage statements, they are preserved as is when integrating callee into the caller. There are no new storage statements for such locals. Turns out this approach is unsound due to peculiar semantics of MIR. It is well defined to return from a function while there are still some live locals. At the same time it is undefined behaviour to execute StorageLive for already live local. Effectively inliner is obliged to end the storage for locals that are still live when callee returns, which it doesn't do at the moment. Arguably this is more of a bug in MIR semantics, then one in the inliner
hey would you like to first T-opsem discuss this? Maybe have this topic on a meeting and figure out a plan to fix this?
Oh, interesting catch. Cc Maybe we should just allow StorageLive on an already live local (and declare it to first implicitly free the local, and then make it live again)...

Related discussion:
text: Operand::Immediate(Immediate::Uninit) }); <del> // StorageLive expects the local to be dead, and marks it live. </del> <ins> // If the local is already live, deallocate its old memory. </ins> let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val); <del> if !matches!(old, LocalValue::Dead) { throw_ub_custom!(fluent::const_eval_double_storage_live); } </del> <ins> self.deallocate_local(old)?; </ins> Ok(()) }
Code change:
The inliner strategy for dealing with storage statements is simple. If a callee local already has some storage statements, they are preserved as is when integrating callee into the caller. There are no new storage statements for such locals. Turns out this approach is unsound due to peculiar semantics of MIR. It is well defined to return from a function while there are still some live locals. At the same time it is undefined behaviour to execute StorageLive for already live local. Effectively inliner is obliged to end the storage for locals that are still live when callee returns, which it doesn't do at the moment. Arguably this is more of a bug in MIR semantics, then one in the inliner
hey would you like to first T-opsem discuss this? Maybe have this topic on a meeting and figure out a plan to fix this?
Oh, interesting catch. Cc Maybe we should just allow StorageLive on an already live local (and declare it to first implicitly free the local, and then make it live again)...

Related discussion:
text: assert!(local != mir::RETURN_PLACE, "Cannot make return place dead"); trace!("{:?} is now dead", local); <del> // It is entirely okay for this local to be already dead (at least that's how we currently generate MIR) </del> <ins> // If the local is already dead, this is a NOP. </ins> let old = mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead); self.deallocate_local(old)?; Ok(())
Code change:
The inliner strategy for dealing with storage statements is simple. If a callee local already has some storage statements, they are preserved as is when integrating callee into the caller. There are no new storage statements for such locals. Turns out this approach is unsound due to peculiar semantics of MIR. It is well defined to return from a function while there are still some live locals. At the same time it is undefined behaviour to execute StorageLive for already live local. Effectively inliner is obliged to end the storage for locals that are still live when callee returns, which it doesn't do at the moment. Arguably this is more of a bug in MIR semantics, then one in the inliner
hey would you like to first T-opsem discuss this? Maybe have this topic on a meeting and figure out a plan to fix this?
Oh, interesting catch. Cc Maybe we should just allow StorageLive on an already live local (and declare it to first implicitly free the local, and then make it live again)...

Related discussion:
text: /// At any point during the execution of a function, each local is either allocated or /// unallocated. Except as noted below, all locals except function parameters are initially /// unallocated. `StorageLive` statements cause memory to be allocated for the local while <del> /// `StorageDead` statements cause the memory to be freed. Using a local in any way (not only /// reading/writing from it) while it is unallocated is UB. </del> <ins> /// `StorageDead` statements cause the memory to be freed. In other words, /// `StorageLive`/`StorageDead` act like the heap operations `allocate`/`deallocate`, but for /// stack-allocated local variables. Using a local in any way (not only reading/writing from it) /// while it is unallocated is UB. </ins> /// /// Some locals have no `StorageLive` or `StorageDead` statements within the entire MIR body. /// These locals are implicitly allocated for the full duration of the function. There is a /// convenience method at `rustc_mir_dataflow::storage::always_storage_live_locals` for /// computing these locals. /// <del> /// If the local is already allocated, calling `StorageLive` again is UB. However, for an /// unallocated local an additional `StorageDead` all is simply a nop. </del> <ins> /// If the local is already allocated, calling `StorageLive` again will implicitly free the /// local and then allocate fresh uninitilized memory. If a local is already deallocated, /// calling `StorageDead` again is a NOP. </ins> StorageLive(Local), /// See `StorageLive` above.
Code change:
The inliner strategy for dealing with storage statements is simple. If a callee local already has some storage statements, they are preserved as is when integrating callee into the caller. There are no new storage statements for such locals. Turns out this approach is unsound due to peculiar semantics of MIR. It is well defined to return from a function while there are still some live locals. At the same time it is undefined behaviour to execute StorageLive for already live local. Effectively inliner is obliged to end the storage for locals that are still live when callee returns, which it doesn't do at the moment. Arguably this is more of a bug in MIR semantics, then one in the inliner
hey would you like to first T-opsem discuss this? Maybe have this topic on a meeting and figure out a plan to fix this?
Oh, interesting catch. Cc Maybe we should just allow StorageLive on an already live local (and declare it to first implicitly free the local, and then make it live again)...

Related discussion:
text: <ins> #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; #[custom_mir(dialect = "runtime")] fn main() { mir! { let val: i32; { val = 42; //~ERROR: accessing a dead local variable StorageLive(val); // too late... (but needs to be here to make `val` not implicitly live) Return() } } } </ins>
Code change:
The inliner strategy for dealing with storage statements is simple. If a callee local already has some storage statements, they are preserved as is when integrating callee into the caller. There are no new storage statements for such locals. Turns out this approach is unsound due to peculiar semantics of MIR. It is well defined to return from a function while there are still some live locals. At the same time it is undefined behaviour to execute StorageLive for already live local. Effectively inliner is obliged to end the storage for locals that are still live when callee returns, which it doesn't do at the moment. Arguably this is more of a bug in MIR semantics, then one in the inliner
hey would you like to first T-opsem discuss this? Maybe have this topic on a meeting and figure out a plan to fix this?
Oh, interesting catch. Cc Maybe we should just allow StorageLive on an already live local (and declare it to first implicitly free the local, and then make it live again)...

Related discussion:
text: <ins> error: Undefined Behavior: accessing a dead local variable --> $DIR/storage-live-dead-var.rs:LL:CC | LL |             val = 42; |             ^^^^^^^^ accessing a dead local variable | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: = note: inside `main` at $DIR/storage-live-dead-var.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error </ins>
Code change:
The inliner strategy for dealing with storage statements is simple. If a callee local already has some storage statements, they are preserved as is when integrating callee into the caller. There are no new storage statements for such locals. Turns out this approach is unsound due to peculiar semantics of MIR. It is well defined to return from a function while there are still some live locals. At the same time it is undefined behaviour to execute StorageLive for already live local. Effectively inliner is obliged to end the storage for locals that are still live when callee returns, which it doesn't do at the moment. Arguably this is more of a bug in MIR semantics, then one in the inliner
hey would you like to first T-opsem discuss this? Maybe have this topic on a meeting and figure out a plan to fix this?
Oh, interesting catch. Cc Maybe we should just allow StorageLive on an already live local (and declare it to first implicitly free the local, and then make it live again)...

Related discussion:
text: <ins> #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; #[custom_mir(dialect = "runtime")] fn main() { mir! { let val: i32; let _val2: i32; { StorageLive(val); val = 42; StorageLive(val); // reset val to `uninit` _val2 = val; //~ERROR: uninitialized Return() } } } </ins>
Code change:
The inliner strategy for dealing with storage statements is simple. If a callee local already has some storage statements, they are preserved as is when integrating callee into the caller. There are no new storage statements for such locals. Turns out this approach is unsound due to peculiar semantics of MIR. It is well defined to return from a function while there are still some live locals. At the same time it is undefined behaviour to execute StorageLive for already live local. Effectively inliner is obliged to end the storage for locals that are still live when callee returns, which it doesn't do at the moment. Arguably this is more of a bug in MIR semantics, then one in the inliner
hey would you like to first T-opsem discuss this? Maybe have this topic on a meeting and figure out a plan to fix this?
Oh, interesting catch. Cc Maybe we should just allow StorageLive on an already live local (and declare it to first implicitly free the local, and then make it live again)...

Related discussion:
text: <ins> error: Undefined Behavior: constructing invalid value: encountered uninitialized memory, but expected an integer --> $DIR/storage-live-resets-var.rs:LL:CC | LL |             _val2 = val; |             ^^^^^^^^^^^ constructing invalid value: encountered uninitialized memory, but expected an integer | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: = note: inside `main` at $DIR/storage-live-resets-var.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error </ins>
Code change:
For this snippet (): rustc gives: Since , for const-able values, rustc suggests the creation of a constant binding. Here this is not possible because is not const fn. However, we can suggest instead.
Personally, I prefer over a separate binding. Even in the case, the generated code will call the initialization function many times. Maybe in the case where bindings are possible, we can suggest both? Where they are not possible, we don't suggest anything right now, so at the least we should suggest there. what do you think?
Once is stable we can suggest that :3. But until then sounds reasonable.
Agreed, good point about . It seems to have a stabilization PR open with an FCP, which is blocked: . Maybe there might be progress on it this month: . Even if we stabilize inline const, it might make sense to wait with suggesting it for a while so that we don't make code depend on the latest MSRV immediately. So therefore, I think that it might still make sense to implement this in the meantime.
I think this should (in the future) suggest  instead, since the function would only be called once if were , whereas calls it for every element.

Related discussion:
text: ], Applicability::MachineApplicable, ); <ins> } else { // FIXME: we may suggest array::repeat instead err.help("consider using `core::array::from_fn` to initialize the array"); err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information"); </ins> } if self.tcx.sess.is_nightly_build()
Code change:
For this snippet (): rustc gives: Since , for const-able values, rustc suggests the creation of a constant binding. Here this is not possible because is not const fn. However, we can suggest instead.
Personally, I prefer over a separate binding. Even in the case, the generated code will call the initialization function many times. Maybe in the case where bindings are possible, we can suggest both? Where they are not possible, we don't suggest anything right now, so at the least we should suggest there. what do you think?
Once is stable we can suggest that :3. But until then sounds reasonable.
Agreed, good point about . It seems to have a stabilization PR open with an FCP, which is blocked: . Maybe there might be progress on it this month: . Even if we stabilize inline const, it might make sense to wait with suggesting it for a while so that we don't make code depend on the latest MSRV immediately. So therefore, I think that it might still make sense to implement this in the meantime.
I think this should (in the future) suggest  instead, since the function would only be called once if were , whereas calls it for every element.

Related discussion:
text: |                    ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` | = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider annotating `Header<'_>` with `#[derive(Copy)]` | LL + #[derive(Copy)]
Code change:
For this snippet (): rustc gives: Since , for const-able values, rustc suggests the creation of a constant binding. Here this is not possible because is not const fn. However, we can suggest instead.
Personally, I prefer over a separate binding. Even in the case, the generated code will call the initialization function many times. Maybe in the case where bindings are possible, we can suggest both? Where they are not possible, we don't suggest anything right now, so at the least we should suggest there. what do you think?
Once is stable we can suggest that :3. But until then sounds reasonable.
Agreed, good point about . It seems to have a stabilization PR open with an FCP, which is blocked: . Maybe there might be progress on it this month: . Even if we stabilize inline const, it might make sense to wait with suggesting it for a while so that we don't make code depend on the latest MSRV immediately. So therefore, I think that it might still make sense to implement this in the meantime.
I think this should (in the future) suggest  instead, since the function would only be called once if were , whereas calls it for every element.

Related discussion:
text: |                    ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` | = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider annotating `Header<'_>` with `#[derive(Copy)]` | LL + #[derive(Copy)]
Code change:
For this snippet (): rustc gives: Since , for const-able values, rustc suggests the creation of a constant binding. Here this is not possible because is not const fn. However, we can suggest instead.
Personally, I prefer over a separate binding. Even in the case, the generated code will call the initialization function many times. Maybe in the case where bindings are possible, we can suggest both? Where they are not possible, we don't suggest anything right now, so at the least we should suggest there. what do you think?
Once is stable we can suggest that :3. But until then sounds reasonable.
Agreed, good point about . It seems to have a stabilization PR open with an FCP, which is blocked: . Maybe there might be progress on it this month: . Even if we stabilize inline const, it might make sense to wait with suggesting it for a while so that we don't make code depend on the latest MSRV immediately. So therefore, I think that it might still make sense to implement this in the meantime.
I think this should (in the future) suggest  instead, since the function would only be called once if were , whereas calls it for every element.

Related discussion:
text: |      ^ the trait `Copy` is not implemented for `T` | = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider restricting type parameter `T` | LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
Code change:
For this snippet (): rustc gives: Since , for const-able values, rustc suggests the creation of a constant binding. Here this is not possible because is not const fn. However, we can suggest instead.
Personally, I prefer over a separate binding. Even in the case, the generated code will call the initialization function many times. Maybe in the case where bindings are possible, we can suggest both? Where they are not possible, we don't suggest anything right now, so at the least we should suggest there. what do you think?
Once is stable we can suggest that :3. But until then sounds reasonable.
Agreed, good point about . It seems to have a stabilization PR open with an FCP, which is blocked: . Maybe there might be progress on it this month: . Even if we stabilize inline const, it might make sense to wait with suggesting it for a while so that we don't make code depend on the latest MSRV immediately. So therefore, I think that it might still make sense to implement this in the meantime.
I think this should (in the future) suggest  instead, since the function would only be called once if were , whereas calls it for every element.

Related discussion:
text: | = note: required for `Option<Bar>` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)]