about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-02-12 09:24:33 +0100
committerLukas Wirth <lukastw97@gmail.com>2025-02-12 09:24:33 +0100
commit3a041fcc2cc514ef87f29d8aa8300a0f6a2fa0da (patch)
tree96b7c28888e9d98eaec600ef6e38cdaad4958f7c
parentda4c09937559e8d93cc6499ec8510a3571449061 (diff)
downloadrust-3a041fcc2cc514ef87f29d8aa8300a0f6a2fa0da.tar.gz
rust-3a041fcc2cc514ef87f29d8aa8300a0f6a2fa0da.zip
Propogate error types in mir type projections
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs13
2 files changed, 22 insertions, 2 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
index 84d8950b1aa..41304bbd8a9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
@@ -10,7 +10,7 @@ use crate::{
     lang_items::is_box,
     mapping::ToChalk,
     CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap,
-    Substitution, TraitEnvironment, Ty, TyKind,
+    Substitution, TraitEnvironment, Ty, TyExt, TyKind,
 };
 use base_db::CrateId;
 use chalk_ir::Mutability;
@@ -144,6 +144,13 @@ impl<V, T> ProjectionElem<V, T> {
         closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
         krate: CrateId,
     ) -> Ty {
+        // we only bail on mir building when there are type mismatches
+        // but error types may pop up resulting in us still attempting to build the mir
+        // so just propagate the error type
+        if base.is_unknown() {
+            return TyKind::Error.intern(Interner);
+        }
+
         if matches!(base.kind(Interner), TyKind::Alias(_) | TyKind::AssociatedType(..)) {
             base = normalize(
                 db,
@@ -166,7 +173,7 @@ impl<V, T> ProjectionElem<V, T> {
                     TyKind::Error.intern(Interner)
                 }
             },
-            ProjectionElem::Field(Either::Left(f)) => match &base.kind(Interner) {
+            ProjectionElem::Field(Either::Left(f)) => match base.kind(Interner) {
                 TyKind::Adt(_, subst) => {
                     db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst)
                 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
index 67ece566941..d5caf4de336 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
@@ -263,4 +263,17 @@ fn main() {
 "#,
         );
     }
+
+    // regression test as we used to panic in this scenario
+    #[test]
+    fn unknown_struct_pattern_param_type() {
+        check_diagnostics(
+            r#"
+struct S { field : u32 }
+fn f(S { field }: error) {
+      // ^^^^^ 💡 warn: unused variable
+}
+"#,
+        );
+    }
 }