about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-12-04 18:53:50 +0000
committerMichael Goulet <michael@errs.io>2022-12-04 18:53:50 +0000
commitd442c015d6d688460a182947e797f4bf69876044 (patch)
tree21114349ca0ebd3f9497869960a0f547a1af1612
parent26b24cd7558c02c433ef9f621894cb6a2f31898d (diff)
downloadrust-d442c015d6d688460a182947e797f4bf69876044.tar.gz
rust-d442c015d6d688460a182947e797f4bf69876044.zip
Don't ICE in ExprUseVisitor on FRU for non-existent struct
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs7
-rw-r--r--src/test/ui/structs/unresolved-struct-with-fru.rs12
-rw-r--r--src/test/ui/structs/unresolved-struct-with-fru.stderr9
3 files changed, 27 insertions, 1 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 4f06ad8a018..03b174c7795 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -523,6 +523,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         // Consume the expressions supplying values for each field.
         for field in fields {
             self.consume_expr(field.expr);
+
+            // The struct path probably didn't resolve
+            if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
+                self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field");
+            }
         }
 
         let with_expr = match *opt_with {
@@ -542,7 +547,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
                     let is_mentioned = fields
                         .iter()
-                        .any(|f| self.mc.typeck_results.field_index(f.hir_id) == f_index);
+                        .any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index));
                     if !is_mentioned {
                         let field_place = self.mc.cat_projection(
                             &*with_expr,
diff --git a/src/test/ui/structs/unresolved-struct-with-fru.rs b/src/test/ui/structs/unresolved-struct-with-fru.rs
new file mode 100644
index 00000000000..c9fdca45772
--- /dev/null
+++ b/src/test/ui/structs/unresolved-struct-with-fru.rs
@@ -0,0 +1,12 @@
+struct S {
+    a: u32,
+}
+
+fn main() {
+    let s1 = S { a: 1 };
+
+    let _ = || {
+        let s2 = Oops { a: 2, ..s1 };
+        //~^ ERROR cannot find struct, variant or union type `Oops` in this scope
+    };
+}
diff --git a/src/test/ui/structs/unresolved-struct-with-fru.stderr b/src/test/ui/structs/unresolved-struct-with-fru.stderr
new file mode 100644
index 00000000000..a5796a22225
--- /dev/null
+++ b/src/test/ui/structs/unresolved-struct-with-fru.stderr
@@ -0,0 +1,9 @@
+error[E0422]: cannot find struct, variant or union type `Oops` in this scope
+  --> $DIR/unresolved-struct-with-fru.rs:9:18
+   |
+LL |         let s2 = Oops { a: 2, ..s1 };
+   |                  ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.