Skip to content

Commit ed40b95

Browse files
committed
spell out nested self type
1 parent 05704ec commit ed40b95

File tree

2 files changed

+49
-9
lines changed

2 files changed

+49
-9
lines changed

Diff for: compiler/rustc_typeck/src/check/check.rs

+38-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_attr as attr;
77
use rustc_errors::{Applicability, ErrorReported};
88
use rustc_hir as hir;
99
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
10+
use rustc_hir::intravisit::Visitor;
1011
use rustc_hir::lang_items::LangItem;
1112
use rustc_hir::{ItemKind, Node};
1213
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -557,6 +558,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
557558
);
558559

559560
if let Some(ty) = prohibit_opaque.break_value() {
561+
let mut visitor = SelfTySpanVisitor { tcx, selfty_spans: vec![] };
562+
visitor.visit_item(&item);
560563
let is_async = match item.kind {
561564
ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
562565
matches!(origin, hir::OpaqueTyOrigin::AsyncFn)
@@ -573,15 +576,13 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
573576
if is_async { "async fn" } else { "impl Trait" },
574577
);
575578

576-
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
577-
if snippet == "Self" {
578-
err.span_suggestion(
579-
span,
580-
"consider spelling out the type instead",
581-
format!("{:?}", ty),
582-
Applicability::MaybeIncorrect,
583-
);
584-
}
579+
for span in visitor.selfty_spans {
580+
err.span_suggestion(
581+
span,
582+
"consider spelling out the type instead",
583+
format!("{:?}", ty),
584+
Applicability::MaybeIncorrect,
585+
);
585586
}
586587
err.emit();
587588
}
@@ -1590,3 +1591,31 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
15901591
}
15911592
err.emit();
15921593
}
1594+
1595+
struct SelfTySpanVisitor<'tcx> {
1596+
tcx: TyCtxt<'tcx>,
1597+
selfty_spans: Vec<Span>,
1598+
}
1599+
1600+
impl Visitor<'tcx> for SelfTySpanVisitor<'tcx> {
1601+
type Map = rustc_middle::hir::map::Map<'tcx>;
1602+
1603+
fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
1604+
hir::intravisit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
1605+
}
1606+
1607+
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
1608+
match arg.kind {
1609+
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
1610+
[segment]
1611+
if segment.res.map(|res| matches!(res, Res::SelfTy(_, _))).unwrap_or(false) =>
1612+
{
1613+
self.selfty_spans.push(path.span);
1614+
}
1615+
_ => {}
1616+
},
1617+
_ => {}
1618+
}
1619+
hir::intravisit::walk_ty(self, arg);
1620+
}
1621+
}

Diff for: src/test/ui/async-await/issues/issue-78600.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0760]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
2+
--> $DIR/issue-78600.rs:6:33
3+
|
4+
LL | async fn new(i: &'a i32) -> Result<Self, ()> {
5+
| ^^^^^^^----^^^^^
6+
| |
7+
| help: consider spelling out the type instead: `std::result::Result<S<'a>, ()>`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0760`.

0 commit comments

Comments
 (0)