Explain why we check variant equality.

This commit is contained in:
Camille GILLOT 2023-10-11 16:11:55 +00:00
parent ff6812cd20
commit fbf0a0c5ff

View File

@ -512,6 +512,21 @@ fn project(
return Some(fields[f.as_usize()]); return Some(fields[f.as_usize()]);
} else if let Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant)) = self.get(value) } else if let Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant)) = self.get(value)
&& let Value::Aggregate(_, written_variant, fields) = self.get(*outer_value) && let Value::Aggregate(_, written_variant, fields) = self.get(*outer_value)
// This pass is not aware of control-flow, so we do not know whether the
// replacement we are doing is actually reachable. We could be in any arm of
// ```
// match Some(x) {
// Some(y) => /* stuff */,
// None => /* other */,
// }
// ```
//
// In surface rust, the current statement would be unreachable.
//
// However, from the reference chapter on enums and RFC 2195,
// accessing the wrong variant is not UB if the enum has repr.
// So it's not impossible for a series of MIR opts to generate
// a downcast to an inactive variant.
&& written_variant == read_variant && written_variant == read_variant
{ {
return Some(fields[f.as_usize()]); return Some(fields[f.as_usize()]);