about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-05-29 08:45:15 +0000
committerbors <bors@rust-lang.org>2022-05-29 08:45:15 +0000
commitf94fa62d69faf5bd63b3772d3ec4f0c76cf2db57 (patch)
tree8981372169c9dfa5dcc6c6025af06d7e2a282d10
parent6c9fc4fec2193ebfa7ed7eb163b6eea925b56f7b (diff)
parentbe2fa2b31b9e6b01ed96f41061a231ea45a54216 (diff)
downloadrust-f94fa62d69faf5bd63b3772d3ec4f0c76cf2db57.tar.gz
rust-f94fa62d69faf5bd63b3772d3ec4f0c76cf2db57.zip
Auto merge of #12409 - lowr:fix/usize-overflow, r=Veykril
fix overflow during type inference for tuple struct patterns

The following code causes integer overflow during type inference for (malformed) tuple struct patterns.

```rust
struct S(usize);
let S(.., a, b) = S(1);
```

It has been panicking only in debug builds, and working in a way in release builds but it was inconsistent with type inference for tuple patterns:

```rust
struct S(usize);
let S(.., a, b) = S(1); // a -> unknown, b -> usize
let (.., a, b) = (1,);  // a -> usize, b -> unknown
```

With this PR, the overflow no longer happens by utilizing `saturating_sub()` like in other places and type inference for tuple struct patterns is in line with that for tuple patterns.
-rw-r--r--crates/hir-ty/src/infer/pat.rs2
-rw-r--r--crates/hir-ty/src/tests/regression.rs27
2 files changed, 28 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index dbce0f7cd4f..c06d262f5e3 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -42,7 +42,7 @@ impl<'a> InferenceContext<'a> {
             Some(idx) => subpats.split_at(idx),
             None => (subpats, &[][..]),
         };
-        let post_idx_offset = field_tys.iter().count() - post.len();
+        let post_idx_offset = field_tys.iter().count().saturating_sub(post.len());
 
         let pre_iter = pre.iter().enumerate();
         let post_iter = (post_idx_offset..).zip(post.iter());
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index ef27667ffa5..93f765f703c 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1620,3 +1620,30 @@ pub trait Destruct {}
 "#,
     );
 }
+
+#[test]
+fn tuple_struct_pattern_with_unmatched_args_crash() {
+    check_infer(
+        r#"
+struct S(usize);
+fn main() {
+    let S(.., a, b) = S(1);
+    let (.., a, b) = (1,);
+}
+        "#,
+        expect![[r#"
+        27..85 '{     ...1,); }': ()
+        37..48 'S(.., a, b)': S
+        43..44 'a': usize
+        46..47 'b': {unknown}
+        51..52 'S': S(usize) -> S
+        51..55 'S(1)': S
+        53..54 '1': usize
+        65..75 '(.., a, b)': (i32, {unknown})
+        70..71 'a': i32
+        73..74 'b': {unknown}
+        78..82 '(1,)': (i32,)
+        79..80 '1': i32
+        "#]],
+    );
+}