Skip to content

Commit 547f266

Browse files
committed
fix: rust-lang#12247 fully qualified call required to determine trait method type
1 parent 398a71a commit 547f266

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
lines changed

crates/hir-expand/src/name.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,13 @@ pub mod known {
266266
IntoIter,
267267
Try,
268268
Ok,
269+
Err,
269270
Future,
270271
IntoFuture,
271272
Result,
272273
Option,
273274
Output,
275+
Residual,
274276
Target,
275277
Box,
276278
RangeFrom,

crates/hir-ty/src/infer.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,17 @@ impl<'a> InferenceContext<'a> {
928928
.or_else(|| trait_data.associated_type_by_name(&name![Output]))
929929
}
930930

931+
fn resolve_ops_try_err(&self) -> Option<TypeAliasId> {
932+
// FIXME resolve via lang_item once try v2 is stable
933+
let path = path![core::ops::Try];
934+
let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
935+
let trait_data = self.db.trait_data(trait_);
936+
trait_data
937+
// FIXME remove once try v2 is stable
938+
.associated_type_by_name(&name![Err])
939+
.or_else(|| trait_data.associated_type_by_name(&name![Residual]))
940+
}
941+
931942
fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
932943
let trait_ = self.resolve_lang_item(name![neg])?.as_trait()?;
933944
self.db.trait_data(trait_).associated_type_by_name(&name![Output])

crates/hir-ty/src/infer/expr.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,14 @@ impl<'a> InferenceContext<'a> {
567567
}
568568
Expr::Try { expr } => {
569569
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
570+
let actual_ret = inner_ty.clone();
571+
let residual = self.resolve_ops_try_err();
572+
let expect_err = self.resolve_associated_type(self.return_ty.clone(), residual);
573+
let actual_err = self.resolve_associated_type(actual_ret, residual);
574+
match self.table.coerce(&actual_err, &expect_err) {
575+
Err(_) => (),
576+
Ok(_) => (),
577+
}
570578
self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok())
571579
}
572580
Expr::Cast { expr, type_ref } => {

crates/hir-ty/src/tests/regression.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,91 @@ fn clone_iter<T>(s: Iter<T>) {
944944
)
945945
}
946946

947+
#[test]
948+
fn issue_12247() {
949+
check_infer(
950+
r#"
951+
//- minicore: result, try
952+
fn aa() -> Result<i32, E3> {
953+
let a : Result<i32, E1> = Err(E1);
954+
let b = a.mapE()?;
955+
}
956+
struct E1;
957+
struct E2;
958+
struct E3;
959+
960+
impl From<E1> for E2 {
961+
fn from(value: E1) -> Self {
962+
E2
963+
}
964+
}
965+
966+
impl From<E1> for E3 {
967+
fn from(value: E1) -> Self {
968+
E3
969+
}
970+
}
971+
trait MapErr<T, E> {
972+
fn mapE(self) -> Result<T, E>;
973+
}
974+
975+
impl <T, ET> MapErr<T, E2> for Result<T, ET>
976+
where
977+
ET: Into<E2>,
978+
{
979+
fn mapE(self) -> Result<T, E2> {
980+
self.map_err(|e| e.into())
981+
}
982+
}
983+
984+
impl <T, ET> MapErr<T, E3> for Result<T, ET>
985+
where
986+
ET: Into<E3>,
987+
{
988+
fn mapE(self) -> Result<T, E3> {
989+
self.map_err(|e| e.into())
990+
}
991+
}
992+
"#, expect![
993+
r#"
994+
27..92 '{ ...()?; }': Result<i32, E3>
995+
37..38 'a': Result<i32, E1>
996+
59..62 'Err': Err<i32, E1>(E1) -> Result<i32, E1>
997+
59..66 'Err(E1)': Result<i32, E1>
998+
63..65 'E1': E1
999+
76..77 'b': Try::Output<Result<i32, E3>>
1000+
80..81 'a': Result<i32, E1>
1001+
80..88 'a.mapE()': Result<i32, E3>
1002+
80..89 'a.mapE()?': Try::Output<Result<i32, E3>>
1003+
162..167 'value': E1
1004+
181..199 '{ ... }': E2
1005+
191..193 'E2': E2
1006+
238..243 'value': E1
1007+
257..275 '{ ... }': E3
1008+
267..269 'E3': E3
1009+
311..315 'self': Self
1010+
420..424 'self': Result<T, ET>
1011+
443..485 '{ ... }': Result<T, E2>
1012+
453..457 'self': Result<T, ET>
1013+
453..479 'self.m...nto())': Result<T, E2>
1014+
466..478 '|e| e.into()': |{unknown}| -> {unknown}
1015+
467..468 'e': {unknown}
1016+
470..471 'e': {unknown}
1017+
470..478 'e.into()': {unknown}
1018+
572..576 'self': Result<T, ET>
1019+
595..637 '{ ... }': Result<T, E3>
1020+
605..609 'self': Result<T, ET>
1021+
605..631 'self.m...nto())': Result<T, E3>
1022+
618..630 '|e| e.into()': |{unknown}| -> {unknown}
1023+
619..620 'e': {unknown}
1024+
622..623 'e': {unknown}
1025+
622..630 'e.into()': {unknown}
1026+
"#
1027+
]
1028+
)
1029+
}
1030+
1031+
9471032
#[test]
9481033
fn issue_8686() {
9491034
check_infer(

0 commit comments

Comments
 (0)