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