Skip to content

Commit f2aea1e

Browse files
committed
further update fuzzy_match_tys
1 parent 0efc6c0 commit f2aea1e

25 files changed

+111
-66
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+52-34
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,13 @@ use suggestions::InferCtxtExt as _;
4040
pub use rustc_infer::traits::error_reporting::*;
4141

4242
// When outputting impl candidates, prefer showing those that are more similar.
43+
//
44+
// We also compare candidates after skipping lifetimes, which has a lower
45+
// priority than exact matches.
4346
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
4447
pub enum CandidateSimilarity {
45-
Exact,
46-
Fuzzy,
48+
Exact { ignoring_lifetimes: bool },
49+
Fuzzy { ignoring_lifetimes: bool },
4750
}
4851

4952
#[derive(Debug, Clone, Copy)]
@@ -1155,7 +1158,12 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
11551158
error: &MismatchedProjectionTypes<'tcx>,
11561159
);
11571160

1158-
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool;
1161+
fn fuzzy_match_tys(
1162+
&self,
1163+
a: Ty<'tcx>,
1164+
b: Ty<'tcx>,
1165+
ignoring_lifetimes: bool,
1166+
) -> Option<CandidateSimilarity>;
11591167

11601168
fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
11611169

@@ -1458,24 +1466,32 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
14581466
});
14591467
}
14601468

1461-
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
1469+
fn fuzzy_match_tys(
1470+
&self,
1471+
mut a: Ty<'tcx>,
1472+
mut b: Ty<'tcx>,
1473+
ignoring_lifetimes: bool,
1474+
) -> Option<CandidateSimilarity> {
14621475
/// returns the fuzzy category of a given type, or None
14631476
/// if the type can be equated to any type.
1464-
fn type_category(t: Ty<'_>) -> Option<u32> {
1477+
fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
14651478
match t.kind() {
14661479
ty::Bool => Some(0),
14671480
ty::Char => Some(1),
14681481
ty::Str => Some(2),
1469-
ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
1470-
ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
1482+
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::String, def.did) => Some(2),
1483+
ty::Int(..)
1484+
| ty::Uint(..)
1485+
| ty::Float(..)
1486+
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) => Some(4),
14711487
ty::Ref(..) | ty::RawPtr(..) => Some(5),
14721488
ty::Array(..) | ty::Slice(..) => Some(6),
14731489
ty::FnDef(..) | ty::FnPtr(..) => Some(7),
14741490
ty::Dynamic(..) => Some(8),
14751491
ty::Closure(..) => Some(9),
14761492
ty::Tuple(..) => Some(10),
1477-
ty::Projection(..) => Some(11),
1478-
ty::Param(..) => Some(12),
1493+
ty::Param(..) => Some(11),
1494+
ty::Projection(..) => Some(12),
14791495
ty::Opaque(..) => Some(13),
14801496
ty::Never => Some(14),
14811497
ty::Adt(..) => Some(15),
@@ -1497,17 +1513,33 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
14971513
}
14981514
};
14991515

1500-
match (type_category(a), type_category(b)) {
1501-
(Some(cat_a), Some(cat_b)) => match (a.kind(), b.kind()) {
1516+
if !ignoring_lifetimes {
1517+
a = strip_references(a);
1518+
b = strip_references(b);
1519+
}
1520+
1521+
let cat_a = type_category(self.tcx, a)?;
1522+
let cat_b = type_category(self.tcx, b)?;
1523+
if a == b {
1524+
Some(CandidateSimilarity::Exact { ignoring_lifetimes })
1525+
} else if cat_a == cat_b {
1526+
match (a.kind(), b.kind()) {
15021527
(ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b,
1503-
_ if cat_a == cat_b => true,
1504-
(ty::Ref(..), _) | (_, ty::Ref(..)) => {
1505-
self.fuzzy_match_tys(strip_references(a), strip_references(b))
1528+
// Matching on references results in a lot of unhelpful
1529+
// suggestions, so let's just not do that for now.
1530+
//
1531+
// We still upgrade successful matches to `ignoring_lifetimes: true`
1532+
// to prioritize that impl.
1533+
(ty::Ref(..) | ty::RawPtr(..), ty::Ref(..) | ty::RawPtr(..)) => {
1534+
self.fuzzy_match_tys(a, b, true).is_some()
15061535
}
1507-
_ => false,
1508-
},
1509-
// infer and error can be equated to all types
1510-
_ => true,
1536+
_ => true,
1537+
}
1538+
.then_some(CandidateSimilarity::Fuzzy { ignoring_lifetimes })
1539+
} else if ignoring_lifetimes {
1540+
None
1541+
} else {
1542+
self.fuzzy_match_tys(a, b, true)
15111543
}
15121544
}
15131545

@@ -1533,22 +1565,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
15331565

15341566
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
15351567

1536-
// Check for exact match.
1537-
if trait_ref.skip_binder().self_ty() == imp.self_ty() {
1538-
return Some(ImplCandidate {
1539-
trait_ref: imp,
1540-
similarity: CandidateSimilarity::Exact,
1541-
});
1542-
}
1543-
1544-
if self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty()) {
1545-
return Some(ImplCandidate {
1546-
trait_ref: imp,
1547-
similarity: CandidateSimilarity::Fuzzy,
1548-
});
1549-
}
1550-
1551-
None
1568+
self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty(), false)
1569+
.map(|similarity| ImplCandidate { trait_ref: imp, similarity })
15521570
})
15531571
.collect()
15541572
}

compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
5656
trait_ref.substs.types().skip(1),
5757
impl_trait_ref.substs.types().skip(1),
5858
)
59-
.all(|(u, v)| self.fuzzy_match_tys(u, v))
59+
.all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
6060
{
6161
fuzzy_match_impls.push(def_id);
6262
}

src/test/ui/associated-types/hr-associated-type-bound-1.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | type U = str;
55
| ^^^ the trait `Clone` is not implemented for `str`
66
|
7+
= help: the following implementations were found:
8+
<String as Clone>
79
note: required by a bound in `X`
810
--> $DIR/hr-associated-type-bound-1.rs:3:33
911
|

src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | type V = str;
55
| ^^^ the trait `Clone` is not implemented for `str`
66
|
7+
= help: the following implementations were found:
8+
<String as Clone>
79
note: required by a bound in `Y`
810
--> $DIR/hr-associated-type-bound-param-1.rs:4:36
911
|

src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | T: Z<'a, u16>,
55
| ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
66
|
7+
= help: the following implementations were found:
8+
<String as Clone>
79
note: required by a bound in `Z`
810
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
911
|
@@ -19,6 +21,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
1921
LL | T: Z<'a, u16>,
2022
| ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
2123
|
24+
= help: the following implementations were found:
25+
<String as Clone>
2226
note: required by a bound in `Z`
2327
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
2428
|
@@ -34,6 +38,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
3438
LL | type W = str;
3539
| ^^^ the trait `Clone` is not implemented for `str`
3640
|
41+
= help: the following implementations were found:
42+
<String as Clone>
3743
note: required by a bound in `Z`
3844
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
3945
|

src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | type U = str;
55
| ^^^ the trait `Clone` is not implemented for `str`
66
|
7+
= help: the following implementations were found:
8+
<String as Clone>
79
note: required by a bound in `X`
810
--> $DIR/hr-associated-type-bound-param-3.rs:4:33
911
|

src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | type U = str;
55
| ^^^ the trait `Clone` is not implemented for `str`
66
|
7+
= help: the following implementations were found:
8+
<String as Clone>
79
note: required by a bound in `X`
810
--> $DIR/hr-associated-type-bound-param-4.rs:4:36
911
|

src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | type U = str;
55
| ^^^ the trait `Clone` is not implemented for `str`
66
|
7+
= help: the following implementations were found:
8+
<String as Clone>
79
note: required by a bound in `X`
810
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
911
|
@@ -19,6 +21,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
1921
LL | type U = str;
2022
| ^^^ the trait `Clone` is not implemented for `str`
2123
|
24+
= help: the following implementations were found:
25+
<String as Clone>
2226
note: required by a bound in `X`
2327
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
2428
|

src/test/ui/block-result/issue-22645.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
44
LL | b + 3
55
| ^ the trait `Scalar` is not implemented for `{integer}`
66
|
7+
= help: the following implementations were found:
8+
<f64 as Scalar>
79
note: required because of the requirements on the impl of `Add<{integer}>` for `Bob`
810
--> $DIR/issue-22645.rs:8:19
911
|

src/test/ui/chalkify/chalk_initial_program.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
44
LL | gimme::<f32>();
55
| ^^^ the trait `Foo` is not implemented for `f32`
66
|
7+
= help: the following implementations were found:
8+
<i32 as Foo>
9+
<u32 as Foo>
710
note: required by a bound in `gimme`
811
--> $DIR/chalk_initial_program.rs:9:13
912
|

src/test/ui/chalkify/impl_wf.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
1717
LL | impl Baz<f32> for f32 { }
1818
| ^^^^^^^^ the trait `Foo` is not implemented for `f32`
1919
|
20+
= help: the following implementations were found:
21+
<i32 as Foo>
2022
note: required by a bound in `Baz`
2123
--> $DIR/impl_wf.rs:18:31
2224
|

src/test/ui/chalkify/impl_wf_2.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
44
LL | type Item = f32;
55
| ^^^ the trait `Foo` is not implemented for `f32`
66
|
7+
= help: the following implementations were found:
8+
<i32 as Foo>
79
note: required by a bound in `Bar::Item`
810
--> $DIR/impl_wf_2.rs:8:16
911
|

