Skip to content

Commit 37a5464

Browse files
Eagerly instantiate closure ty
1 parent 098d4fd commit 37a5464

File tree

4 files changed

+73
-79
lines changed

4 files changed

+73
-79
lines changed

Diff for: compiler/rustc_hir_typeck/src/closure.rs

+70-76
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6868

6969
debug!(?bound_sig, ?liberated_sig);
7070

71+
let parent_args =
72+
GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
73+
74+
let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin {
75+
kind: TypeVariableOriginKind::ClosureSynthetic,
76+
span: expr_span,
77+
});
78+
7179
// FIXME: We could probably actually just unify this further --
7280
// instead of having a `FnSig` and a `Option<CoroutineTypes>`,
7381
// we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`,
7482
// similar to how `ty::GenSig` is a distinct data structure.
75-
let coroutine_types = match closure.kind {
76-
hir::ClosureKind::Closure => None,
83+
let (closure_ty, coroutine_types) = match closure.kind {
84+
hir::ClosureKind::Closure => {
85+
// Tuple up the arguments and insert the resulting function type into
86+
// the `closures` table.
87+
let sig = bound_sig.map_bound(|sig| {
88+
tcx.mk_fn_sig(
89+
[Ty::new_tup(tcx, sig.inputs())],
90+
sig.output(),
91+
sig.c_variadic,
92+
sig.unsafety,
93+
sig.abi,
94+
)
95+
});
96+
97+
debug!(?sig, ?expected_kind);
98+
99+
let closure_kind_ty = match expected_kind {
100+
Some(kind) => Ty::from_closure_kind(tcx, kind),
101+
102+
// Create a type variable (for now) to represent the closure kind.
103+
// It will be unified during the upvar inference phase (`upvar.rs`)
104+
None => self.next_root_ty_var(TypeVariableOrigin {
105+
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
106+
kind: TypeVariableOriginKind::ClosureSynthetic,
107+
span: expr_span,
108+
}),
109+
};
110+
111+
let closure_args = ty::ClosureArgs::new(
112+
tcx,
113+
ty::ClosureArgsParts {
114+
parent_args,
115+
closure_kind_ty,
116+
closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig),
117+
tupled_upvars_ty,
118+
},
119+
);
120+
121+
(Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args), None)
122+
}
77123
hir::ClosureKind::Coroutine(kind) => {
78124
let yield_ty = match kind {
79125
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
@@ -119,74 +165,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
119165
// Resume type defaults to `()` if the coroutine has no argument.
120166
let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
121167

122-
Some(CoroutineTypes { resume_ty, yield_ty })
123-
}
124-
};
125-
126-
check_fn(
127-
&mut FnCtxt::new(self, self.param_env, closure.def_id),
128-
liberated_sig,
129-
coroutine_types,
130-
closure.fn_decl,
131-
expr_def_id,
132-
body,
133-
// Closure "rust-call" ABI doesn't support unsized params
134-
false,
135-
);
136-
137-
let parent_args =
138-
GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
139-
140-
let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin {
141-
kind: TypeVariableOriginKind::ClosureSynthetic,
142-
span: expr_span,
143-
});
144-
145-
match closure.kind {
146-
hir::ClosureKind::Closure => {
147-
assert_eq!(coroutine_types, None);
148-
// Tuple up the arguments and insert the resulting function type into
149-
// the `closures` table.
150-
let sig = bound_sig.map_bound(|sig| {
151-
tcx.mk_fn_sig(
152-
[Ty::new_tup(tcx, sig.inputs())],
153-
sig.output(),
154-
sig.c_variadic,
155-
sig.unsafety,
156-
sig.abi,
157-
)
158-
});
159-
160-
debug!(?sig, ?expected_kind);
161-
162-
let closure_kind_ty = match expected_kind {
163-
Some(kind) => Ty::from_closure_kind(tcx, kind),
164-
165-
// Create a type variable (for now) to represent the closure kind.
166-
// It will be unified during the upvar inference phase (`upvar.rs`)
167-
None => self.next_root_ty_var(TypeVariableOrigin {
168-
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
169-
kind: TypeVariableOriginKind::ClosureSynthetic,
170-
span: expr_span,
171-
}),
172-
};
173-
174-
let closure_args = ty::ClosureArgs::new(
175-
tcx,
176-
ty::ClosureArgsParts {
177-
parent_args,
178-
closure_kind_ty,
179-
closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig),
180-
tupled_upvars_ty,
181-
},
182-
);
183-
184-
Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args)
185-
}
186-
hir::ClosureKind::Coroutine(_) => {
187-
let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else {
188-
bug!("expected coroutine to have yield/resume types");
189-
};
190168
let interior = self.next_ty_var(TypeVariableOrigin {
191169
kind: TypeVariableOriginKind::MiscVariable,
192170
span: body.value.span,
@@ -209,9 +187,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
209187
},
210188
);
211189

212-
Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args)
190+
(
191+
Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args),
192+
Some(CoroutineTypes { resume_ty, yield_ty }),
193+
)
213194
}
214-
}
195+
};
196+
197+
check_fn(
198+
&mut FnCtxt::new(self, self.param_env, closure.def_id),
199+
liberated_sig,
200+
coroutine_types,
201+
closure.fn_decl,
202+
expr_def_id,
203+
body,
204+
// Closure "rust-call" ABI doesn't support unsized params
205+
false,
206+
);
207+
208+
closure_ty
215209
}
216210

217211
/// Given the expected type, figures out what it can about this closure we
@@ -683,10 +677,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
683677
})
684678
}
685679
// All `gen {}` and `async gen {}` must return unit.
686-
hir::ClosureKind::Coroutine(
687-
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
688-
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
689-
) => self.tcx.types.unit,
680+
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
681+
hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen,
682+
_,
683+
)) => self.tcx.types.unit,
690684

691685
// For async blocks, we just fall back to `_` here.
692686
// For closures/coroutines, we know nothing about the return

Diff for: tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | let c1 : () = c;
99
| expected due to this
1010
|
1111
= note: expected unit type `()`
12-
found closure `{mod1::f<T>::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}`
12+
found closure `{mod1::f<T>::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}`
1313
help: use parentheses to call this closure
1414
|
1515
LL | let c1 : () = c();

Diff for: tests/ui/closures/print/closure-print-generic-verbose-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | let c1 : () = c;
99
| expected due to this
1010
|
1111
= note: expected unit type `()`
12-
found closure `{f<T>::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}`
12+
found closure `{f<T>::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}`
1313
help: use parentheses to call this closure
1414
|
1515
LL | let c1 : () = c();

Diff for: tests/ui/closures/print/closure-print-verbose.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
77
| expected due to this
88
|
99
= note: expected fn pointer `fn(u8) -> u8`
10-
found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?6t]}`
10+
found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?4t]}`
1111
note: closures can only be coerced to `fn` types if they do not capture any variables
1212
--> $DIR/closure-print-verbose.rs:10:39
1313
|

0 commit comments

Comments
 (0)