Skip to content

Commit 07d5c25

Browse files
authored
Rollup merge of rust-lang#129493 - cjgillot:early-opaque-def, r=petrochenkov
Create opaque definitions in resolver. Implementing rust-lang#129023 (comment) That was easier than I expected. r? `@petrochenkov`
2 parents 1063c0d + f68f665 commit 07d5c25

File tree

8 files changed

+91
-97
lines changed

8 files changed

+91
-97
lines changed

compiler/rustc_ast/src/visit.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ pub enum FnKind<'a> {
6969
Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
7070

7171
/// E.g., `|x, y| body`.
72-
Closure(&'a ClosureBinder, &'a FnDecl, &'a Expr),
72+
Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
7373
}
7474

7575
impl<'a> FnKind<'a> {
7676
pub fn header(&self) -> Option<&'a FnHeader> {
7777
match *self {
7878
FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
79-
FnKind::Closure(_, _, _) => None,
79+
FnKind::Closure(..) => None,
8080
}
8181
}
8282

@@ -90,7 +90,7 @@ impl<'a> FnKind<'a> {
9090
pub fn decl(&self) -> &'a FnDecl {
9191
match self {
9292
FnKind::Fn(_, _, sig, _, _, _) => &sig.decl,
93-
FnKind::Closure(_, decl, _) => decl,
93+
FnKind::Closure(_, _, decl, _) => decl,
9494
}
9595
}
9696

@@ -839,7 +839,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
839839
try_visit!(walk_fn_decl(visitor, decl));
840840
visit_opt!(visitor, visit_block, body);
841841
}
842-
FnKind::Closure(binder, decl, body) => {
842+
FnKind::Closure(binder, _coroutine_kind, decl, body) => {
843843
try_visit!(visitor.visit_closure_binder(binder));
844844
try_visit!(walk_fn_decl(visitor, decl));
845845
try_visit!(visitor.visit_expr(body));
@@ -1107,7 +1107,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
11071107
ExprKind::Closure(box Closure {
11081108
binder,
11091109
capture_clause,
1110-
coroutine_kind: _,
1110+
coroutine_kind,
11111111
constness: _,
11121112
movability: _,
11131113
fn_decl,
@@ -1116,7 +1116,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
11161116
fn_arg_span: _,
11171117
}) => {
11181118
try_visit!(visitor.visit_capture_by(capture_clause));
1119-
try_visit!(visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id))
1119+
try_visit!(visitor.visit_fn(
1120+
FnKind::Closure(binder, coroutine_kind, fn_decl, body),
1121+
*span,
1122+
*id
1123+
))
11201124
}
11211125
ExprKind::Block(block, opt_label) => {
11221126
visit_opt!(visitor, visit_label, opt_label);

compiler/rustc_ast_lowering/src/lib.rs

+4-26
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ use std::collections::hash_map::Entry;
4545
use rustc_ast::node_id::NodeMap;
4646
use rustc_ast::ptr::P;
4747
use rustc_ast::{self as ast, *};
48-
use rustc_ast_pretty::pprust;
4948
use rustc_data_structures::captures::Captures;
5049
use rustc_data_structures::fingerprint::Fingerprint;
5150
use rustc_data_structures::fx::FxIndexSet;
@@ -1399,24 +1398,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13991398
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span });
14001399
}
14011400

1402-
let span = t.span;
1403-
1404-
// HACK: pprust breaks strings with newlines when the type
1405-
// gets too long. We don't want these to show up in compiler
1406-
// output or built artifacts, so replace them here...
1407-
// Perhaps we should instead format APITs more robustly.
1408-
let ident = Ident::from_str_and_span(
1409-
&pprust::ty_to_string(t).replace('\n', " "),
1410-
span,
1411-
);
1412-
1413-
self.create_def(
1414-
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
1415-
*def_node_id,
1416-
ident.name,
1417-
DefKind::TyParam,
1418-
span,
1419-
);
1401+
let def_id = self.local_def_id(*def_node_id);
1402+
let name = self.tcx.item_name(def_id.to_def_id());
1403+
let ident = Ident::new(name, span);
14201404
let (param, bounds, path) = self.lower_universal_param_and_bounds(
14211405
*def_node_id,
14221406
span,
@@ -1618,13 +1602,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16181602
opaque_ty_span: Span,
16191603
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
16201604
) -> hir::TyKind<'hir> {
1621-
let opaque_ty_def_id = self.create_def(
1622-
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
1623-
opaque_ty_node_id,
1624-
kw::Empty,
1625-
DefKind::OpaqueTy,
1626-
opaque_ty_span,
1627-
);
1605+
let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
16281606
debug!(?opaque_ty_def_id);
16291607

