diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-09-01 03:58:04 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-01 03:58:04 +0200 |
| commit | 07d5c250be85d3d8532369cb2aec8e15213ac956 (patch) | |
| tree | 5fb33360158bbf8aadab57b9295d8da087f13349 /compiler/rustc_resolve/src | |
| parent | 1063c0dd37bda8913ffc5548735ffeea14eb6123 (diff) | |
| parent | f68f66538a88a377b3510723950e97373796c5c8 (diff) | |
| download | rust-07d5c250be85d3d8532369cb2aec8e15213ac956.tar.gz rust-07d5c250be85d3d8532369cb2aec8e15213ac956.zip | |
Rollup merge of #129493 - cjgillot:early-opaque-def, r=petrochenkov
Create opaque definitions in resolver. Implementing https://github.com/rust-lang/rust/issues/129023#issuecomment-2306079532 That was easier than I expected. r? `@petrochenkov`
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/def_collector.rs | 116 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 2 |
2 files changed, 65 insertions, 53 deletions
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 3595db78e93..a70d51606f7 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -2,6 +2,7 @@ use std::mem; use rustc_ast::visit::FnKind; use rustc_ast::*; +use rustc_ast_pretty::pprust; use rustc_expand::expand::AstFragment; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; @@ -120,8 +121,6 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_item(&mut self, i: &'a Item) { - debug!("visit_item: {:?}", i); - // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better let mut opt_macro_data = None; @@ -183,38 +182,51 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { - if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind { - match sig.header.coroutine_kind { - Some(coroutine_kind) => { - self.visit_generics(generics); - - // For async functions, we need to create their inner defs inside of a - // closure to match their desugared representation. Besides that, - // we must mirror everything that `visit::walk_fn` below does. - self.visit_fn_header(&sig.header); - for param in &sig.decl.inputs { - self.visit_param(param); - } - self.visit_fn_ret_ty(&sig.decl.output); - // If this async fn has no body (i.e. it's an async fn signature in a trait) - // then the closure_def will never be used, and we should avoid generating a - // def-id for it. - if let Some(body) = body { - let closure_def = self.create_def( - coroutine_kind.closure_id(), - kw::Empty, - DefKind::Closure, - span, - ); - self.with_parent(closure_def, |this| this.visit_block(body)); - } - return; + match fn_kind { + FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body) + if let Some(coroutine_kind) = header.coroutine_kind => + { + self.visit_fn_header(header); + self.visit_generics(generics); + + // For async functions, we need to create their inner defs inside of a + // closure to match their desugared representation. Besides that, + // we must mirror everything that `visit::walk_fn` below does. + let FnDecl { inputs, output } = &**decl; + for param in inputs { + self.visit_param(param); + } + + let (return_id, return_span) = coroutine_kind.return_id(); + let return_def = + self.create_def(return_id, kw::Empty, DefKind::OpaqueTy, return_span); + self.with_parent(return_def, |this| this.visit_fn_ret_ty(output)); + + // If this async fn has no body (i.e. it's an async fn signature in a trait) + // then the closure_def will never be used, and we should avoid generating a + // def-id for it. + if let Some(body) = body { + let closure_def = self.create_def( + coroutine_kind.closure_id(), + kw::Empty, + DefKind::Closure, + span, + ); + self.with_parent(closure_def, |this| this.visit_block(body)); } - None => {} } - } + FnKind::Closure(binder, Some(coroutine_kind), decl, body) => { + self.visit_closure_binder(binder); + visit::walk_fn_decl(self, decl); - visit::walk_fn(self, fn_kind); + // Async closures desugar to closures inside of closures, so + // we must create two defs. + let coroutine_def = + self.create_def(coroutine_kind.closure_id(), kw::Empty, DefKind::Closure, span); + self.with_parent(coroutine_def, |this| visit::walk_expr(this, body)); + } + _ => visit::walk_fn(self, fn_kind), + } } fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { @@ -334,27 +346,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_expr(&mut self, expr: &'a Expr) { let parent_def = match expr.kind { ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), - ExprKind::Closure(ref closure) => { - // Async closures desugar to closures inside of closures, so - // we must create two defs. - let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span); - match closure.coroutine_kind { - Some(coroutine_kind) => { - self.with_parent(closure_def, |this| { - let coroutine_def = this.create_def( - coroutine_kind.closure_id(), - kw::Empty, - DefKind::Closure, - expr.span, - ); - this.with_parent(coroutine_def, |this| visit::walk_expr(this, expr)); - }); - return; - } - None => closure_def, - } - } - ExprKind::Gen(_, _, _, _) => { + ExprKind::Closure(..) | ExprKind::Gen(..) => { self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) } ExprKind::ConstBlock(ref constant) => { @@ -381,6 +373,26 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), // Anonymous structs or unions are visited later after defined. TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {} + TyKind::ImplTrait(id, _) => { + // HACK: pprust breaks strings with newlines when the type + // gets too long. We don't want these to show up in compiler + // output or built artifacts, so replace them here... + // Perhaps we should instead format APITs more robustly. + let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " ")); + let kind = match self.impl_trait_context { + ImplTraitContext::Universal => DefKind::TyParam, + ImplTraitContext::Existential => DefKind::OpaqueTy, + }; + let id = self.create_def(*id, name, kind, ty.span); + match self.impl_trait_context { + // Do not nest APIT, as we desugar them as `impl_trait: bounds`, + // so the `impl_trait` node is not a parent to `bounds`. + ImplTraitContext::Universal => visit::walk_ty(self, ty), + ImplTraitContext::Existential => { + self.with_parent(id, |this| visit::walk_ty(this, ty)) + } + }; + } _ => visit::walk_ty(self, ty), } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8ec0469ed6d..a0386ddcbb3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1010,7 +1010,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, this.in_func_body = previous_state; } } - FnKind::Closure(binder, declaration, body) => { + FnKind::Closure(binder, _, declaration, body) => { this.visit_closure_binder(binder); this.with_lifetime_rib( |
