about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs9
-rw-r--r--tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs26
-rw-r--r--tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr21
3 files changed, 56 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 6013430e1ff..aca3840712e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2378,6 +2378,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .filter_map(|variant| {
                     let sole_field = &variant.single_field();
 
+                    // When expected_ty and expr_ty are the same ADT, we prefer to compare their internal generic params,
+                    // When the current variant has a sole field whose type is still an unresolved inference variable,
+                    // suggestions would be often wrong. So suppress the suggestion. See #145294.
+                    if let (ty::Adt(exp_adt, _), ty::Adt(act_adt, _)) = (expected.kind(), expr_ty.kind())
+                        && exp_adt.did() == act_adt.did()
+                        && sole_field.ty(self.tcx, args).is_ty_var() {
+                            return None;
+                    }
+
                     let field_is_local = sole_field.did.is_local();
                     let field_is_accessible =
                         sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
diff --git a/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs
new file mode 100644
index 00000000000..cfe167cf88d
--- /dev/null
+++ b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs
@@ -0,0 +1,26 @@
+// Suppress the suggestion that adding a wrapper.
+// When expected_ty and expr_ty are the same ADT,
+// we prefer to compare their internal generic params,
+// so when the current variant corresponds to an unresolved infer,
+// the suggestion is rejected.
+// e.g. `Ok(Some("hi"))` is type of `Result<Option<&str>, _>`,
+// where `E` is still an unresolved inference variable.
+
+fn foo() -> Result<Option<String>, ()> {
+    todo!()
+}
+
+#[derive(PartialEq, Debug)]
+enum Bar<T, E> {
+    A(T),
+    B(E),
+}
+
+fn bar() -> Bar<String, ()> {
+    todo!()
+}
+
+fn main() {
+    assert_eq!(Ok(Some("hi")), foo()); //~ ERROR mismatched types [E0308]
+    assert_eq!(Bar::A("hi"), bar()); //~ ERROR mismatched types [E0308]
+}
diff --git a/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr
new file mode 100644
index 00000000000..5e4ad132210
--- /dev/null
+++ b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/suggest-add-wrapper-issue-145294.rs:24:32
+   |
+LL |     assert_eq!(Ok(Some("hi")), foo());
+   |                                ^^^^^ expected `Result<Option<&str>, _>`, found `Result<Option<String>, ()>`
+   |
+   = note: expected enum `Result<Option<&str>, _>`
+              found enum `Result<Option<String>, ()>`
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-add-wrapper-issue-145294.rs:25:30
+   |
+LL |     assert_eq!(Bar::A("hi"), bar());
+   |                              ^^^^^ expected `Bar<&str, _>`, found `Bar<String, ()>`
+   |
+   = note: expected enum `Bar<&str, _>`
+              found enum `Bar<String, ()>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.