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