From fbf0a0c5ff0177afda43e404b2e03a48012cfe8f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 11 Oct 2023 16:11:55 +0000 Subject: [PATCH] Explain why we check variant equality. --- compiler/rustc_mir_transform/src/gvn.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index cced62ecf37..b9e75f5c93f 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -512,6 +512,21 @@ fn project( return Some(fields[f.as_usize()]); } else if let Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant)) = self.get(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 { return Some(fields[f.as_usize()]);