]> git.lizzy.rs Git - rust.git/commitdiff
Fix another crash, and try harder to prevent stack overflows
authorFlorian Diebold <flodiebold@gmail.com>
Sat, 9 Feb 2019 20:31:31 +0000 (21:31 +0100)
committerFlorian Diebold <flodiebold@gmail.com>
Sat, 9 Feb 2019 20:53:55 +0000 (21:53 +0100)
crates/ra_hir/src/ty.rs
crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap [new file with mode: 0644]
crates/ra_hir/src/ty/tests.rs

index 28cb32ac58ada14f7202c3eb0aa7127b9c637441..5d5bde3050b0d676121945badfd9b4a07432651f 100644 (file)
@@ -879,11 +879,22 @@ fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
         ty
     }
 
-    fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool {
-        substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify(t1, t2))
+    fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool {
+        substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth))
     }
 
     fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
+        self.unify_inner(ty1, ty2, 0)
+    }
+
+    fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
+        if depth > 1000 {
+            // prevent stackoverflows
+            panic!("infinite recursion in unification");
+        }
+        if ty1 == ty2 {
+            return true;
+        }
         // try to resolve type vars first
         let ty1 = self.resolve_ty_shallow(ty1);
         let ty2 = self.resolve_ty_shallow(ty2);
@@ -904,13 +915,15 @@ fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
             (
                 Ty::Adt { def_id: def_id1, substs: substs1, .. },
                 Ty::Adt { def_id: def_id2, substs: substs2, .. },
-            ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2),
-            (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2),
-            (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2),
-            (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2),
+            ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2, depth + 1),
+            (Ty::Slice(t1), Ty::Slice(t2)) => self.unify_inner(t1, t2, depth + 1),
+            (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => {
+                self.unify_inner(t1, t2, depth + 1)
+            }
+            (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1),
             (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true,
             (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => {
-                ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify(t1, t2))
+                ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1))
             }
             (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
             | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap
new file mode 100644 (file)
index 0000000..6bbf59f
--- /dev/null
@@ -0,0 +1,30 @@
+---
+created: "2019-02-09T20:28:37.294693728Z"
+creator: insta@0.6.1
+source: crates/ra_hir/src/ty/tests.rs
+expression: "&result"
+---
+[27; 323) '{     ...   } }': ()
+[33; 321) 'for co...     }': ()
+[37; 44) 'content': &[unknown]
+[48; 61) 'doesnt_matter': [unknown]
+[62; 321) '{     ...     }': ()
+[76; 80) 'name': &&[unknown]
+[83; 167) 'if doe...     }': &&[unknown]
+[86; 99) 'doesnt_matter': bool
+[100; 129) '{     ...     }': &&[unknown]
+[114; 119) 'first': &&[unknown]
+[135; 167) '{     ...     }': &&[unknown]
+[149; 157) '&content': &&[unknown]
+[150; 157) 'content': &[unknown]
+[182; 189) 'content': &&[unknown]
+[192; 314) 'if ICE...     }': &&[unknown]
+[195; 232) 'ICE_RE..._VALUE': [unknown]
+[195; 248) 'ICE_RE...&name)': bool
+[242; 247) '&name': &&&[unknown]
+[243; 247) 'name': &&[unknown]
+[249; 277) '{     ...     }': &&[unknown]
+[263; 267) 'name': &&[unknown]
+[283; 314) '{     ...     }': &[unknown]
+[297; 304) 'content': &[unknown]
+
index e088df97c408d5e6fcf613d2847018db962487df..8cc771084fe937fbb937854edd13520c4a6979bb 100644 (file)
@@ -693,6 +693,31 @@ pub fn primitive_type() {
     );
 }
 
+#[test]
+fn infer_std_crash_5() {
+    // taken from rustc
+    check_inference(
+        "infer_std_crash_5",
+        r#"
+fn extra_compiler_flags() {
+    for content in doesnt_matter {
+        let name = if doesnt_matter {
+            first
+        } else {
+            &content
+        };
+
+        let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
+            name
+        } else {
+            content
+        };
+    }
+}
+"#,
+    );
+}
+
 fn infer(content: &str) -> String {
     let (db, _, file_id) = MockDatabase::with_single_file(content);
     let source_file = db.parse(file_id);