pub use rustc_infer::traits::error_reporting::*;
// When outputting impl candidates, prefer showing those that are more similar.
+//
+// We also compare candidates after skipping lifetimes, which has a lower
+// priority than exact matches.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum CandidateSimilarity {
- Exact,
- Fuzzy,
+ Exact { ignoring_lifetimes: bool },
+ Fuzzy { ignoring_lifetimes: bool },
}
#[derive(Debug, Clone, Copy)]
error: &MismatchedProjectionTypes<'tcx>,
);
- fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool;
+ fn fuzzy_match_tys(
+ &self,
+ a: Ty<'tcx>,
+ b: Ty<'tcx>,
+ ignoring_lifetimes: bool,
+ ) -> Option<CandidateSimilarity>;
fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
});
}
- fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+ fn fuzzy_match_tys(
+ &self,
+ mut a: Ty<'tcx>,
+ mut b: Ty<'tcx>,
+ ignoring_lifetimes: bool,
+ ) -> Option<CandidateSimilarity> {
/// returns the fuzzy category of a given type, or None
/// if the type can be equated to any type.
- fn type_category(t: Ty<'_>) -> Option<u32> {
+ fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
match t.kind() {
ty::Bool => Some(0),
ty::Char => Some(1),
ty::Str => Some(2),
- ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
- ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
+ ty::Adt(def, _) if tcx.is_diagnostic_item(sym::String, def.did) => Some(2),
+ ty::Int(..)
+ | ty::Uint(..)
+ | ty::Float(..)
+ | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) => Some(4),
ty::Ref(..) | ty::RawPtr(..) => Some(5),
ty::Array(..) | ty::Slice(..) => Some(6),
ty::FnDef(..) | ty::FnPtr(..) => Some(7),
ty::Dynamic(..) => Some(8),
ty::Closure(..) => Some(9),
ty::Tuple(..) => Some(10),
- ty::Projection(..) => Some(11),
- ty::Param(..) => Some(12),
+ ty::Param(..) => Some(11),
+ ty::Projection(..) => Some(12),
ty::Opaque(..) => Some(13),
ty::Never => Some(14),
ty::Adt(..) => Some(15),
}
};
- match (type_category(a), type_category(b)) {
- (Some(cat_a), Some(cat_b)) => match (a.kind(), b.kind()) {
+ if !ignoring_lifetimes {
+ a = strip_references(a);
+ b = strip_references(b);
+ }
+
+ let cat_a = type_category(self.tcx, a)?;
+ let cat_b = type_category(self.tcx, b)?;
+ if a == b {
+ Some(CandidateSimilarity::Exact { ignoring_lifetimes })
+ } else if cat_a == cat_b {
+ match (a.kind(), b.kind()) {
(ty::Adt(def_a, _), ty::Adt(def_b, _)) => def_a == def_b,
- _ if cat_a == cat_b => true,
- (ty::Ref(..), _) | (_, ty::Ref(..)) => {
- self.fuzzy_match_tys(strip_references(a), strip_references(b))
+ // Matching on references results in a lot of unhelpful
+ // suggestions, so let's just not do that for now.
+ //
+ // We still upgrade successful matches to `ignoring_lifetimes: true`
+ // to prioritize that impl.
+ (ty::Ref(..) | ty::RawPtr(..), ty::Ref(..) | ty::RawPtr(..)) => {
+ self.fuzzy_match_tys(a, b, true).is_some()
}
- _ => false,
- },
- // infer and error can be equated to all types
- _ => true,
+ _ => true,
+ }
+ .then_some(CandidateSimilarity::Fuzzy { ignoring_lifetimes })
+ } else if ignoring_lifetimes {
+ None
+ } else {
+ self.fuzzy_match_tys(a, b, true)
}
}
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
- // Check for exact match.
- if trait_ref.skip_binder().self_ty() == imp.self_ty() {
- return Some(ImplCandidate {
- trait_ref: imp,
- similarity: CandidateSimilarity::Exact,
- });
- }
-
- if self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty()) {
- return Some(ImplCandidate {
- trait_ref: imp,
- similarity: CandidateSimilarity::Fuzzy,
- });
- }
-
- None
+ self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty(), false)
+ .map(|similarity| ImplCandidate { trait_ref: imp, similarity })
})
.collect()
}
trait_ref.substs.types().skip(1),
impl_trait_ref.substs.types().skip(1),
)
- .all(|(u, v)| self.fuzzy_match_tys(u, v))
+ .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
{
fuzzy_match_impls.push(def_id);
}
LL | type U = str;
| ^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-1.rs:3:33
|
LL | type V = str;
| ^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `Y`
--> $DIR/hr-associated-type-bound-param-1.rs:4:36
|
LL | T: Z<'a, u16>,
| ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `Z`
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
LL | T: Z<'a, u16>,
| ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `Z`
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
LL | type W = str;
| ^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `Z`
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
LL | type U = str;
| ^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-param-3.rs:4:33
|
LL | type U = str;
| ^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-param-4.rs:4:36
|
LL | type U = str;
| ^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
|
LL | type U = str;
| ^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
|
LL | b + 3
| ^ the trait `Scalar` is not implemented for `{integer}`
|
+ = help: the following implementations were found:
+ <f64 as Scalar>
note: required because of the requirements on the impl of `Add<{integer}>` for `Bob`
--> $DIR/issue-22645.rs:8:19
|
LL | gimme::<f32>();
| ^^^ the trait `Foo` is not implemented for `f32`
|
+ = help: the following implementations were found:
+ <i32 as Foo>
+ <u32 as Foo>
note: required by a bound in `gimme`
--> $DIR/chalk_initial_program.rs:9:13
|
LL | impl Baz<f32> for f32 { }
| ^^^^^^^^ the trait `Foo` is not implemented for `f32`
|
+ = help: the following implementations were found:
+ <i32 as Foo>
note: required by a bound in `Baz`
--> $DIR/impl_wf.rs:18:31
|
LL | type Item = f32;
| ^^^ the trait `Foo` is not implemented for `f32`
|
+ = help: the following implementations were found:
+ <i32 as Foo>
note: required by a bound in `Bar::Item`
--> $DIR/impl_wf_2.rs:8:16
|
| |
| required by a bound introduced by this call
|
+ = help: the following implementations were found:
+ <i32 as Bar>
+ <u32 as Bar>
note: required by a bound in `only_bar`
--> $DIR/type_inference.rs:12:16
|
LL | let s = S {
| ^ the trait `Foo` is not implemented for `{float}`
|
+ = help: the following implementations were found:
+ <i32 as Foo>
note: required by a bound in `S`
--> $DIR/type_wf.rs:6:13
|
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize`
|
= help: the following implementations were found:
- <&T as Copy>
- <*const T as Copy>
- <*mut T as Copy>
+ <isize as Copy>
+ <f32 as Copy>
+ <f64 as Copy>
<i128 as Copy>
- and 11 others
+ and 10 others
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18
|
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize`
|
= help: the following implementations were found:
- <&T as Copy>
- <*const T as Copy>
- <*mut T as Copy>
+ <isize as Copy>
+ <f32 as Copy>
+ <f64 as Copy>
<i128 as Copy>
- and 11 others
+ and 10 others
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18
|
LL | assert_copy::<&'a mut (dyn Dummy + Send)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut (dyn Dummy + Send + 'a)`
|
- = help: the following implementations were found:
- <&T as Copy>
- <*const T as Copy>
- <*mut T as Copy>
note: required by a bound in `assert_copy`
--> $DIR/kindck-copy.rs:5:18
|
LL | default type U = str;
| ^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `X::U`
--> $DIR/default-associated-type-bound-1.rs:8:13
|
| required by a bound introduced by this call
|
= note: to coerce a `String` into a `&str`, use `&*` as a prefix
+ = help: the following implementations were found:
+ <String as From<&String>>
+ <String as From<&mut str>>
+ <String as From<&str>>
+ <String as From<Box<str>>>
+ and 2 others
= note: required because of the requirements on the impl of `Into<&str>` for `String`
note: required by a bound in `foo`
--> $DIR/into-str.rs:1:31
| |
| required by a bound introduced by this call
|
+ = help: the following implementations were found:
+ <&f32 as Tr>
note: required by a bound in `bar`
--> $DIR/issue-84973-negative.rs:5:11
|
| |
| required by a bound introduced by this call
|
- = help: the following implementations were found:
- <&'a UnixStream as std::io::Write>
- <&ChildStdin as std::io::Write>
- <&File as std::io::Write>
- <&Sink as std::io::Write>
- and 5 others
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
note: required by a bound in `BufWriter::<W>::new`
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
LL | let fp = BufWriter::new(fp);
| ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
|
- = help: the following implementations were found:
- <&'a UnixStream as std::io::Write>
- <&ChildStdin as std::io::Write>
- <&File as std::io::Write>
- <&Sink as std::io::Write>
- and 5 others
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
note: required by a bound in `BufWriter`
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
LL | f::<dyn X<Y = str>>();
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `f`
--> $DIR/check-trait-object-bounds-1.rs:7:9
|
LL | f::<dyn X<Y = str>>();
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
|
+ = help: the following implementations were found:
+ <String as Clone>
note: required by a bound in `f`
--> $DIR/check-trait-object-bounds-4.rs:10:9
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | opts.get(<String as AsRef<str>>::as_ref(opt));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ and 4 other candidates
error[E0283]: type annotations needed
--> $DIR/issue-77982.rs:13:44
| | help: consider adding dereference here: `&***baz`
| required by a bound introduced by this call
|
- = help: the following implementations were found:
- <&LDM as Happy>
note: required by a bound in `foo`
--> $DIR/multiple-0.rs:30:26
|
| |
| required by a bound introduced by this call
|
- = help: the following implementations were found:
- <&mut LDM as Happy>
note: required by a bound in `foo`
--> $DIR/multiple-1.rs:45:26
|
= help: the following implementations were found:
<u8 as From<NonZeroU8>>
<u8 as From<bool>>
- <i128 as From<NonZeroI128>>
- <i128 as From<bool>>
- and 60 others
+ <f32 as From<i16>>
+ <f32 as From<i8>>
+ and 71 others
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`