16301608
// Map from captured (old) lifetime to synthetic (new) lifetime.

compiler/rustc_ast_passes/src/ast_validation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14851485

14861486
let disallowed = (!tilde_const_allowed).then(|| match fk {
14871487
FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span },
1488-
FnKind::Closure(_, _, _) => TildeConstReason::Closure,
1488+
FnKind::Closure(..) => TildeConstReason::Closure,
14891489
});
14901490
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
14911491
}

compiler/rustc_resolve/src/def_collector.rs

+64-52
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::mem;
22

33
use rustc_ast::visit::FnKind;
44
use rustc_ast::*;
5+
use rustc_ast_pretty::pprust;
56
use rustc_expand::expand::AstFragment;
67
use rustc_hir as hir;
78
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
@@ -120,8 +121,6 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
120121

121122
impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
122123
fn visit_item(&mut self, i: &'a Item) {
123-
debug!("visit_item: {:?}", i);
124-
125124
// Pick the def data. This need not be unique, but the more
126125
// information we encapsulate into, the better
127126
let mut opt_macro_data = None;
@@ -183,38 +182,51 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
183182
}
184183

185184
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
186-
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
187-
match sig.header.coroutine_kind {
188-
Some(coroutine_kind) => {
189-
self.visit_generics(generics);
190-
191-
// For async functions, we need to create their inner defs inside of a
192-
// closure to match their desugared representation. Besides that,
193-
// we must mirror everything that `visit::walk_fn` below does.
194-
self.visit_fn_header(&sig.header);
195-
for param in &sig.decl.inputs {
196-
self.visit_param(param);
197-
}
198-
self.visit_fn_ret_ty(&sig.decl.output);
199-
// If this async fn has no body (i.e. it's an async fn signature in a trait)
200-
// then the closure_def will never be used, and we should avoid generating a
201-
// def-id for it.
202-
if let Some(body) = body {
203-
let closure_def = self.create_def(
204-
coroutine_kind.closure_id(),
205-
kw::Empty,
206-
DefKind::Closure,
207-
span,
208-
);
209-
self.with_parent(closure_def, |this| this.visit_block(body));
210-
}
211-
return;
185+
match fn_kind {
186+
FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body)
187+
if let Some(coroutine_kind) = header.coroutine_kind =>
188+
{
189+
self.visit_fn_header(header);
190+
self.visit_generics(generics);
191+
192+
// For async functions, we need to create their inner defs inside of a
193+
// closure to match their desugared representation. Besides that,
194+
// we must mirror everything that `visit::walk_fn` below does.
195+
let FnDecl { inputs, output } = &**decl;
196+
for param in inputs {
197+
self.visit_param(param);
198+
}
199+
200+
let (return_id, return_span) = coroutine_kind.return_id();
201+
let return_def =
202+
self.create_def(return_id, kw::Empty, DefKind::OpaqueTy, return_span);
203+
self.with_parent(return_def, |this| this.visit_fn_ret_ty(output));
204+
205+
// If this async fn has no body (i.e. it's an async fn signature in a trait)
206+
// then the closure_def will never be used, and we should avoid generating a
207+
// def-id for it.
208+
if let Some(body) = body {
209+
let closure_def = self.create_def(
210+
coroutine_kind.closure_id(),
211+
kw::Empty,
212+
DefKind::Closure,
213+
span,
214+
);
215+
self.with_parent(closure_def, |this| this.visit_block(body));
212216
}
213-
None => {}
214217
}
215-
}
218+
FnKind::Closure(binder, Some(coroutine_kind), decl, body) => {
219+
self.visit_closure_binder(binder);
220+
visit::walk_fn_decl(self, decl);
216221

217-
visit::walk_fn(self, fn_kind);
222+
// Async closures desugar to closures inside of closures, so
223+
// we must create two defs.
224+
let coroutine_def =
225+
self.create_def(coroutine_kind.closure_id(), kw::Empty, DefKind::Closure, span);
226+
self.with_parent(coroutine_def, |this| visit::walk_expr(this, body));
227+
}
228+
_ => visit::walk_fn(self, fn_kind),
229+
}
218230
}
219231

