From 53e24fe49c93024ad9ccbdf5e5cc2065c064b1e8 Mon Sep 17 00:00:00 2001 From: bitgaoshu Date: Sat, 10 Dec 2022 14:08:12 +0800 Subject: [PATCH] fix: #12247 fully qualified call required to determine trait method type --- crates/hir-expand/src/name.rs | 2 + crates/hir-ty/src/infer.rs | 5 ++ crates/hir-ty/src/infer/coerce.rs | 1 + crates/hir-ty/src/infer/expr.rs | 8 +++ crates/hir-ty/src/tests/regression.rs | 85 +++++++++++++++++++++++++++ 5 files changed, 101 insertions(+) diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 0e4d20c07ee9..34c79c62b646 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -274,11 +274,13 @@ pub mod known { IntoIter, Try, Ok, + Err, Future, IntoFuture, Result, Option, Output, + Residual, Target, Box, RangeFrom, diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 571b3e968631..50d86a868c79 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -950,6 +950,11 @@ impl<'a> InferenceContext<'a> { self.resolve_output_on(self.resolve_lang_trait(LangItem::Try)?) } + fn resolve_ops_try_err(&self) -> Option { + let trait_ = self.resolve_lang_trait(LangItem::Try)?; + self.db.trait_data(trait_).associated_type_by_name(&name![Residual]) + } + fn resolve_ops_neg_output(&self) -> Option { self.resolve_output_on(self.resolve_lang_trait(LangItem::Neg)?) } diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs index 3293534a068b..3bd743dc0615 100644 --- a/crates/hir-ty/src/infer/coerce.rs +++ b/crates/hir-ty/src/infer/coerce.rs @@ -252,6 +252,7 @@ impl<'a> InferenceTable<'a> { } _ => { // Otherwise, just use unification rules. + eprintln!("just unification rules"); self.unify_and(&from_ty, to_ty, identity) } } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 7b9bf0c5cf3d..a58eccf43453 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -603,6 +603,14 @@ impl<'a> InferenceContext<'a> { .build(); self.write_method_resolution(tgt_expr, func, subst.clone()); } + let actual_ret = inner_ty.clone(); + let residual = self.resolve_ops_try_err(); + let expect_err = self.resolve_associated_type(self.return_ty.clone(), residual); + let actual_err = self.resolve_associated_type(actual_ret, residual); + match self.table.coerce(&actual_err, &expect_err) { + Err(_) => (), + Ok(_) => (), + } let try_output = self.resolve_output_on(trait_); self.resolve_associated_type(inner_ty, try_output) } else { diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index de6ae7fff8fb..f8a9359eb2ba 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -944,6 +944,91 @@ fn clone_iter(s: Iter) { ) } +#[test] +fn issue_12247() { + check_infer( + r#" +//- minicore: result, try +fn aa() -> Result { + let a : Result = Err(E1); + let b = a.mapE()?; +} +struct E1; +struct E2; +struct E3; + +impl From for E2 { + fn from(value: E1) -> Self { + E2 + } +} + +impl From for E3 { + fn from(value: E1) -> Self { + E3 + } +} +trait MapErr { + fn mapE(self) -> Result; +} + +impl MapErr for Result +where + ET: Into, +{ + fn mapE(self) -> Result { + self.map_err(|e| e.into()) + } +} + +impl MapErr for Result +where + ET: Into, +{ + fn mapE(self) -> Result { + self.map_err(|e| e.into()) + } +} + "#, expect![ + r#" +27..92 '{ ...()?; }': Result +37..38 'a': Result +59..62 'Err': Err(E1) -> Result +59..66 'Err(E1)': Result +63..65 'E1': E1 +76..77 'b': Try::Output> +80..81 'a': Result +80..88 'a.mapE()': Result +80..89 'a.mapE()?': Try::Output> +162..167 'value': E1 +181..199 '{ ... }': E2 +191..193 'E2': E2 +238..243 'value': E1 +257..275 '{ ... }': E3 +267..269 'E3': E3 +311..315 'self': Self +420..424 'self': Result +443..485 '{ ... }': Result +453..457 'self': Result +453..479 'self.m...nto())': Result +466..478 '|e| e.into()': |{unknown}| -> {unknown} +467..468 'e': {unknown} +470..471 'e': {unknown} +470..478 'e.into()': {unknown} +572..576 'self': Result +595..637 '{ ... }': Result +605..609 'self': Result +605..631 'self.m...nto())': Result +618..630 '|e| e.into()': |{unknown}| -> {unknown} +619..620 'e': {unknown} +622..623 'e': {unknown} +622..630 'e.into()': {unknown} +"# + ] + ) +} + + #[test] fn issue_8686() { check_infer(