From 05704ec79aa729044aef70449d6661b658f0e37e Mon Sep 17 00:00:00 2001 From: csmoe Date: Fri, 12 Feb 2021 16:50:25 +0800 Subject: [PATCH 1/3] add testcase for issue 78600 --- src/test/ui/async-await/issues/issue-78600.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/async-await/issues/issue-78600.rs diff --git a/src/test/ui/async-await/issues/issue-78600.rs b/src/test/ui/async-await/issues/issue-78600.rs new file mode 100644 index 0000000000000..8aaeaecf3e1da --- /dev/null +++ b/src/test/ui/async-await/issues/issue-78600.rs @@ -0,0 +1,12 @@ +// edition:2018 + +struct S<'a>(&'a i32); + +impl<'a> S<'a> { + async fn new(i: &'a i32) -> Result { + //~^ ERROR: `async fn` + Ok(S(&22)) + } +} + +fn main() {} From ed40b95925ddbe3596eebbca64f776f0f7c57d95 Mon Sep 17 00:00:00 2001 From: csmoe Date: Fri, 12 Feb 2021 16:50:45 +0800 Subject: [PATCH 2/3] spell out nested self type --- compiler/rustc_typeck/src/check/check.rs | 47 +++++++++++++++---- .../ui/async-await/issues/issue-78600.stderr | 11 +++++ 2 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/async-await/issues/issue-78600.stderr diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 012ccb1af46b1..990d19914381d 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -7,6 +7,7 @@ use rustc_attr as attr; 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 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( ); 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 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( 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 opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { } err.emit(); } + +struct SelfTySpanVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + selfty_spans: Vec, +} + +impl Visitor<'tcx> for SelfTySpanVisitor<'tcx> { + type Map = rustc_middle::hir::map::Map<'tcx>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + 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 index 0000000000000..8e3dc0406fafc --- /dev/null +++ b/src/test/ui/async-await/issues/issue-78600.stderr @@ -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 { + | ^^^^^^^----^^^^^ + | | + | help: consider spelling out the type instead: `std::result::Result, ()>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0760`. From 5385a3d6a779b2e85d47c3fc317796ea3755c11a Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 13 Feb 2021 14:45:53 +0800 Subject: [PATCH 3/3] spell the real selftype --- compiler/rustc_typeck/src/check/check.rs | 67 +++++++++---------- .../ui/async-await/issues/issue-78600.stderr | 2 +- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 990d19914381d..21613bbc6f2e4 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -9,7 +9,7 @@ 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_hir::{def::Res, ItemKind, Node, PathSegment}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; @@ -516,10 +516,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( } } - #[derive(Debug)] struct ProhibitOpaqueVisitor<'tcx> { opaque_identity_ty: Ty<'tcx>, generics: &'tcx ty::Generics, + tcx: TyCtxt<'tcx>, + selftys: Vec<(Span, Option)>, } impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { @@ -536,6 +537,29 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( } } + impl Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { + type Map = rustc_middle::hir::map::Map<'tcx>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + 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 { + [PathSegment { res: Some(Res::SelfTy(_, impl_ref)), .. }] => { + let impl_ty_name = + impl_ref.map(|(def_id, _)| self.tcx.def_path_str(def_id)); + self.selftys.push((path.span, impl_ty_name)); + } + _ => {} + }, + _ => {} + } + hir::intravisit::walk_ty(self, arg); + } + } + if let ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, .. @@ -547,18 +571,19 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), ), generics: tcx.generics_of(def_id), + tcx, + selftys: vec![], }; let prohibit_opaque = tcx .explicit_item_bounds(def_id) .iter() .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); debug!( - "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}", - prohibit_opaque, visitor + "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor.opaque_identity_ty={:?}, visitor.generics={:?}", + prohibit_opaque, visitor.opaque_identity_ty, visitor.generics ); 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, .. }) => { @@ -576,11 +601,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( if is_async { "async fn" } else { "impl Trait" }, ); - for span in visitor.selfty_spans { + for (span, name) in visitor.selftys { err.span_suggestion( span, "consider spelling out the type instead", - format!("{:?}", ty), + name.unwrap_or_else(|| format!("{:?}", ty)), Applicability::MaybeIncorrect, ); } @@ -1591,31 +1616,3 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { } err.emit(); } - -struct SelfTySpanVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - selfty_spans: Vec, -} - -impl Visitor<'tcx> for SelfTySpanVisitor<'tcx> { - type Map = rustc_middle::hir::map::Map<'tcx>; - - fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { - 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 index 8e3dc0406fafc..92b66147106e1 100644 --- a/src/test/ui/async-await/issues/issue-78600.stderr +++ b/src/test/ui/async-await/issues/issue-78600.stderr @@ -4,7 +4,7 @@ error[E0760]: `async fn` return type cannot contain a projection or `Self` that LL | async fn new(i: &'a i32) -> Result { | ^^^^^^^----^^^^^ | | - | help: consider spelling out the type instead: `std::result::Result, ()>` + | help: consider spelling out the type instead: `S<'a>` error: aborting due to previous error