Skip to content

Commit 025d58a

Browse files
Auto merge of #140283 - adwinwhite:fn-pointer-coercion, r=<try>
Fix accidental type inference in array coercion
2 parents 2886b36 + a7b44b9 commit 025d58a

File tree

4 files changed

+66
-6
lines changed

4 files changed

+66
-6
lines changed

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,12 +1817,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18171817
let element_ty = if !args.is_empty() {
18181818
let coerce_to = expected
18191819
.to_option(self)
1820-
.and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index())
1820+
.and_then(|uty| {
1821+
self.try_structurally_resolve_type(expr.span, uty)
1822+
.builtin_index()
1823+
// Avoid using the original type variable as the coerce_to type, as it may resolve
1824+
// during the first coercion instead of being the LUB type.
1825+
.filter(|t| !self.try_structurally_resolve_type(expr.span, *t).is_ty_var())
1826+
})
18211827
.unwrap_or_else(|| self.next_ty_var(expr.span));
1828+
let element_expected = Expectation::ExpectHasType(coerce_to)
1829+
.try_structurally_resolve_and_adjust_for_branches(self, expr.span);
18221830
let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
18231831
assert_eq!(self.diverges.get(), Diverges::Maybe);
18241832
for e in args {
1825-
let e_ty = self.check_expr_with_hint(e, coerce_to);
1833+
let e_ty = self.check_expr_with_expectation(e, element_expected);
18261834
let cause = self.misc(e.span);
18271835
coerce.coerce(self, &cause, e, e_ty);
18281836
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//@ run-pass
2+
// Check that least upper bound coercions don't resolve type variable merely based on the first
3+
// coercion. Check issue #136420.
4+
5+
fn foo() {}
6+
fn bar() {}
7+
8+
fn infer<T>(_: T) {}
9+
10+
fn infer_array_element<T>(_: [T; 2]) {}
11+
12+
fn main() {
13+
// Previously the element type's ty var will be unified with `foo`.
14+
let _: [_; 2] = [foo, bar];
15+
infer_array_element([foo, bar]);
16+
let _ = [foo, if false { bar } else { foo }];
17+
18+
let _ = if false {
19+
foo
20+
} else {
21+
bar
22+
};
23+
infer(if false {
24+
foo
25+
} else {
26+
bar
27+
});
28+
let _ = if false {
29+
foo
30+
} else {
31+
if false {
32+
bar
33+
} else {
34+
foo
35+
}
36+
};
37+
38+
39+
let _ = match false {
40+
true => foo,
41+
false => bar,
42+
};
43+
infer(match false {
44+
true => foo,
45+
false => bar,
46+
});
47+
let _ = match 1 {
48+
2 => foo,
49+
_ => if false {
50+
bar
51+
} else {
52+
foo
53+
},
54+
};
55+
}

tests/ui/coercion/coerce-unify.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,4 @@ pub fn main() {
6262
let a = [1, 2, 3];
6363
let v = vec![1, 2, 3];
6464
check2!(&a[..], &v);
65-
66-
// Make sure in-array coercion still works.
67-
let _ = [("a", Default::default()), (Default::default(), "b"), (&s, &s)];
6865
}

tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ error[E0308]: mismatched types
103103
--> $DIR/typo-in-repeat-expr-issue-80173.rs:57:23
104104
|
105105
LL | let k = vec!['c', 10];
106-
| ^^ expected `char`, found `u8`
106+
| ^^ expected `char`, found integer
107107
|
108108
help: replace the comma with a semicolon to create a vector
109109
|

0 commit comments

Comments
 (0)