diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-12 21:05:09 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-12 21:05:09 +0000 |
commit | 92faa2225ae2c508c605b8d6f53381a2cc330d32 (patch) | |
tree | 5f9237fe67c6a5fd8e3f17eddfc3ee9b5a7a35a8 /crates/ra_hir | |
parent | 61324a845bde0959c1f9ac86ce31d022812f4c21 (diff) | |
parent | e5f9d54661a46c3e37130716264f8c5ea7540af9 (diff) |
Merge #815
815: Fix another crash r=matklad a=flodiebold
Found while typechecking rustc with better name resolution...
`walk_mut` doing a preorder walk can lead to an infinite recursion when substituting type parameters; postorder is actually what we want.
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_nested_generics_crash.snap | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 19 |
3 files changed, 33 insertions, 2 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 2dc1de41a..f28a7e731 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -450,7 +450,6 @@ impl Ty { | |||
450 | } | 450 | } |
451 | 451 | ||
452 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | 452 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { |
453 | f(self); | ||
454 | match self { | 453 | match self { |
455 | Ty::Slice(t) | Ty::Array(t) => t.walk(f), | 454 | Ty::Slice(t) | Ty::Array(t) => t.walk(f), |
456 | Ty::RawPtr(t, _) => t.walk(f), | 455 | Ty::RawPtr(t, _) => t.walk(f), |
@@ -490,10 +489,10 @@ impl Ty { | |||
490 | | Ty::Infer(_) | 489 | | Ty::Infer(_) |
491 | | Ty::Unknown => {} | 490 | | Ty::Unknown => {} |
492 | } | 491 | } |
492 | f(self); | ||
493 | } | 493 | } |
494 | 494 | ||
495 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 495 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
496 | f(self); | ||
497 | match self { | 496 | match self { |
498 | Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f), | 497 | Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f), |
499 | Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), | 498 | Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), |
@@ -544,6 +543,7 @@ impl Ty { | |||
544 | | Ty::Infer(_) | 543 | | Ty::Infer(_) |
545 | | Ty::Unknown => {} | 544 | | Ty::Unknown => {} |
546 | } | 545 | } |
546 | f(self); | ||
547 | } | 547 | } |
548 | 548 | ||
549 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Ty { | 549 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Ty { |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_nested_generics_crash.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_nested_generics_crash.snap new file mode 100644 index 000000000..209454a91 --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_nested_generics_crash.snap | |||
@@ -0,0 +1,12 @@ | |||
1 | --- | ||
2 | created: "2019-02-11T21:59:04.302375838Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [92; 106) 'query_response': Canonical<QueryResponse<R>> | ||
8 | [137; 167) '{ ...lue; }': () | ||
9 | [143; 164) '&query....value': &QueryResponse<R> | ||
10 | [144; 158) 'query_response': Canonical<QueryResponse<R>> | ||
11 | [144; 164) 'query_....value': QueryResponse<R> | ||
12 | |||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index e64fd2749..203f1fe4d 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -719,6 +719,25 @@ fn extra_compiler_flags() { | |||
719 | ); | 719 | ); |
720 | } | 720 | } |
721 | 721 | ||
722 | #[test] | ||
723 | fn infer_nested_generics_crash() { | ||
724 | // another crash found typechecking rustc | ||
725 | check_inference( | ||
726 | "infer_nested_generics_crash", | ||
727 | r#" | ||
728 | struct Canonical<V> { | ||
729 | value: V, | ||
730 | } | ||
731 | struct QueryResponse<V> { | ||
732 | value: V, | ||
733 | } | ||
734 | fn test<R>(query_response: Canonical<QueryResponse<R>>) { | ||
735 | &query_response.value; | ||
736 | } | ||
737 | "#, | ||
738 | ); | ||
739 | } | ||
740 | |||
722 | fn infer(content: &str) -> String { | 741 | fn infer(content: &str) -> String { |
723 | let (db, _, file_id) = MockDatabase::with_single_file(content); | 742 | let (db, _, file_id) = MockDatabase::with_single_file(content); |
724 | let source_file = db.parse(file_id); | 743 | let source_file = db.parse(file_id); |