about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-08-10 09:28:22 -0700
committerGitHub <noreply@github.com>2022-08-10 09:28:22 -0700
commit5459edf8bd0f4d2302719d5372b7899393b445fe (patch)
tree4026f7aac5dcf533d2943373a3f5dcdfdd2b988e
parenta6116b95640451c14858a487b3cfcf31f3e67b77 (diff)
parent54cf66f241dd2728e0918b44efae93a3fd33ad78 (diff)
downloadrust-5459edf8bd0f4d2302719d5372b7899393b445fe.tar.gz
rust-5459edf8bd0f4d2302719d5372b7899393b445fe.zip
Rollup merge of #100349 - TaKO8Ki:remove-type-string-comparison, r=lcnr
Refactor: remove a type string comparison
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs16
-rw-r--r--src/test/ui/suggestions/as-ref.rs7
-rw-r--r--src/test/ui/suggestions/as-ref.stderr62
3 files changed, 77 insertions, 8 deletions
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 0595b9a73be..bac0be44aa9 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -598,13 +598,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         let self_ty = self.typeck_results.borrow().expr_ty(&method_expr[0]);
-        let self_ty = format!("{:?}", self_ty);
         let name = method_path.ident.name;
-        let is_as_ref_able = (self_ty.starts_with("&std::option::Option")
-            || self_ty.starts_with("&std::result::Result")
-            || self_ty.starts_with("std::option::Option")
-            || self_ty.starts_with("std::result::Result"))
-            && (name == sym::map || name == sym::and_then);
+        let is_as_ref_able = match self_ty.peel_refs().kind() {
+            ty::Adt(def, _) => {
+                (self.tcx.is_diagnostic_item(sym::Option, def.did())
+                    || self.tcx.is_diagnostic_item(sym::Result, def.did()))
+                    && (name == sym::map || name == sym::and_then)
+            }
+            _ => false,
+        };
         match (is_as_ref_able, self.sess().source_map().span_to_snippet(method_path.ident.span)) {
             (true, Ok(src)) => {
                 let suggestion = format!("as_ref().{}", src);
@@ -792,7 +794,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             _ if is_range_literal(expr) => true,
                             _ => false,
                         };
-                        let sugg_expr = if needs_parens { format!("({src})") } else { src };
 
                         if let Some(sugg) = self.can_use_as_ref(expr) {
                             return Some((
@@ -820,6 +821,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                         }
 
+                        let sugg_expr = if needs_parens { format!("({src})") } else { src };
                         return Some(match mutability {
                             hir::Mutability::Mut => (
                                 sp,
diff --git a/src/test/ui/suggestions/as-ref.rs b/src/test/ui/suggestions/as-ref.rs
index 46d9461538c..a0535344185 100644
--- a/src/test/ui/suggestions/as-ref.rs
+++ b/src/test/ui/suggestions/as-ref.rs
@@ -17,4 +17,11 @@ fn main() {
     // note: do not suggest because of `E: usize`
     let x: &Result<usize, usize> = &Ok(3);
     let y: Result<&usize, usize> = x; //~ ERROR mismatched types [E0308]
+
+    let multiple_ref_opt = &&Some(Foo);
+    multiple_ref_opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308]
+    multiple_ref_opt.and_then(|arg| Some(takes_ref(arg))); //~ ERROR mismatched types [E0308]
+    let multiple_ref_result = &&Ok(Foo);
+    multiple_ref_result.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308]
+    multiple_ref_result.and_then(|arg| Ok(takes_ref(arg))); //~ ERROR mismatched types [E0308]
 }
diff --git a/src/test/ui/suggestions/as-ref.stderr b/src/test/ui/suggestions/as-ref.stderr
index 1efd1b317b7..deafa9f48d4 100644
--- a/src/test/ui/suggestions/as-ref.stderr
+++ b/src/test/ui/suggestions/as-ref.stderr
@@ -97,6 +97,66 @@ LL |     let y: Result<&usize, usize> = x;
    = note:   expected enum `Result<&usize, usize>`
            found reference `&Result<usize, usize>`
 
-error: aborting due to 7 previous errors
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:22:42
+   |
+LL |     multiple_ref_opt.map(|arg| takes_ref(arg));
+   |                      ---       --------- ^^^ expected `&Foo`, found struct `Foo`
+   |                      |         |
+   |                      |         arguments to this function are incorrect
+   |                      help: consider using `as_ref` instead: `as_ref().map`
+   |
+note: function defined here
+  --> $DIR/as-ref.rs:3:4
+   |
+LL | fn takes_ref(_: &Foo) {}
+   |    ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:23:52
+   |
+LL |     multiple_ref_opt.and_then(|arg| Some(takes_ref(arg)));
+   |                      --------            --------- ^^^ expected `&Foo`, found struct `Foo`
+   |                      |                   |
+   |                      |                   arguments to this function are incorrect
+   |                      help: consider using `as_ref` instead: `as_ref().and_then`
+   |
+note: function defined here
+  --> $DIR/as-ref.rs:3:4
+   |
+LL | fn takes_ref(_: &Foo) {}
+   |    ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:25:45
+   |
+LL |     multiple_ref_result.map(|arg| takes_ref(arg));
+   |                         ---       --------- ^^^ expected `&Foo`, found struct `Foo`
+   |                         |         |
+   |                         |         arguments to this function are incorrect
+   |                         help: consider using `as_ref` instead: `as_ref().map`
+   |
+note: function defined here
+  --> $DIR/as-ref.rs:3:4
+   |
+LL | fn takes_ref(_: &Foo) {}
+   |    ^^^^^^^^^ -------
+
+error[E0308]: mismatched types
+  --> $DIR/as-ref.rs:26:53
+   |
+LL |     multiple_ref_result.and_then(|arg| Ok(takes_ref(arg)));
+   |                         --------          --------- ^^^ expected `&Foo`, found struct `Foo`
+   |                         |                 |
+   |                         |                 arguments to this function are incorrect
+   |                         help: consider using `as_ref` instead: `as_ref().and_then`
+   |
+note: function defined here
+  --> $DIR/as-ref.rs:3:4
+   |
+LL | fn takes_ref(_: &Foo) {}
+   |    ^^^^^^^^^ -------
+
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0308`.