Skip to content

Commit ff62657

Browse files
authored
Rollup merge of #145361 - xizheyin:145294, r=compiler-errors
Suppress wrapper suggestion when expected and actual ty are the same adt and the variant is unresolved Fixes #145294 I initially tried the desired suggestion in this issue, but since that suggestion occurs in the expected type, it is inappropriate to suggest for expected expressions (see other suggest methods in the same file). I believe that suppressing the incorrect suggestion is the more appropriate choice here. I opted for a slightly more general approach: when the expected type and actual type are the same ADT (e.g., both are Result in this example), we assume that code tend to compare the internal generic parameters(i.e. `Option<&str>` vs `Option<String>`, instead of `E = _` vs `Result<Option<String>>>`). When `E` is an unresolved infer type in the expected type (`_` in this example), we should not wrapp the actual type. Two commits show the difference. r? compiler
2 parents 30e5be4 + e0cc2be commit ff62657

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2378,6 +2378,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23782378
.filter_map(|variant| {
23792379
let sole_field = &variant.single_field();
23802380

2381+
// When expected_ty and expr_ty are the same ADT, we prefer to compare their internal generic params,
2382+
// When the current variant has a sole field whose type is still an unresolved inference variable,
2383+
// suggestions would be often wrong. So suppress the suggestion. See #145294.
2384+
if let (ty::Adt(exp_adt, _), ty::Adt(act_adt, _)) = (expected.kind(), expr_ty.kind())
2385+
&& exp_adt.did() == act_adt.did()
2386+
&& sole_field.ty(self.tcx, args).is_ty_var() {
2387+
return None;
2388+
}
2389+
23812390
let field_is_local = sole_field.did.is_local();
23822391
let field_is_accessible =
23832392
sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Suppress the suggestion that adding a wrapper.
2+
// When expected_ty and expr_ty are the same ADT,
3+
// we prefer to compare their internal generic params,
4+
// so when the current variant corresponds to an unresolved infer,
5+
// the suggestion is rejected.
6+
// e.g. `Ok(Some("hi"))` is type of `Result<Option<&str>, _>`,
7+
// where `E` is still an unresolved inference variable.
8+
9+
fn foo() -> Result<Option<String>, ()> {
10+
todo!()
11+
}
12+
13+
#[derive(PartialEq, Debug)]
14+
enum Bar<T, E> {
15+
A(T),
16+
B(E),
17+
}
18+
19+
fn bar() -> Bar<String, ()> {
20+
todo!()
21+
}
22+
23+
fn main() {
24+
assert_eq!(Ok(Some("hi")), foo()); //~ ERROR mismatched types [E0308]
25+
assert_eq!(Bar::A("hi"), bar()); //~ ERROR mismatched types [E0308]
26+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/suggest-add-wrapper-issue-145294.rs:24:32
3+
|
4+
LL | assert_eq!(Ok(Some("hi")), foo());
5+
| ^^^^^ expected `Result<Option<&str>, _>`, found `Result<Option<String>, ()>`
6+
|
7+
= note: expected enum `Result<Option<&str>, _>`
8+
found enum `Result<Option<String>, ()>`
9+
10+
error[E0308]: mismatched types
11+
--> $DIR/suggest-add-wrapper-issue-145294.rs:25:30
12+
|
13+
LL | assert_eq!(Bar::A("hi"), bar());
14+
| ^^^^^ expected `Bar<&str, _>`, found `Bar<String, ()>`
15+
|
16+
= note: expected enum `Bar<&str, _>`
17+
found enum `Bar<String, ()>`
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)