Transmuting between non-repr(C) types is UB
That's not entirely correct. The full statement is that ransmuting between types that don't have a guaranteed layout is relying on unspecified behavior (and I see @pcpthm has been arguing for that, too) .
Miri cannot detect when you are relying on unspecified behavior, that's why you do not get an error. This is different from what we usually refer to as UB, so while it is often a convenient short-hand to say that such transmutes are UB, it can also be confusing.
Do you have a link for that? We should likely fix the Nomicon then.
This seems to indicate an outdated view of what UB is; also see the UCG glossary. "Undefined Behavior", these days (since around C89) is not about things "not being defined" in the spec; it is about things explicitly being defined as never happening -- so that if they happen anyway, that's "causing undefined behavior". If the spec of the Abstract Machine doesn't define something, that's just an incomplete spec and not a license for anyone to do anything.
No, that is wrong. The compiler can never move possibly-UB-causing operations to before a check that might avoid executing them! if false { cause_ub(); }
is a perfectly valid thing to do. Dead code never gets executed on the Abstract Machine, and thus there cannot be UB from dead code either.
The compiler is free to reorder UB around operations that will definitely terminate. This leads to the (in)famous "atemporal UB" in C:
printf("Hello\n"); // definitely terminates
cause_ub();
No matter what printf
does, this program will definitely always eventually have UB, and that is en9ough to give the compiler license to move the UB "up" and make it happen earlier. But that is not the same as moving UB out of conditionals that guard against UB!
The UCG is gathering information on the de-facto situation of Rust and forming consensus within itself to make recommendations to the lang team. Nothing the UCG does or says has any normative power. The plan is, once we have some amount of material, to start writing RFCs that go through the usual process to eventually become normative.
So, if you view the UCG documents as pre-RFCs, you are not very wrong.
But, to come back to the original question by @CreepySkeleton (man you guys went on a tangent here ): that code seems fine to me. transmute::<Option<&Data>, usize>
is indeed the same as as_ref()
(well, at least my reading of this FCP is that we have lang team consensus on that), and the safety docs for that say
When calling this method, you have to ensure that if the pointer is non-NULL, then it is properly aligned, dereferencable (for the whole size of T
) and points to an initialized instance of T
.
So as long as you an make sure that this is true whenever as_ref
is called (and it seems like you do), I'd say you are good.