Skip to content

Commit 165142e

Browse files
committed
fuzzify fuzzy_match_tys
1 parent 002456a commit 165142e

File tree

11 files changed

+68
-120
lines changed

11 files changed

+68
-120
lines changed

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

Lines changed: 37 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ use rustc_hir::Item;
2121
use rustc_hir::Node;
2222
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
2323
use rustc_middle::ty::error::ExpectedFound;
24-
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
2524
use rustc_middle::ty::fold::TypeFolder;
2625
use rustc_middle::ty::{
27-
self, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable,
26+
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable,
2827
};
2928
use rustc_session::DiagnosticMessageId;
3029
use rustc_span::symbol::{kw, sym};
@@ -44,9 +43,7 @@ pub use rustc_infer::traits::error_reporting::*;
4443
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
4544
pub enum CandidateSimilarity {
4645
Exact,
47-
Simplified,
4846
Fuzzy,
49-
Unknown,
5047
}
5148

5249
#[derive(Debug, Clone, Copy)]
@@ -1158,7 +1155,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
11581155
error: &MismatchedProjectionTypes<'tcx>,
11591156
);
11601157

1161-
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>, strip_references: StripReferences) -> bool;
1158+
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool;
11621159

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

@@ -1461,7 +1458,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
14611458
});
14621459
}
14631460

1464-
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>, strip_references: StripReferences) -> bool {
1461+
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
14651462
/// returns the fuzzy category of a given type, or None
14661463
/// if the type can be equated to any type.
14671464
fn type_category(t: Ty<'_>) -> Option<u32> {
@@ -1481,19 +1478,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
14811478
ty::Param(..) => Some(12),
14821479
ty::Opaque(..) => Some(13),
14831480
ty::Never => Some(14),
1484-
ty::Adt(adt, ..) => match adt.adt_kind() {
1485-
AdtKind::Struct => Some(15),
1486-
AdtKind::Union => Some(16),
1487-
AdtKind::Enum => Some(17),
1488-
},
1489-
ty::Generator(..) => Some(18),
1490-
ty::Foreign(..) => Some(19),
1491-
ty::GeneratorWitness(..) => Some(20),
1481+
ty::Adt(..) => Some(15),
1482+
ty::Generator(..) => Some(16),
1483+
ty::Foreign(..) => Some(17),
1484+
ty::GeneratorWitness(..) => Some(18),
14921485
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
14931486
}
14941487
}
14951488

1496-
let strip_reference = |mut t: Ty<'tcx>| -> Ty<'tcx> {
1489+
let strip_references = |mut t: Ty<'tcx>| -> Ty<'tcx> {
14971490
loop {
14981491
match t.kind() {
14991492
ty::Ref(_, inner, _) | ty::RawPtr(ty::TypeAndMut { ty: inner, .. }) => {
@@ -1504,16 +1497,14 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
15041497
}
15051498
};
15061499

1507-
let (a, b) = if strip_references == StripReferences::Yes {
1508-
(strip_reference(a), strip_reference(b))
1509-
} else {
1510-
(a, b)
1511-
};
1512-
15131500
match (type_category(a), type_category(b)) {
15141501
(Some(cat_a), Some(cat_b)) => match (a.kind(), b.kind()) {
1515-
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
1516-
_ => cat_a == cat_b,
1502+
(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))
1506+
}
1507+
_ => false,
15171508
},
15181509
// infer and error can be equated to all types
15191510
_ => true,
@@ -1533,87 +1524,33 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
15331524
&self,
15341525
trait_ref: ty::PolyTraitRef<'tcx>,
15351526
) -> Vec<ImplCandidate<'tcx>> {
1536-
// We simplify params and strip references here.
1537-
//
1538-
// This both removes a lot of unhelpful suggestions, e.g.
1539-
// when searching for `&Foo: Trait` it doesn't suggestion `impl Trait for &Bar`,
1540-
// while also suggesting impls for `&Foo` when we're looking for `Foo: Trait`.
1541-
//
1542-
// The second thing isn't necessarily always a good thing, but
1543-
// any other simple setup results in a far worse output, so 🤷
1544-
let simp = fast_reject::simplify_type(
1545-
self.tcx,
1546-
trait_ref.skip_binder().self_ty(),
1547-
SimplifyParams::Yes,
1548-
StripReferences::Yes,
1549-
);
1550-
let all_impls = self.tcx.all_impls(trait_ref.def_id());
1551-
1552-
match simp {
1553-
Some(simp) => {
1554-
all_impls
1555-
.filter_map(|def_id| {
1556-
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
1557-
return None;
1558-
}
1527+
self.tcx
1528+
.all_impls(trait_ref.def_id())
1529+
.filter_map(|def_id| {
1530+
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
1531+
return None;
1532+
}
15591533

1560-
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
1534+
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
15611535

1562-
// Check for exact match.
1563-
if trait_ref.skip_binder().self_ty() == imp.self_ty() {
1564-
return Some(ImplCandidate {
1565-
trait_ref: imp,
1566-
similarity: CandidateSimilarity::Exact,
1567-
});
1568-
}
1569-
1570-
// Check for match between simplified types.
1571-
let imp_simp = fast_reject::simplify_type(
1572-
self.tcx,
1573-
imp.self_ty(),
1574-
SimplifyParams::Yes,
1575-
StripReferences::Yes,
1576-
);
1577-
if let Some(imp_simp) = imp_simp {
1578-
if simp == imp_simp {
1579-
return Some(ImplCandidate {
1580-
trait_ref: imp,
1581-
similarity: CandidateSimilarity::Simplified,
1582-
});
1583-
}
1584-
}
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+
}
15851543

1586-
// Check for fuzzy match.
1587-
// Pass `StripReferences::Yes` because although we do want to
1588-
// be fuzzier than `simplify_type`, we don't want to be
1589-
// *too* fuzzy.
1590-
if self.fuzzy_match_tys(
1591-
trait_ref.skip_binder().self_ty(),
1592-
imp.self_ty(),
1593-
StripReferences::Yes,
1594-
) {
1595-
return Some(ImplCandidate {
1596-
trait_ref: imp,
1597-
similarity: CandidateSimilarity::Fuzzy,
1598-
});
1599-
}
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+
}
16001550

1601-
None
1602-
})
1603-
.collect()
1604-
}
1605-
None => all_impls
1606-
.filter_map(|def_id| {
1607-
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
1608-
return None;
1609-
}
1610-
self.tcx.impl_trait_ref(def_id).map(|trait_ref| ImplCandidate {
1611-
trait_ref,
1612-
similarity: CandidateSimilarity::Unknown,
1613-
})
1614-
})
1615-
.collect(),
1616-
}
1551+
None
1552+
})
1553+
.collect()
16171554
}
16181555

