self is a local variable that always becomes invalid by the end of the function. In the first function, the *const i32 is pointing at that local variable, and so it is pointing at garbage after the function completes. It's a dangling pointer, and it is always invalid to dereference it at the call site.
In the second function, self is a reference to something that exists outside of the function. And the *const i32 is pointing at that same thing which is outside of the function. You never create a reference or pointer to the self variable in this case, you just effectively return a copy of one that already exists. How long the returned pointer is valid to dereference depends on what is going on at the call site.
struct Length(i32,*const i32);
pub fn from_ptr(&self) -> i32{
// SAFE: Length drop then i32 drop too!!
unsafe{self.1.read()}
}
When you move the Length around, the address where the i32 is changes, but the value of the *const i32 does not change, so this doesn't work like you seem to think it does.
There's a problem with the unsafe block in E1. The lifetime of v: &i32 in _new is unrestricted, so its address may or may not be valid at the time of from_ptr.
By the way, if you meant to create a self-referencing struct (i.e. the pointer points to an address inside Length, which I guess you want to be its i32 field) then I read that it requires using Pin to prevent the Length from being moved. I'm not really familiar with that, but I'll drop a link to the docs
And your current code is not self-referencing, E1's pointer points to wherever v points to (can be in main's stack frame, on the heap via &*b where b is a Box<i32>, etc), and E2's pointer points within _new's stack frame allocation.