src/test/ui/chalkify/type_inference.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ LL | only_bar(x);
66
| |
77
| required by a bound introduced by this call
88
|
9+
= help: the following implementations were found:
10+
<i32 as Bar>
11+
<u32 as Bar>
912
note: required by a bound in `only_bar`
1013
--> $DIR/type_inference.rs:12:16
1114
|

src/test/ui/chalkify/type_wf.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `{float}: Foo` is not satisfied
44
LL | let s = S {
55
| ^ the trait `Foo` is not implemented for `{float}`
66
|
7+
= help: the following implementations were found:
8+
<i32 as Foo>
79
note: required by a bound in `S`
810
--> $DIR/type_wf.rs:6:13
911
|

src/test/ui/kindck/kindck-copy.stderr

+8-12
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ LL | assert_copy::<&'static mut isize>();
55
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
66
|
77
= help: the following implementations were found:
8-
<&T as Copy>
9-
<*const T as Copy>
10-
<*mut T as Copy>
8+
<isize as Copy>
9+
<f32 as Copy>
10+
<f64 as Copy>
1111
<i128 as Copy>
12-
and 11 others
12+
and 10 others
1313
note: required by a bound in `assert_copy`
1414
--> $DIR/kindck-copy.rs:5:18
1515
|
@@ -23,11 +23,11 @@ LL | assert_copy::<&'a mut isize>();
2323
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
2424
|
2525
= help: the following implementations were found:
26-
<&T as Copy>
27-
<*const T as Copy>
28-
<*mut T as Copy>
26+
<isize as Copy>
27+
<f32 as Copy>
28+
<f64 as Copy>
2929
<i128 as Copy>
30-
and 11 others
30+
and 10 others
3131
note: required by a bound in `assert_copy`
3232
--> $DIR/kindck-copy.rs:5:18
3333
|
@@ -112,10 +112,6 @@ error[E0277]: the trait bound `&'a mut (dyn Dummy + Send + 'a): Copy` is not sat
112112
LL | assert_copy::<&'a mut (dyn Dummy + Send)>();
113113
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut (dyn Dummy + Send + 'a)`
114114
|
115-
= help: the following implementations were found:
116-
<&T as Copy>
117-
<*const T as Copy>
118-
<*mut T as Copy>
119115
note: required by a bound in `assert_copy`
120116
--> $DIR/kindck-copy.rs:5:18
121117
|

src/test/ui/specialization/default-associated-type-bound-1.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
1414
LL | default type U = str;
1515
| ^^^ the trait `Clone` is not implemented for `str`
1616
|
17+
= help: the following implementations were found:
18+
<String as Clone>
1719
note: required by a bound in `X::U`
1820
--> $DIR/default-associated-type-bound-1.rs:8:13
1921
|

src/test/ui/suggestions/into-str.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ LL | foo(String::new());
77
| required by a bound introduced by this call
88
|
99
= note: to coerce a `String` into a `&str`, use `&*` as a prefix
10+
= help: the following implementations were found:
11+
<String as From<&String>>
12+
<String as From<&mut str>>
13+
<String as From<&str>>
14+
<String as From<Box<str>>>
15+
and 2 others
1016
= note: required because of the requirements on the impl of `Into<&str>` for `String`
1117
note: required by a bound in `foo`
1218
--> $DIR/into-str.rs:1:31

src/test/ui/suggestions/issue-84973-negative.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | bar(a);
66
| |
77
| required by a bound introduced by this call
88
|
9+
= help: the following implementations were found:
10+
<&f32 as Tr>
911
note: required by a bound in `bar`
1012
--> $DIR/issue-84973-negative.rs:5:11
1113
|

src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr

-12
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@ LL | let fp = BufWriter::new(fp);
66
| |
77
| required by a bound introduced by this call
88
|
9-
= help: the following implementations were found:
10-
<&'a UnixStream as std::io::Write>
11-
<&ChildStdin as std::io::Write>
12-
<&File as std::io::Write>
13-
<&Sink as std::io::Write>
14-
and 5 others
159
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
1610
note: required by a bound in `BufWriter::<W>::new`
1711
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
@@ -25,12 +19,6 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis
2519
LL | let fp = BufWriter::new(fp);
2620
| ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
2721
|
28-
= help: the following implementations were found:
29-
<&'a UnixStream as std::io::Write>
30-
<&ChildStdin as std::io::Write>
31-
<&File as std::io::Write>
32-
<&Sink as std::io::Write>
33-
and 5 others
3422
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
3523
note: required by a bound in `BufWriter`
3624
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL

src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
44
LL | f::<dyn X<Y = str>>();
55
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
66
|
7+
= help: the following implementations were found:
8+
<String as Clone>
79
note: required by a bound in `f`
810
--> $DIR/check-trait-object-bounds-1.rs:7:9
911
|

0 commit comments

Comments
 (0)