16191556
fn report_similar_impl_candidates(

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use super::{
44
use crate::infer::InferCtxt;
55
use rustc_hir as hir;
66
use rustc_hir::def_id::DefId;
7-
use rustc_middle::ty::fast_reject::StripReferences;
87
use rustc_middle::ty::subst::Subst;
98
use rustc_middle::ty::{self, GenericParamDefKind};
109
use rustc_span::symbol::sym;
@@ -57,7 +56,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
5756
trait_ref.substs.types().skip(1),
5857
impl_trait_ref.substs.types().skip(1),
5958
)
60-
.all(|(u, v)| self.fuzzy_match_tys(u, v, StripReferences::No))
59+
.all(|(u, v)| self.fuzzy_match_tys(u, v))
6160
{
6261
fuzzy_match_impls.push(def_id);
6362
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ error[E0277]: the trait bound `for<'b> <T as X<'b>>::U: Clone` is not satisfied
44
LL | fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
55
| ^^^^^ the trait `for<'b> Clone` is not implemented for `<T as X<'b>>::U`
66
|
7-
= help: the following implementations were found:
8-
<&T as Clone>
97
note: required by a bound in `X`
108
--> $DIR/hr-associated-type-bound-object.rs:3:33
119
|

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ 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>
97
note: required because of the requirements on the impl of `Add<{integer}>` for `Bob`
108
--> $DIR/issue-22645.rs:8:19
119
|

src/test/ui/chalkify/type_inference.stderr

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ 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>
129
note: required by a bound in `only_bar`
1310
--> $DIR/type_inference.rs:12:16
1411
|

src/test/ui/chalkify/type_wf.stderr

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ 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-
<Option<T> as Foo>
9-
<i32 as Foo>
107
note: required by a bound in `S`
118
--> $DIR/type_wf.rs:6:13
129
|

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

Lines changed: 12 additions & 8 deletions
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-
<isize as Copy>
8+
<&T as Copy>
9+
<*const T as Copy>
10+
<*mut T as Copy>
911
<i128 as Copy>
10-
<i16 as Copy>
11-
<i32 as Copy>
12-
and 8 others
12+
and 11 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-
<isize as Copy>
26+
<&T as Copy>
27+
<*const T as Copy>
28+
<*mut T as Copy>
2729
<i128 as Copy>
28-
<i16 as Copy>
29-
<i32 as Copy>
30-
and 8 others
30+
and 11 others
3131
note: required by a bound in `assert_copy`
3232
--> $DIR/kindck-copy.rs:5:18
3333
|
@@ -112,6 +112,10 @@ 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>
115119
note: required by a bound in `assert_copy`
116120
--> $DIR/kindck-copy.rs:5:18
117121
|

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ 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
915
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
1016
note: required by a bound in `BufWriter::<W>::new`
1117
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
@@ -19,6 +25,12 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis
1925
LL | let fp = BufWriter::new(fp);
2026
| ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
2127
|
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
2234
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
2335
note: required by a bound in `BufWriter`
2436
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL

src/test/ui/traits/suggest-deferences/issue-62530.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LL | takes_type_parameter(&string); // Error
88
| | help: consider adding dereference here: `&*string`
99
| required by a bound introduced by this call
1010
|
11+
= help: the following implementations were found:
12+
<&str as SomeTrait>
1113
note: required by a bound in `takes_type_parameter`
1214
--> $DIR/issue-62530.rs:4:44
1315
|

src/test/ui/traits/suggest-deferences/multiple-0.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LL | foo(&baz);
88
| | help: consider adding dereference here: `&***baz`
99
| required by a bound introduced by this call
1010
|
11+
= help: the following implementations were found:
12+
<&LDM as Happy>
1113
note: required by a bound in `foo`
1214
--> $DIR/multiple-0.rs:30:26
1315
|

src/test/ui/traits/suggest-deferences/multiple-1.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | foo(&mut baz);
66
| |
77
| required by a bound introduced by this call
88
|
9+
= help: the following implementations were found:
10+
<&mut LDM as Happy>
911
note: required by a bound in `foo`
1012
--> $DIR/multiple-1.rs:45:26
1113
|

0 commit comments

Comments
 (0)