220232
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> {
334346
fn visit_expr(&mut self, expr: &'a Expr) {
335347
let parent_def = match expr.kind {
336348
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
337-
ExprKind::Closure(ref closure) => {
338-
// Async closures desugar to closures inside of closures, so
339-
// we must create two defs.
340-
let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span);
341-
match closure.coroutine_kind {
342-
Some(coroutine_kind) => {
343-
self.with_parent(closure_def, |this| {
344-
let coroutine_def = this.create_def(
345-
coroutine_kind.closure_id(),
346-
kw::Empty,
347-
DefKind::Closure,
348-
expr.span,
349-
);
350-
this.with_parent(coroutine_def, |this| visit::walk_expr(this, expr));
351-
});
352-
return;
353-
}
354-
None => closure_def,
355-
}
356-
}
357-
ExprKind::Gen(_, _, _, _) => {
349+
ExprKind::Closure(..) | ExprKind::Gen(..) => {
358350
self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
359351
}
360352
ExprKind::ConstBlock(ref constant) => {
@@ -381,6 +373,26 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
381373
TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
382374
// Anonymous structs or unions are visited later after defined.
383375
TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {}
376+
TyKind::ImplTrait(id, _) => {
377+
// HACK: pprust breaks strings with newlines when the type
378+
// gets too long. We don't want these to show up in compiler
379+
// output or built artifacts, so replace them here...
380+
// Perhaps we should instead format APITs more robustly.
381+
let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " "));
382+
let kind = match self.impl_trait_context {
383+
ImplTraitContext::Universal => DefKind::TyParam,
384+
ImplTraitContext::Existential => DefKind::OpaqueTy,
385+
};
386+
let id = self.create_def(*id, name, kind, ty.span);
387+
match self.impl_trait_context {
388+
// Do not nest APIT, as we desugar them as `impl_trait: bounds`,
389+
// so the `impl_trait` node is not a parent to `bounds`.
390+
ImplTraitContext::Universal => visit::walk_ty(self, ty),
391+
ImplTraitContext::Existential => {
392+
self.with_parent(id, |this| visit::walk_ty(this, ty))
393+
}
394+
};
395+
}
384396
_ => visit::walk_ty(self, ty),
385397
}
386398
}

compiler/rustc_resolve/src/late.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
10101010
this.in_func_body = previous_state;
10111011
}
10121012
}
1013-
FnKind::Closure(binder, declaration, body) => {
1013+
FnKind::Closure(binder, _, declaration, body) => {
10141014
this.visit_closure_binder(binder);
10151015

10161016
this.with_lifetime_rib(

tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
field_tys: {
44
_0: CoroutineSavedTy {
55
ty: Coroutine(
6-
DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
6+
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
77
[
88
(),
99
std::future::ResumeTy,
1010
(),
1111
(),
1212
CoroutineWitness(
13-
DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
13+
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
1414
[],
1515
),
1616
(),
@@ -24,14 +24,14 @@
2424
},
2525
_1: CoroutineSavedTy {
2626
ty: Coroutine(
27-
DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
27+
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
2828
[
2929
(),
3030
std::future::ResumeTy,
3131
(),
3232
(),
3333
CoroutineWitness(
34-
DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
34+
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
3535
[],
3636
),
3737
(),

tests/ui/coroutine/print/coroutine-print-verbose-1.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ note: coroutine is not `Send` as this value is used across a yield
1010
--> $DIR/coroutine-print-verbose-1.rs:35:9
1111
|
1212
LL | let _non_send_gen = make_non_send_coroutine();
13-
| ------------- has type `Opaque(DefId(0:34 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send`
13+
| ------------- has type `Opaque(DefId(0:24 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send`
1414
LL | yield;
1515
| ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
1616
note: required by a bound in `require_send`
@@ -33,12 +33,12 @@ note: required because it's used within this coroutine
3333
|
3434
LL | #[coroutine] || {
3535
| ^^
36-
note: required because it appears within the type `Opaque(DefId(0:35 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
36+
note: required because it appears within the type `Opaque(DefId(0:29 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
3737
--> $DIR/coroutine-print-verbose-1.rs:41:30
3838
|
3939
LL | pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> {
4040
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
41-
note: required because it appears within the type `Opaque(DefId(0:36 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])`
41+
note: required because it appears within the type `Opaque(DefId(0:32 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])`
4242
--> $DIR/coroutine-print-verbose-1.rs:47:34
4343
|
4444
LL | fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> {

tests/ui/nll/ty-outlives/impl-trait-captures.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds
1+
error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds
22
--> $DIR/impl-trait-captures.rs:11:5
33
|
44
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
55
| -- ------------ opaque type defined here
66
| |
7-
| hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here
7+
| hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here
88
LL | x
99
| ^
1010
|
11-
help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`
11+
help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_))`
1212
|
13-
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> {
13+
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> {
1414
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1515

1616
error: aborting due to 1 previous error

0 commit comments

Comments
 (0)