Skip to content

Commit 60930fc

Browse files
committed
fuzzify fuzzy_match_tys
1 parent 97463da commit 60930fc

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

+37-100
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)]
@@ -1099,7 +1096,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
10991096
error: &MismatchedProjectionTypes<'tcx>,
11001097
);
11011098

1102-
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>, strip_references: StripReferences) -> bool;
1099+
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool;
11031100

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

@@ -1404,7 +1401,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
14041401
});
14051402
}
14061403

1407-
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>, strip_references: StripReferences) -> bool {
1404+
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
14081405
/// returns the fuzzy category of a given type, or None
14091406
/// if the type can be equated to any type.
14101407
fn type_category(t: Ty<'_>) -> Option<u32> {
@@ -1424,19 +1421,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
14241421
ty::Param(..) => Some(12),
14251422
ty::Opaque(..) => Some(13),
14261423
ty::Never => Some(14),
1427-
ty::Adt(adt, ..) => match adt.adt_kind() {
1428-
AdtKind::Struct => Some(15),
1429-
AdtKind::Union => Some(16),
1430-
AdtKind::Enum => Some(17),
1431-
},
1432-
ty::Generator(..) => Some(18),
1433-
ty::Foreign(..) => Some(19),
1434-
ty::GeneratorWitness(..) => Some(20),
1424+
ty::Adt(..) => Some(15),
1425+
ty::Generator(..) => Some(16),
1426+
ty::Foreign(..) => Some(17),
1427+
ty::GeneratorWitness(..) => Some(18),
14351428
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
14361429
}
14371430
}
14381431

1439-
let strip_reference = |mut t: Ty<'tcx>| -> Ty<'tcx> {
1432+
let strip_references = |mut t: Ty<'tcx>| -> Ty<'tcx> {
14401433
loop {
14411434
match t.kind() {
14421435
ty::Ref(_, inner, _) | ty::RawPtr(ty::TypeAndMut { ty: inner, .. }) => {
@@ -1447,16 +1440,14 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
14471440
}
14481441
};
14491442

1450-
let (a, b) = if strip_references == StripReferences::Yes {
1451-
(strip_reference(a), strip_reference(b))
1452-
} else {
1453-
(a, b)
1454-
};
1455-
14561443
match (type_category(a), type_category(b)) {
14571444
(Some(cat_a), Some(cat_b)) => match (a.kind(), b.kind()) {
1458-
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
1459-
_ => cat_a == cat_b,
1445+
(ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b,
1446+
_ if cat_a == cat_b => true,
1447+
(ty::Ref(..), _) | (_, ty::Ref(..)) => {
1448+
self.fuzzy_match_tys(strip_references(a), strip_references(b))
1449+
}
1450+
_ => false,
14601451
},
14611452
// infer and error can be equated to all types
14621453
_ => true,
@@ -1476,87 +1467,33 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
14761467
&self,
14771468
trait_ref: ty::PolyTraitRef<'tcx>,
14781469
) -> Vec<ImplCandidate<'tcx>> {
1479-
// We simplify params and strip references here.
1480-
//
1481-
// This both removes a lot of unhelpful suggestions, e.g.
1482-
// when searching for `&Foo: Trait` it doesn't suggestion `impl Trait for &Bar`,
1483-
// while also suggesting impls for `&Foo` when we're looking for `Foo: Trait`.
1484-
//
1485-
// The second thing isn't necessarily always a good thing, but
1486-
// any other simple setup results in a far worse output, so 🤷
1487-
let simp = fast_reject::simplify_type(
1488-
self.tcx,
1489-
trait_ref.skip_binder().self_ty(),
1490-
SimplifyParams::Yes,
1491-
StripReferences::Yes,
1492-
);
1493-
let all_impls = self.tcx.all_impls(trait_ref.def_id());
1494-
1495-
match simp {
1496-
Some(simp) => {
1497-
all_impls
1498-
.filter_map(|def_id| {
1499-
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
1500-
return None;
1501-
}
1470+
self.tcx
1471+
.all_impls(trait_ref.def_id())
1472+
.filter_map(|def_id| {
1473+
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
1474+
return None;
1475+
}
15021476

1503-
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
1477+
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
15041478

1505-
// Check for exact match.
1506-
if trait_ref.skip_binder().self_ty() == imp.self_ty() {
1507-
return Some(ImplCandidate {
1508-
trait_ref: imp,
1509-
similarity: CandidateSimilarity::Exact,
1510-
});
1511-
}
1512-
1513-
// Check for match between simplified types.
1514-
let imp_simp = fast_reject::simplify_type(
1515-
self.tcx,
1516-
imp.self_ty(),
1517-
SimplifyParams::Yes,
1518-
StripReferences::Yes,
1519-
);
1520-
if let Some(imp_simp) = imp_simp {
1521-
if simp == imp_simp {
1522-
return Some(ImplCandidate {
1523-
trait_ref: imp,
1524-
similarity: CandidateSimilarity::Simplified,
1525-
});
1526-
}
1527-
}
1479+
// Check for exact match.
1480+
if trait_ref.skip_binder().self_ty() == imp.self_ty() {
1481+
return Some(ImplCandidate {
1482+
trait_ref: imp,
1483+
similarity: CandidateSimilarity::Exact,
1484+
});
1485+
}
15281486

1529-
// Check for fuzzy match.
1530-
// Pass `StripReferences::Yes` because although we do want to
1531-
// be fuzzier than `simplify_type`, we don't want to be
1532-
// *too* fuzzy.
1533-
if self.fuzzy_match_tys(
1534-
trait_ref.skip_binder().self_ty(),
1535-
imp.self_ty(),
1536-
StripReferences::Yes,
1537-
) {
1538-
return Some(ImplCandidate {
1539-
trait_ref: imp,
1540-
similarity: CandidateSimilarity::Fuzzy,
1541-
});
1542-
}
1487+
if self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty()) {
1488+
return Some(ImplCandidate {
1489+
trait_ref: imp,
1490+
similarity: CandidateSimilarity::Fuzzy,
1491+
});
1492+
}
15431493

1544-
None
1545-
})
1546-
.collect()
1547-
}
1548-
None => all_impls
1549-
.filter_map(|def_id| {
1550-
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
1551-
return None;
1552-
}
1553-
self.tcx.impl_trait_ref(def_id).map(|trait_ref| ImplCandidate {
1554-
trait_ref,
1555-
similarity: CandidateSimilarity::Unknown,
1556-
})
1557-
})
1558-
.collect(),
1559-
}
1494+
None
1495+
})
1496+
.collect()
15601497
}
15611498

15621499
fn report_similar_impl_candidates(

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

+1-2
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

-2
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

-2
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

-3
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

-3
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

+12-8
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

+12
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

+2
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

+2
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

+2
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)