]> git.lizzy.rs Git - rust.git/commitdiff
spell out nested self type
authorcsmoe <csmoe@msn.com>
Fri, 12 Feb 2021 08:50:45 +0000 (16:50 +0800)
committercsmoe <csmoe@msn.com>
Fri, 12 Feb 2021 08:50:45 +0000 (16:50 +0800)
compiler/rustc_typeck/src/check/check.rs
src/test/ui/async-await/issues/issue-78600.stderr [new file with mode: 0644]

index 012ccb1af46b16fef82dd19643d3dda41715739c..990d19914381dd6c345e7ddc05fe935d2584c3fb 100644 (file)
@@ -7,6 +7,7 @@
 use rustc_errors::{Applicability, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ItemKind, Node};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -557,6 +558,8 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         );
 
         if let Some(ty) = prohibit_opaque.break_value() {
+            let mut visitor = SelfTySpanVisitor { tcx, selfty_spans: vec![] };
+            visitor.visit_item(&item);
             let is_async = match item.kind {
                 ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
                     matches!(origin, hir::OpaqueTyOrigin::AsyncFn)
@@ -573,15 +576,13 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 if is_async { "async fn" } else { "impl Trait" },
             );
 
-            if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
-                if snippet == "Self" {
-                    err.span_suggestion(
-                        span,
-                        "consider spelling out the type instead",
-                        format!("{:?}", ty),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
+            for span in visitor.selfty_spans {
+                err.span_suggestion(
+                    span,
+                    "consider spelling out the type instead",
+                    format!("{:?}", ty),
+                    Applicability::MaybeIncorrect,
+                );
             }
             err.emit();
         }
@@ -1590,3 +1591,31 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
     err.emit();
 }
+
+struct SelfTySpanVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    selfty_spans: Vec<Span>,
+}
+
+impl Visitor<'tcx> for SelfTySpanVisitor<'tcx> {
+    type Map = rustc_middle::hir::map::Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
+        hir::intravisit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
+    }
+
+    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
+        match arg.kind {
+            hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
+                [segment]
+                    if segment.res.map(|res| matches!(res, Res::SelfTy(_, _))).unwrap_or(false) =>
+                {
+                    self.selfty_spans.push(path.span);
+                }
+                _ => {}
+            },
+            _ => {}
+        }
+        hir::intravisit::walk_ty(self, arg);
+    }
+}
diff --git a/src/test/ui/async-await/issues/issue-78600.stderr b/src/test/ui/async-await/issues/issue-78600.stderr
new file mode 100644 (file)
index 0000000..8e3dc04
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0760]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+  --> $DIR/issue-78600.rs:6:33
+   |
+LL |     async fn new(i: &'a i32) -> Result<Self, ()> {
+   |                                 ^^^^^^^----^^^^^
+   |                                        |
+   |                                        help: consider spelling out the type instead: `std::result::Result<S<'a>, ()>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0760`.