]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //! Code for type-checking closure expressions. |
2 | ||
ff7c6d11 | 3 | use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; |
1a4d82fc | 4 | |
9fa01778 | 5 | use crate::astconv::AstConv; |
dfeec247 XL |
6 | use rustc_hir as hir; |
7 | use rustc_hir::def_id::DefId; | |
3dfed10e | 8 | use rustc_hir::lang_items::LangItem; |
74b04a01 XL |
9 | use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; |
10 | use rustc_infer::infer::LateBoundRegionConversionTime; | |
11 | use rustc_infer::infer::{InferOk, InferResult}; | |
ba9703b0 XL |
12 | use rustc_middle::ty::fold::TypeFoldable; |
13 | use rustc_middle::ty::subst::InternalSubsts; | |
3dfed10e | 14 | use rustc_middle::ty::{self, Ty}; |
dfeec247 XL |
15 | use rustc_span::source_map::Span; |
16 | use rustc_target::spec::abi::Abi; | |
ba9703b0 XL |
17 | use rustc_trait_selection::traits::error_reporting::ArgKind; |
18 | use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; | |
c34b1796 | 19 | use std::cmp; |
476ff2be | 20 | use std::iter; |
1a4d82fc | 21 | |
0531ce1d XL |
22 | /// What signature do we *expect* the closure to have from context? |
23 | #[derive(Debug)] | |
24 | struct ExpectedSig<'tcx> { | |
25 | /// Span that gave us this expectation, if we know that. | |
26 | cause_span: Option<Span>, | |
fc512014 | 27 | sig: ty::PolyFnSig<'tcx>, |
0531ce1d XL |
28 | } |
29 | ||
abe05a73 XL |
30 | struct ClosureSignatures<'tcx> { |
31 | bound_sig: ty::PolyFnSig<'tcx>, | |
32 | liberated_sig: ty::FnSig<'tcx>, | |
33 | } | |
34 | ||
dc9dc135 | 35 | impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
abe05a73 XL |
36 | pub fn check_expr_closure( |
37 | &self, | |
dfeec247 | 38 | expr: &hir::Expr<'_>, |
60c5eb7d | 39 | _capture: hir::CaptureBy, |
dfeec247 | 40 | decl: &'tcx hir::FnDecl<'tcx>, |
abe05a73 | 41 | body_id: hir::BodyId, |
60c5eb7d | 42 | gen: Option<hir::Movability>, |
abe05a73 XL |
43 | expected: Expectation<'tcx>, |
44 | ) -> Ty<'tcx> { | |
dfeec247 | 45 | debug!("check_expr_closure(expr={:?},expected={:?})", expr, expected); |
a7813a04 XL |
46 | |
47 | // It's always helpful for inference if we know the kind of | |
48 | // closure sooner rather than later, so first examine the expected | |
49 | // type, and see if can glean a closure kind from there. | |
c30ab7b3 | 50 | let (expected_sig, expected_kind) = match expected.to_option(self) { |
a7813a04 | 51 | Some(ty) => self.deduce_expectations_from_expected_type(ty), |
c30ab7b3 | 52 | None => (None, None), |
a7813a04 | 53 | }; |
0731742a | 54 | let body = self.tcx.hir().body(body_id); |
2c00a5a8 | 55 | self.check_closure(expr, expected_kind, decl, body, gen, expected_sig) |
a7813a04 | 56 | } |
1a4d82fc | 57 | |
abe05a73 XL |
58 | fn check_closure( |
59 | &self, | |
dfeec247 | 60 | expr: &hir::Expr<'_>, |
abe05a73 | 61 | opt_kind: Option<ty::ClosureKind>, |
dfeec247 XL |
62 | decl: &'tcx hir::FnDecl<'tcx>, |
63 | body: &'tcx hir::Body<'tcx>, | |
60c5eb7d | 64 | gen: Option<hir::Movability>, |
0531ce1d | 65 | expected_sig: Option<ExpectedSig<'tcx>>, |
abe05a73 | 66 | ) -> Ty<'tcx> { |
dfeec247 | 67 | debug!("check_closure(opt_kind={:?}, expected_sig={:?})", opt_kind, expected_sig); |
a7813a04 | 68 | |
416331ca | 69 | let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id); |
abe05a73 | 70 | |
dfeec247 | 71 | let ClosureSignatures { bound_sig, liberated_sig } = |
f9f354fc | 72 | self.sig_of_closure(expr_def_id.to_def_id(), decl, body, expected_sig); |
abe05a73 XL |
73 | |
74 | debug!("check_closure: ty_of_closure returns {:?}", liberated_sig); | |
75 | ||
dfeec247 XL |
76 | let generator_types = |
77 | check_fn(self, self.param_env, liberated_sig, decl, expr.hir_id, body, gen).1; | |
a7813a04 | 78 | |
3dfed10e | 79 | let parent_substs = InternalSubsts::identity_for_item( |
f9f354fc XL |
80 | self.tcx, |
81 | self.tcx.closure_base_def_id(expr_def_id.to_def_id()), | |
82 | ); | |
3dfed10e | 83 | |
29967ef6 XL |
84 | let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin { |
85 | kind: TypeVariableOriginKind::ClosureSynthetic, | |
86 | span: self.tcx.hir().span(expr.hir_id), | |
87 | }); | |
3dfed10e | 88 | |
74b04a01 XL |
89 | if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types |
90 | { | |
3dfed10e XL |
91 | let generator_substs = ty::GeneratorSubsts::new( |
92 | self.tcx, | |
93 | ty::GeneratorSubstsParts { | |
94 | parent_substs, | |
95 | resume_ty, | |
96 | yield_ty, | |
97 | return_ty: liberated_sig.output(), | |
98 | witness: interior, | |
99 | tupled_upvars_ty, | |
100 | }, | |
101 | ); | |
94b46f34 | 102 | |
3dfed10e XL |
103 | return self.tcx.mk_generator( |
104 | expr_def_id.to_def_id(), | |
105 | generator_substs.substs, | |
106 | movability, | |
107 | ); | |
ba9703b0 | 108 | } |
a7813a04 XL |
109 | |
110 | // Tuple up the arguments and insert the resulting function type into | |
111 | // the `closures` table. | |
abe05a73 XL |
112 | let sig = bound_sig.map_bound(|sig| { |
113 | self.tcx.mk_fn_sig( | |
0531ce1d | 114 | iter::once(self.tcx.intern_tup(sig.inputs())), |
abe05a73 | 115 | sig.output(), |
532ac7d7 | 116 | sig.c_variadic, |
abe05a73 XL |
117 | sig.unsafety, |
118 | sig.abi, | |
119 | ) | |
120 | }); | |
121 | ||
122 | debug!( | |
123 | "check_closure: expr_def_id={:?}, sig={:?}, opt_kind={:?}", | |
0531ce1d | 124 | expr_def_id, sig, opt_kind |
abe05a73 | 125 | ); |
a7813a04 | 126 | |
3dfed10e XL |
127 | let closure_kind_ty = match opt_kind { |
128 | Some(kind) => kind.to_ty(self.tcx), | |
ff7c6d11 | 129 | |
3dfed10e XL |
130 | // Create a type variable (for now) to represent the closure kind. |
131 | // It will be unified during the upvar inference phase (`upvar.rs`) | |
132 | None => self.infcx.next_ty_var(TypeVariableOrigin { | |
133 | // FIXME(eddyb) distinguish closure kind inference variables from the rest. | |
134 | kind: TypeVariableOriginKind::ClosureSynthetic, | |
135 | span: expr.span, | |
136 | }), | |
137 | }; | |
9e0c209e | 138 | |
3dfed10e XL |
139 | let closure_substs = ty::ClosureSubsts::new( |
140 | self.tcx, | |
141 | ty::ClosureSubstsParts { | |
142 | parent_substs, | |
143 | closure_kind_ty, | |
144 | closure_sig_as_fn_ptr_ty: self.tcx.mk_fn_ptr(sig), | |
145 | tupled_upvars_ty, | |
146 | }, | |
147 | ); | |
ba9703b0 | 148 | |
3dfed10e | 149 | let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs); |
ba9703b0 XL |
150 | |
151 | debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type); | |
152 | ||
9e0c209e | 153 | closure_type |
1a4d82fc | 154 | } |
1a4d82fc | 155 | |
0531ce1d XL |
156 | /// Given the expected type, figures out what it can about this closure we |
157 | /// are about to type check: | |
abe05a73 XL |
158 | fn deduce_expectations_from_expected_type( |
159 | &self, | |
160 | expected_ty: Ty<'tcx>, | |
0531ce1d | 161 | ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) { |
dfeec247 | 162 | debug!("deduce_expectations_from_expected_type(expected_ty={:?})", expected_ty); |
a7813a04 | 163 | |
1b1a35ee | 164 | match *expected_ty.kind() { |
b7449926 | 165 | ty::Dynamic(ref object_type, ..) => { |
f9f354fc XL |
166 | let sig = object_type.projection_bounds().find_map(|pb| { |
167 | let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self); | |
168 | self.deduce_sig_from_projection(None, pb) | |
169 | }); | |
dfeec247 XL |
170 | let kind = object_type |
171 | .principal_def_id() | |
74b04a01 | 172 | .and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did)); |
a7813a04 | 173 | (sig, kind) |
85aaf69f | 174 | } |
b7449926 XL |
175 | ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), |
176 | ty::FnPtr(sig) => { | |
fc512014 | 177 | let expected_sig = ExpectedSig { cause_span: None, sig }; |
0531ce1d XL |
178 | (Some(expected_sig), Some(ty::ClosureKind::Fn)) |
179 | } | |
c30ab7b3 | 180 | _ => (None, None), |
a7813a04 XL |
181 | } |
182 | } | |
c34b1796 | 183 | |
abe05a73 XL |
184 | fn deduce_expectations_from_obligations( |
185 | &self, | |
186 | expected_vid: ty::TyVid, | |
0531ce1d | 187 | ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) { |
dfeec247 XL |
188 | let expected_sig = |
189 | self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| { | |
abe05a73 XL |
190 | debug!( |
191 | "deduce_expectations_from_obligations: obligation.predicate={:?}", | |
192 | obligation.predicate | |
193 | ); | |
a7813a04 | 194 | |
5869c6ff XL |
195 | let bound_predicate = obligation.predicate.kind(); |
196 | if let ty::PredicateKind::Projection(proj_predicate) = | |
197 | obligation.predicate.kind().skip_binder() | |
f9f354fc | 198 | { |
a7813a04 XL |
199 | // Given a Projection predicate, we can potentially infer |
200 | // the complete signature. | |
3dfed10e XL |
201 | self.deduce_sig_from_projection( |
202 | Some(obligation.cause.span), | |
29967ef6 | 203 | bound_predicate.rebind(proj_predicate), |
3dfed10e | 204 | ) |
0bf4aa26 XL |
205 | } else { |
206 | None | |
a7813a04 | 207 | } |
0731742a | 208 | }); |
a7813a04 XL |
209 | |
210 | // Even if we can't infer the full signature, we may be able to | |
6a06907d | 211 | // infer the kind. This can occur when we elaborate a predicate |
a7813a04 XL |
212 | // like `F : Fn<A>`. Note that due to subtyping we could encounter |
213 | // many viable options, so pick the most restrictive. | |
dfeec247 XL |
214 | let expected_kind = self |
215 | .obligations_for_self_ty(expected_vid) | |
74b04a01 | 216 | .filter_map(|(tr, _)| self.tcx.fn_trait_kind_from_lang_item(tr.def_id())) |
dfeec247 | 217 | .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); |
a7813a04 XL |
218 | |
219 | (expected_sig, expected_kind) | |
c34b1796 | 220 | } |
85aaf69f | 221 | |
a7813a04 | 222 | /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce |
48663c56 | 223 | /// everything we need to know about a closure or generator. |
0531ce1d XL |
224 | /// |
225 | /// The `cause_span` should be the span that caused us to | |
226 | /// have this expected signature, or `None` if we can't readily | |
227 | /// know that. | |
abe05a73 XL |
228 | fn deduce_sig_from_projection( |
229 | &self, | |
0531ce1d | 230 | cause_span: Option<Span>, |
f9f354fc | 231 | projection: ty::PolyProjectionPredicate<'tcx>, |
0531ce1d | 232 | ) -> Option<ExpectedSig<'tcx>> { |
a7813a04 | 233 | let tcx = self.tcx; |
1a4d82fc | 234 | |
c30ab7b3 | 235 | debug!("deduce_sig_from_projection({:?})", projection); |
85aaf69f | 236 | |
6a06907d | 237 | let trait_def_id = projection.trait_def_id(tcx); |
1a4d82fc | 238 | |
6a06907d | 239 | let is_fn = tcx.fn_trait_kind_from_lang_item(trait_def_id).is_some(); |
3dfed10e | 240 | let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span); |
6a06907d | 241 | let is_gen = gen_trait == trait_def_id; |
48663c56 XL |
242 | if !is_fn && !is_gen { |
243 | debug!("deduce_sig_from_projection: not fn or generator"); | |
a7813a04 XL |
244 | return None; |
245 | } | |
1a4d82fc | 246 | |
48663c56 XL |
247 | if is_gen { |
248 | // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return` | |
249 | // associated item and not yield. | |
74b04a01 XL |
250 | let return_assoc_item = |
251 | self.tcx.associated_items(gen_trait).in_definition_order().nth(1).unwrap().def_id; | |
48663c56 XL |
252 | if return_assoc_item != projection.projection_def_id() { |
253 | debug!("deduce_sig_from_projection: not return assoc item of generator"); | |
254 | return None; | |
255 | } | |
256 | } | |
1a4d82fc | 257 | |
48663c56 | 258 | let input_tys = if is_fn { |
6a06907d | 259 | let arg_param_ty = projection.skip_binder().projection_ty.substs.type_at(1); |
fc512014 | 260 | let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty); |
48663c56 XL |
261 | debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty); |
262 | ||
1b1a35ee | 263 | match arg_param_ty.kind() { |
48663c56 XL |
264 | ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()).collect::<Vec<_>>(), |
265 | _ => return None, | |
266 | } | |
267 | } else { | |
74b04a01 XL |
268 | // Generators with a `()` resume type may be defined with 0 or 1 explicit arguments, |
269 | // else they must have exactly 1 argument. For now though, just give up in this case. | |
270 | return None; | |
a7813a04 | 271 | }; |
1a4d82fc | 272 | |
83c7162d | 273 | let ret_param_ty = projection.skip_binder().ty; |
fc512014 | 274 | let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty); |
48663c56 | 275 | debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty); |
1a4d82fc | 276 | |
fc512014 | 277 | let sig = projection.rebind(self.tcx.mk_fn_sig( |
48663c56 XL |
278 | input_tys.iter(), |
279 | &ret_param_ty, | |
8bb4bdeb XL |
280 | false, |
281 | hir::Unsafety::Normal, | |
abe05a73 | 282 | Abi::Rust, |
fc512014 | 283 | )); |
48663c56 | 284 | debug!("deduce_sig_from_projection: sig={:?}", sig); |
1a4d82fc | 285 | |
0531ce1d | 286 | Some(ExpectedSig { cause_span, sig }) |
a7813a04 | 287 | } |
1a4d82fc | 288 | |
abe05a73 XL |
289 | fn sig_of_closure( |
290 | &self, | |
291 | expr_def_id: DefId, | |
dfeec247 XL |
292 | decl: &hir::FnDecl<'_>, |
293 | body: &hir::Body<'_>, | |
0531ce1d | 294 | expected_sig: Option<ExpectedSig<'tcx>>, |
abe05a73 XL |
295 | ) -> ClosureSignatures<'tcx> { |
296 | if let Some(e) = expected_sig { | |
297 | self.sig_of_closure_with_expectation(expr_def_id, decl, body, e) | |
298 | } else { | |
299 | self.sig_of_closure_no_expectation(expr_def_id, decl, body) | |
300 | } | |
301 | } | |
302 | ||
303 | /// If there is no expected signature, then we will convert the | |
304 | /// types that the user gave into a signature. | |
305 | fn sig_of_closure_no_expectation( | |
306 | &self, | |
307 | expr_def_id: DefId, | |
dfeec247 XL |
308 | decl: &hir::FnDecl<'_>, |
309 | body: &hir::Body<'_>, | |
abe05a73 XL |
310 | ) -> ClosureSignatures<'tcx> { |
311 | debug!("sig_of_closure_no_expectation()"); | |
312 | ||
e74abb32 | 313 | let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); |
abe05a73 XL |
314 | |
315 | self.closure_sigs(expr_def_id, body, bound_sig) | |
316 | } | |
317 | ||
318 | /// Invoked to compute the signature of a closure expression. This | |
319 | /// combines any user-provided type annotations (e.g., `|x: u32| | |
320 | /// -> u32 { .. }`) with the expected signature. | |
321 | /// | |
322 | /// The approach is as follows: | |
323 | /// | |
324 | /// - Let `S` be the (higher-ranked) signature that we derive from the user's annotations. | |
325 | /// - Let `E` be the (higher-ranked) signature that we derive from the expectations, if any. | |
326 | /// - If we have no expectation `E`, then the signature of the closure is `S`. | |
327 | /// - Otherwise, the signature of the closure is E. Moreover: | |
328 | /// - Skolemize the late-bound regions in `E`, yielding `E'`. | |
329 | /// - Instantiate all the late-bound regions bound in the closure within `S` | |
330 | /// with fresh (existential) variables, yielding `S'` | |
331 | /// - Require that `E' = S'` | |
332 | /// - We could use some kind of subtyping relationship here, | |
333 | /// I imagine, but equality is easier and works fine for | |
334 | /// our purposes. | |
335 | /// | |
336 | /// The key intuition here is that the user's types must be valid | |
337 | /// from "the inside" of the closure, but the expectation | |
338 | /// ultimately drives the overall signature. | |
339 | /// | |
340 | /// # Examples | |
341 | /// | |
342 | /// ``` | |
343 | /// fn with_closure<F>(_: F) | |
344 | /// where F: Fn(&u32) -> &u32 { .. } | |
345 | /// | |
346 | /// with_closure(|x: &u32| { ... }) | |
347 | /// ``` | |
348 | /// | |
349 | /// Here: | |
350 | /// - E would be `fn(&u32) -> &u32`. | |
351 | /// - S would be `fn(&u32) -> | |
352 | /// - E' is `&'!0 u32 -> &'!0 u32` | |
353 | /// - S' is `&'?0 u32 -> ?T` | |
354 | /// | |
355 | /// S' can be unified with E' with `['?0 = '!0, ?T = &'!10 u32]`. | |
356 | /// | |
357 | /// # Arguments | |
358 | /// | |
9fa01778 | 359 | /// - `expr_def_id`: the `DefId` of the closure expression |
abe05a73 XL |
360 | /// - `decl`: the HIR declaration of the closure |
361 | /// - `body`: the body of the closure | |
362 | /// - `expected_sig`: the expected signature (if any). Note that | |
363 | /// this is missing a binder: that is, there may be late-bound | |
364 | /// regions with depth 1, which are bound then by the closure. | |
365 | fn sig_of_closure_with_expectation( | |
366 | &self, | |
367 | expr_def_id: DefId, | |
dfeec247 XL |
368 | decl: &hir::FnDecl<'_>, |
369 | body: &hir::Body<'_>, | |
0531ce1d | 370 | expected_sig: ExpectedSig<'tcx>, |
abe05a73 | 371 | ) -> ClosureSignatures<'tcx> { |
dfeec247 | 372 | debug!("sig_of_closure_with_expectation(expected_sig={:?})", expected_sig); |
abe05a73 XL |
373 | |
374 | // Watch out for some surprises and just ignore the | |
375 | // expectation if things don't see to match up with what we | |
376 | // expect. | |
fc512014 | 377 | if expected_sig.sig.c_variadic() != decl.c_variadic { |
abe05a73 | 378 | return self.sig_of_closure_no_expectation(expr_def_id, decl, body); |
fc512014 | 379 | } else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 { |
0531ce1d XL |
380 | return self.sig_of_closure_with_mismatched_number_of_arguments( |
381 | expr_def_id, | |
382 | decl, | |
383 | body, | |
384 | expected_sig, | |
385 | ); | |
abe05a73 XL |
386 | } |
387 | ||
388 | // Create a `PolyFnSig`. Note the oddity that late bound | |
389 | // regions appearing free in `expected_sig` are now bound up | |
390 | // in this binder we are creating. | |
fc512014 XL |
391 | assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST)); |
392 | let bound_sig = expected_sig.sig.map_bound(|sig| { | |
393 | self.tcx.mk_fn_sig( | |
394 | sig.inputs().iter().cloned(), | |
395 | sig.output(), | |
396 | sig.c_variadic, | |
397 | hir::Unsafety::Normal, | |
398 | Abi::RustCall, | |
399 | ) | |
400 | }); | |
abe05a73 XL |
401 | |
402 | // `deduce_expectations_from_expected_type` introduces | |
403 | // late-bound lifetimes defined elsewhere, which we now | |
404 | // anonymize away, so as not to confuse the user. | |
fc512014 | 405 | let bound_sig = self.tcx.anonymize_late_bound_regions(bound_sig); |
abe05a73 XL |
406 | |
407 | let closure_sigs = self.closure_sigs(expr_def_id, body, bound_sig); | |
408 | ||
409 | // Up till this point, we have ignored the annotations that the user | |
410 | // gave. This function will check that they unify successfully. | |
411 | // Along the way, it also writes out entries for types that the user | |
3dfed10e | 412 | // wrote into our typeck results, which are then later used by the privacy |
abe05a73 | 413 | // check. |
a1dfa0c6 | 414 | match self.check_supplied_sig_against_expectation(expr_def_id, decl, body, &closure_sigs) { |
abe05a73 XL |
415 | Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok), |
416 | Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body), | |
417 | } | |
418 | ||
419 | closure_sigs | |
420 | } | |
421 | ||
0531ce1d XL |
422 | fn sig_of_closure_with_mismatched_number_of_arguments( |
423 | &self, | |
424 | expr_def_id: DefId, | |
dfeec247 XL |
425 | decl: &hir::FnDecl<'_>, |
426 | body: &hir::Body<'_>, | |
0531ce1d XL |
427 | expected_sig: ExpectedSig<'tcx>, |
428 | ) -> ClosureSignatures<'tcx> { | |
ba9703b0 XL |
429 | let hir = self.tcx.hir(); |
430 | let expr_map_node = hir.get_if_local(expr_def_id).unwrap(); | |
0531ce1d XL |
431 | let expected_args: Vec<_> = expected_sig |
432 | .sig | |
fc512014 | 433 | .skip_binder() |
0531ce1d XL |
434 | .inputs() |
435 | .iter() | |
0bf4aa26 | 436 | .map(|ty| ArgKind::from_expected_ty(ty, None)) |
0531ce1d | 437 | .collect(); |
ba9703b0 XL |
438 | let (closure_span, found_args) = match self.get_fn_like_arguments(expr_map_node) { |
439 | Some((sp, args)) => (Some(sp), args), | |
440 | None => (None, Vec::new()), | |
441 | }; | |
442 | let expected_span = | |
443 | expected_sig.cause_span.unwrap_or_else(|| hir.span_if_local(expr_def_id).unwrap()); | |
0531ce1d XL |
444 | self.report_arg_count_mismatch( |
445 | expected_span, | |
ba9703b0 | 446 | closure_span, |
0531ce1d XL |
447 | expected_args, |
448 | found_args, | |
449 | true, | |
dfeec247 XL |
450 | ) |
451 | .emit(); | |
0531ce1d XL |
452 | |
453 | let error_sig = self.error_sig_of_closure(decl); | |
454 | ||
455 | self.closure_sigs(expr_def_id, body, error_sig) | |
456 | } | |
457 | ||
9fa01778 | 458 | /// Enforce the user's types against the expectation. See |
abe05a73 XL |
459 | /// `sig_of_closure_with_expectation` for details on the overall |
460 | /// strategy. | |
461 | fn check_supplied_sig_against_expectation( | |
462 | &self, | |
0bf4aa26 | 463 | expr_def_id: DefId, |
dfeec247 XL |
464 | decl: &hir::FnDecl<'_>, |
465 | body: &hir::Body<'_>, | |
abe05a73 XL |
466 | expected_sigs: &ClosureSignatures<'tcx>, |
467 | ) -> InferResult<'tcx, ()> { | |
468 | // Get the signature S that the user gave. | |
469 | // | |
470 | // (See comment on `sig_of_closure_with_expectation` for the | |
471 | // meaning of these letters.) | |
e74abb32 | 472 | let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); |
abe05a73 | 473 | |
dfeec247 | 474 | debug!("check_supplied_sig_against_expectation: supplied_sig={:?}", supplied_sig); |
abe05a73 XL |
475 | |
476 | // FIXME(#45727): As discussed in [this comment][c1], naively | |
477 | // forcing equality here actually results in suboptimal error | |
478 | // messages in some cases. For now, if there would have been | |
479 | // an obvious error, we fallback to declaring the type of the | |
480 | // closure to be the one the user gave, which allows other | |
481 | // error message code to trigger. | |
482 | // | |
483 | // However, I think [there is potential to do even better | |
484 | // here][c2], since in *this* code we have the precise span of | |
485 | // the type parameter in question in hand when we report the | |
486 | // error. | |
487 | // | |
488 | // [c1]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341089706 | |
489 | // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796 | |
490 | self.infcx.commit_if_ok(|_| { | |
491 | let mut all_obligations = vec![]; | |
492 | ||
0731742a | 493 | // The liberated version of this signature should be a subtype |
abe05a73 | 494 | // of the liberated form of the expectation. |
dfeec247 XL |
495 | for ((hir_ty, &supplied_ty), expected_ty) in decl |
496 | .inputs | |
497 | .iter() | |
f035d41b | 498 | .zip(supplied_sig.inputs().skip_binder()) // binder moved to (*) below |
dfeec247 | 499 | .zip(expected_sigs.liberated_sig.inputs()) |
abe05a73 XL |
500 | // `liberated_sig` is E'. |
501 | { | |
502 | // Instantiate (this part of..) S to S', i.e., with fresh variables. | |
a1dfa0c6 | 503 | let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars( |
abe05a73 XL |
504 | hir_ty.span, |
505 | LateBoundRegionConversionTime::FnCall, | |
fc512014 | 506 | supplied_sig.inputs().rebind(supplied_ty), |
abe05a73 XL |
507 | ); // recreated from (*) above |
508 | ||
509 | // Check that E' = S'. | |
e1599b0c | 510 | let cause = self.misc(hir_ty.span); |
dfeec247 XL |
511 | let InferOk { value: (), obligations } = |
512 | self.at(&cause, self.param_env).eq(*expected_ty, supplied_ty)?; | |
abe05a73 XL |
513 | all_obligations.extend(obligations); |
514 | } | |
515 | ||
a1dfa0c6 | 516 | let (supplied_output_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars( |
abe05a73 XL |
517 | decl.output.span(), |
518 | LateBoundRegionConversionTime::FnCall, | |
fc512014 | 519 | supplied_sig.output(), |
abe05a73 XL |
520 | ); |
521 | let cause = &self.misc(decl.output.span()); | |
dfeec247 XL |
522 | let InferOk { value: (), obligations } = self |
523 | .at(cause, self.param_env) | |
abe05a73 XL |
524 | .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?; |
525 | all_obligations.extend(obligations); | |
526 | ||
dfeec247 | 527 | Ok(InferOk { value: (), obligations: all_obligations }) |
abe05a73 XL |
528 | }) |
529 | } | |
530 | ||
531 | /// If there is no expected signature, then we will convert the | |
532 | /// types that the user gave into a signature. | |
0bf4aa26 XL |
533 | /// |
534 | /// Also, record this closure signature for later. | |
535 | fn supplied_sig_of_closure( | |
536 | &self, | |
537 | expr_def_id: DefId, | |
dfeec247 XL |
538 | decl: &hir::FnDecl<'_>, |
539 | body: &hir::Body<'_>, | |
0bf4aa26 | 540 | ) -> ty::PolyFnSig<'tcx> { |
dc9dc135 | 541 | let astconv: &dyn AstConv<'_> = self; |
abe05a73 | 542 | |
e74abb32 XL |
543 | debug!( |
544 | "supplied_sig_of_closure(decl={:?}, body.generator_kind={:?})", | |
dfeec247 | 545 | decl, body.generator_kind, |
e74abb32 XL |
546 | ); |
547 | ||
abe05a73 XL |
548 | // First, convert the types that the user supplied (if any). |
549 | let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); | |
550 | let supplied_return = match decl.output { | |
74b04a01 XL |
551 | hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(&output), |
552 | hir::FnRetTy::DefaultReturn(_) => match body.generator_kind { | |
e74abb32 XL |
553 | // In the case of the async block that we create for a function body, |
554 | // we expect the return type of the block to match that of the enclosing | |
555 | // function. | |
556 | Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => { | |
557 | debug!("supplied_sig_of_closure: closure is async fn body"); | |
dfeec247 XL |
558 | self.deduce_future_output_from_obligations(expr_def_id).unwrap_or_else(|| { |
559 | // AFAIK, deducing the future output | |
560 | // always succeeds *except* in error cases | |
561 | // like #65159. I'd like to return Error | |
562 | // here, but I can't because I can't | |
563 | // easily (and locally) prove that we | |
564 | // *have* reported an | |
565 | // error. --nikomatsakis | |
566 | astconv.ty_infer(None, decl.output.span()) | |
567 | }) | |
e74abb32 XL |
568 | } |
569 | ||
570 | _ => astconv.ty_infer(None, decl.output.span()), | |
dfeec247 | 571 | }, |
abe05a73 XL |
572 | }; |
573 | ||
83c7162d | 574 | let result = ty::Binder::bind(self.tcx.mk_fn_sig( |
abe05a73 XL |
575 | supplied_arguments, |
576 | supplied_return, | |
532ac7d7 | 577 | decl.c_variadic, |
abe05a73 XL |
578 | hir::Unsafety::Normal, |
579 | Abi::RustCall, | |
580 | )); | |
581 | ||
582 | debug!("supplied_sig_of_closure: result={:?}", result); | |
583 | ||
fc512014 | 584 | let c_result = self.inh.infcx.canonicalize_response(result); |
3dfed10e | 585 | self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); |
0bf4aa26 | 586 | |
abe05a73 XL |
587 | result |
588 | } | |
589 | ||
e74abb32 XL |
590 | /// Invoked when we are translating the generator that results |
591 | /// from desugaring an `async fn`. Returns the "sugared" return | |
592 | /// type of the `async fn` -- that is, the return type that the | |
593 | /// user specified. The "desugared" return type is a `impl | |
594 | /// Future<Output = T>`, so we do this by searching through the | |
595 | /// obligations to extract the `T`. | |
dfeec247 | 596 | fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty<'tcx>> { |
e74abb32 XL |
597 | debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id); |
598 | ||
dfeec247 XL |
599 | let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| { |
600 | span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn") | |
601 | }); | |
e74abb32 XL |
602 | |
603 | // In practice, the return type of the surrounding function is | |
604 | // always a (not yet resolved) inference variable, because it | |
605 | // is the hidden type for an `impl Trait` that we are going to | |
606 | // be inferring. | |
607 | let ret_ty = ret_coercion.borrow().expected_ty(); | |
608 | let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); | |
1b1a35ee | 609 | let ret_vid = match *ret_ty.kind() { |
e74abb32 | 610 | ty::Infer(ty::TyVar(ret_vid)) => ret_vid, |
29967ef6 | 611 | ty::Error(_) => return None, |
dfeec247 XL |
612 | _ => span_bug!( |
613 | self.tcx.def_span(expr_def_id), | |
614 | "async fn generator return type not an inference variable" | |
615 | ), | |
e74abb32 XL |
616 | }; |
617 | ||
618 | // Search for a pending obligation like | |
619 | // | |
620 | // `<R as Future>::Output = T` | |
621 | // | |
622 | // where R is the return type we are expecting. This type `T` | |
623 | // will be our output. | |
dfeec247 | 624 | let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| { |
5869c6ff XL |
625 | let bound_predicate = obligation.predicate.kind(); |
626 | if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() { | |
3dfed10e XL |
627 | self.deduce_future_output_from_projection( |
628 | obligation.cause.span, | |
fc512014 | 629 | bound_predicate.rebind(proj_predicate), |
3dfed10e | 630 | ) |
dfeec247 XL |
631 | } else { |
632 | None | |
633 | } | |
634 | }); | |
e74abb32 XL |
635 | |
636 | debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty); | |
637 | output_ty | |
638 | } | |
639 | ||
640 | /// Given a projection like | |
641 | /// | |
642 | /// `<X as Future>::Output = T` | |
643 | /// | |
644 | /// where `X` is some type that has no late-bound regions, returns | |
645 | /// `Some(T)`. If the projection is for some other trait, returns | |
646 | /// `None`. | |
647 | fn deduce_future_output_from_projection( | |
648 | &self, | |
649 | cause_span: Span, | |
f9f354fc | 650 | predicate: ty::PolyProjectionPredicate<'tcx>, |
e74abb32 XL |
651 | ) -> Option<Ty<'tcx>> { |
652 | debug!("deduce_future_output_from_projection(predicate={:?})", predicate); | |
653 | ||
654 | // We do not expect any bound regions in our predicate, so | |
655 | // skip past the bound vars. | |
656 | let predicate = match predicate.no_bound_vars() { | |
657 | Some(p) => p, | |
658 | None => { | |
659 | debug!("deduce_future_output_from_projection: has late-bound regions"); | |
660 | return None; | |
661 | } | |
662 | }; | |
663 | ||
664 | // Check that this is a projection from the `Future` trait. | |
6a06907d | 665 | let trait_def_id = predicate.projection_ty.trait_def_id(self.tcx); |
3dfed10e | 666 | let future_trait = self.tcx.require_lang_item(LangItem::Future, Some(cause_span)); |
6a06907d | 667 | if trait_def_id != future_trait { |
e74abb32 XL |
668 | debug!("deduce_future_output_from_projection: not a future"); |
669 | return None; | |
670 | } | |
671 | ||
672 | // The `Future` trait has only one associted item, `Output`, | |
673 | // so check that this is what we see. | |
74b04a01 XL |
674 | let output_assoc_item = |
675 | self.tcx.associated_items(future_trait).in_definition_order().next().unwrap().def_id; | |
e74abb32 XL |
676 | if output_assoc_item != predicate.projection_ty.item_def_id { |
677 | span_bug!( | |
678 | cause_span, | |
679 | "projecting associated item `{:?}` from future, which is not Output `{:?}`", | |
680 | predicate.projection_ty.item_def_id, | |
681 | output_assoc_item, | |
682 | ); | |
683 | } | |
684 | ||
685 | // Extract the type from the projection. Note that there can | |
686 | // be no bound variables in this type because the "self type" | |
687 | // does not have any regions in it. | |
fc512014 | 688 | let output_ty = self.resolve_vars_if_possible(predicate.ty); |
e74abb32 XL |
689 | debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); |
690 | Some(output_ty) | |
691 | } | |
692 | ||
0531ce1d XL |
693 | /// Converts the types that the user supplied, in case that doing |
694 | /// so should yield an error, but returns back a signature where | |
695 | /// all parameters are of type `TyErr`. | |
dfeec247 | 696 | fn error_sig_of_closure(&self, decl: &hir::FnDecl<'_>) -> ty::PolyFnSig<'tcx> { |
dc9dc135 | 697 | let astconv: &dyn AstConv<'_> = self; |
0531ce1d XL |
698 | |
699 | let supplied_arguments = decl.inputs.iter().map(|a| { | |
700 | // Convert the types that the user supplied (if any), but ignore them. | |
701 | astconv.ast_ty_to_ty(a); | |
f035d41b | 702 | self.tcx.ty_error() |
0531ce1d XL |
703 | }); |
704 | ||
74b04a01 | 705 | if let hir::FnRetTy::Return(ref output) = decl.output { |
0bf4aa26 | 706 | astconv.ast_ty_to_ty(&output); |
0531ce1d XL |
707 | } |
708 | ||
fc512014 | 709 | let result = ty::Binder::dummy(self.tcx.mk_fn_sig( |
0531ce1d | 710 | supplied_arguments, |
f035d41b | 711 | self.tcx.ty_error(), |
532ac7d7 | 712 | decl.c_variadic, |
0531ce1d XL |
713 | hir::Unsafety::Normal, |
714 | Abi::RustCall, | |
715 | )); | |
716 | ||
717 | debug!("supplied_sig_of_closure: result={:?}", result); | |
718 | ||
719 | result | |
720 | } | |
721 | ||
abe05a73 XL |
722 | fn closure_sigs( |
723 | &self, | |
724 | expr_def_id: DefId, | |
dfeec247 | 725 | body: &hir::Body<'_>, |
abe05a73 XL |
726 | bound_sig: ty::PolyFnSig<'tcx>, |
727 | ) -> ClosureSignatures<'tcx> { | |
fc512014 | 728 | let liberated_sig = self.tcx().liberate_late_bound_regions(expr_def_id, bound_sig); |
abe05a73 XL |
729 | let liberated_sig = self.inh.normalize_associated_types_in( |
730 | body.value.span, | |
9fa01778 | 731 | body.value.hir_id, |
abe05a73 | 732 | self.param_env, |
fc512014 | 733 | liberated_sig, |
abe05a73 | 734 | ); |
dfeec247 | 735 | ClosureSignatures { bound_sig, liberated_sig } |
abe05a73 | 736 | } |
1a4d82fc | 737 | } |