]> git.lizzy.rs Git - rust.git/commitdiff
further update `fuzzy_match_tys`
authorlcnr <rust@lcnr.de>
Fri, 11 Feb 2022 15:12:22 +0000 (16:12 +0100)
committerlcnr <rust@lcnr.de>
Mon, 14 Feb 2022 06:37:15 +0000 (07:37 +0100)
25 files changed:
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
src/test/ui/associated-types/hr-associated-type-bound-1.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr
src/test/ui/block-result/issue-22645.stderr
src/test/ui/chalkify/chalk_initial_program.stderr
src/test/ui/chalkify/impl_wf.stderr
src/test/ui/chalkify/impl_wf_2.stderr
src/test/ui/chalkify/type_inference.stderr
src/test/ui/chalkify/type_wf.stderr
src/test/ui/kindck/kindck-copy.stderr
src/test/ui/specialization/default-associated-type-bound-1.stderr
src/test/ui/suggestions/into-str.stderr
src/test/ui/suggestions/issue-84973-negative.stderr
src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr
src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr
src/test/ui/traits/issue-77982.stderr
src/test/ui/traits/suggest-deferences/multiple-0.stderr
src/test/ui/traits/suggest-deferences/multiple-1.stderr
src/test/ui/try-trait/bad-interconversion.stderr

index ac7140ca2b67d32b8ebf60353542b7d44ec6b36d..cd0a62af72f322f9426ffd483730a9ee1f3118cb 100644 (file)
 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)]
@@ -1155,7 +1158,12 @@ fn report_projection_error(
         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>;
 
@@ -1458,24 +1466,32 @@ fn report_projection_error(
         });
     }
 
-    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),
@@ -1497,17 +1513,33 @@ fn type_category(t: Ty<'_>) -> Option<u32> {
             }
         };
 
-        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)
         }
     }
 
@@ -1533,22 +1565,8 @@ fn find_similar_impl_candidates(
 
                 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()
     }
index 4e7a34d5951113f7474180891ad2f2f58c9bfde0..4b6ffa8869dbaa1214d2b6607cce702afc161570 100644 (file)
@@ -56,7 +56,7 @@ fn impl_similar_to(
                     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);
                 }
index 4eed5c9a0083c18f6098d51d362a294066d44709..ec28ca240be2b5b9a4bc30e3790d88450323e0fb 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index 99f95c200511ac4c017f5e7ef904ae53309f4d1d..e48ef8d17d1dee70af4f5adb426020fc61c97cac 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index 354caef1e41d8e4594e5d1a11fc63813c9f1a4cb..2fb3af38c0d9b391dcef3b3aac6bc005b4a732e9 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
@@ -19,6 +21,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
@@ -34,6 +38,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index 9935445c306586c88a33a6ae53f6ac923839f0c4..775f45ca82965020718cc52863323b1fe57793c8 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index c26324ee6255455da3fe2d642c09ab79e26f5492..4e9b64ba832adb19be7e4ce2c532751b2a56fed7 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index 4c04d12a71470d25f0f9b33a88ae6c4bb7c95b02..d00abf30d3b053d0fd487fb53e6d58b90a048661 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
@@ -19,6 +21,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index b869a70039c4fb7aebc451767bcbeda66ee409a5..397bdac60513e7f2d1a77e59bc5e9fa0f9c4bf1c 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
 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
    |
index f8b792ae5363ca2400ad3fa68cf0d170c1f5a4ec..7b0b3f85b39158d27ffcf442e33772ab3eec2db2 100644 (file)
@@ -4,6 +4,9 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
 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
    |
index 95e320726aab0a6bd2ec27a50c5ee878a1b0a9df..2bc9f077f0285dc817d2b83e59684db0b51cb2c4 100644 (file)
@@ -17,6 +17,8 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
 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
    |
index 80ec03d6221e8e88b41b9993f75565e0433693f2..30cec80b036c629ea13bc92b043e718949de0f6a 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `f32: Foo` is not satisfied
 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
    |
index a05d8d6aa37da6e1962e79865334fddfb075b0ba..14d43c1474c575b92a3ed7ffd9655e6cca54a5a9 100644 (file)
@@ -6,6 +6,9 @@ LL |     only_bar(x);
    |     |
    |     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
    |
index d029eb2400b8a2f81e7db8813052fa806e6bbccd..6abd8b28760d8261b2c21965a56bf57cb7eadc7f 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `{float}: Foo` is not satisfied
 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
    |
index 607db0d1129298586eb8f360c21f4ed5eb96aa1f..e147366a22410bf6e903f0639f4eae3468bdd3d4 100644 (file)
@@ -5,11 +5,11 @@ LL |     assert_copy::<&'static mut isize>();
    |                   ^^^^^^^^^^^^^^^^^^ 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
    |
@@ -23,11 +23,11 @@ LL |     assert_copy::<&'a mut isize>();
    |                   ^^^^^^^^^^^^^ 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
    |
@@ -112,10 +112,6 @@ error[E0277]: the trait bound `&'a mut (dyn Dummy + Send + 'a): Copy` is not sat
 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
    |
index 6680a29f94245eb27f5c1aa74230dd4f140c06b2..f88acfb2e793e67e5a2df449b55c317ad77e2017 100644 (file)
@@ -14,6 +14,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index 0d9ecc32e08cdd6c75b47cf425955da9ffed7ddc..470c0bfcf73e515e7f0c83bbd7e25528e5a08eeb 100644 (file)
@@ -7,6 +7,12 @@ LL |     foo(String::new());
    |     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
index 1f33374eb29dbf9c050c88e5fa4babd9c4a61a92..bacab64e2642c0e9ed554295cd25316bd9486a37 100644 (file)
@@ -6,6 +6,8 @@ LL |     bar(a);
    |     |
    |     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
    |
index 6aaeafceb42730db74ef069b77d35e1492f1555c..d121932c842e35324a8a8f1060e4713f8dd8ab0c 100644 (file)
@@ -6,12 +6,6 @@ LL |     let fp = BufWriter::new(fp);
    |              |
    |              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
@@ -25,12 +19,6 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis
 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
index 6333b4eb08cd530643b677e926567b01b31e009a..907a1bd75a06448c81feff245bb30c5f5a2085bf 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index 9afae9a9638349ef123624e03352474c864ba1f5..b27f8d791a50f29d9ca246269e80cdf132b74d99 100644 (file)
@@ -4,6 +4,8 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
 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
    |
index 3c4a5d95c137ec6e9cdd752ca26ecef24f171c64..413225d45a62ce6d6cd8d24a7e97c0c3296afb0e 100644 (file)
@@ -44,6 +44,7 @@ LL |     opts.get(<String as AsRef<[u8]>>::as_ref(opt));
    |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 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
index c629b06ba260266ef9d9dd0257764bb50bee1667..bf9f85f1b4595ec4d2c541145af0b83ffd637068 100644 (file)
@@ -8,8 +8,6 @@ LL |     foo(&baz);
    |     |   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
    |
index b18c297ed995435aa065dc10c0252eaa3c7b9bb7..040fbb3e3e699813fae132946c7076eddfcd92d2 100644 (file)
@@ -6,8 +6,6 @@ LL |     foo(&mut baz);
    |     |
    |     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
    |
index 6fc5f94f5f11802dfadf6db3b6b16afff7ecb4c4..171051156b7f242e93a42406afd8761d3e2a5a0e 100644 (file)
@@ -10,9 +10,9 @@ LL |     Ok(Err(123_i32)?)
    = 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`