1313use super :: { check_fn, Expectation , FnCtxt } ;
1414
1515use astconv:: AstConv ;
16+ use rustc:: hir:: def_id:: DefId ;
17+ use rustc:: infer:: LateBoundRegionConversionTime ;
1618use rustc:: infer:: type_variable:: TypeVariableOrigin ;
1719use rustc:: ty:: { self , ToPolyTraitRef , Ty } ;
1820use rustc:: ty:: subst:: Substs ;
21+ use rustc:: ty:: TypeFoldable ;
1922use std:: cmp;
2023use std:: iter;
2124use syntax:: abi:: Abi ;
2225use rustc:: hir;
2326
27+ struct ClosureSignatures < ' tcx > {
28+ bound_sig : ty:: PolyFnSig < ' tcx > ,
29+ liberated_sig : ty:: FnSig < ' tcx > ,
30+ }
31+
2432impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
2533 pub fn check_expr_closure ( & self ,
2634 expr : & hir:: Expr ,
@@ -56,15 +64,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5664 expected_sig) ;
5765
5866 let expr_def_id = self . tcx . hir . local_def_id ( expr. id ) ;
59- let sig = self . ty_of_closure ( decl, expected_sig) ;
6067
61- debug ! ( "check_closure: ty_of_closure returns {:?}" , sig) ;
68+ let ClosureSignatures { bound_sig, liberated_sig } =
69+ self . sig_of_closure ( expr_def_id, decl, body, expected_sig) ;
6270
63- // `deduce_expectations_from_expected_type` introduces late-bound
64- // lifetimes defined elsewhere, which we need to anonymize away.
65- let sig = self . tcx . anonymize_late_bound_regions ( & sig) ;
71+ debug ! ( "check_closure: ty_of_closure returns {:?}" , liberated_sig) ;
6672
67- debug ! ( "check_closure: anonymized sig={:?}" , sig ) ;
73+ let interior = check_fn ( self , self . param_env , liberated_sig , decl , expr . id , body , true ) . 1 ;
6874
6975 // Create type variables (for now) to represent the transformed
7076 // types of upvars. These will be unified during the upvar
@@ -75,14 +81,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7581 |_, _| span_bug ! ( expr. span, "closure has region param" ) ,
7682 |_, _| self . infcx . next_ty_var ( TypeVariableOrigin :: TransformedUpvar ( expr. span ) )
7783 ) ;
78-
79- let fn_sig = self . liberate_late_bound_regions ( expr_def_id, & sig) ;
80- let fn_sig = self . inh . normalize_associated_types_in ( body. value . span ,
81- body. value . id ,
82- self . param_env ,
83- & fn_sig) ;
84-
85- let interior = check_fn ( self , self . param_env , fn_sig, decl, expr. id , body, true ) . 1 ;
84+ let closure_type = self . tcx . mk_closure ( expr_def_id, substs) ;
8685
8786 if let Some ( interior) = interior {
8887 let closure_substs = ty:: ClosureSubsts {
@@ -91,13 +90,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
9190 return self . tcx . mk_generator ( expr_def_id, closure_substs, interior) ;
9291 }
9392
94- let closure_type = self . tcx . mk_closure ( expr_def_id, substs) ;
95-
9693 debug ! ( "check_closure: expr.id={:?} closure_type={:?}" , expr. id, closure_type) ;
9794
9895 // Tuple up the arguments and insert the resulting function type into
9996 // the `closures` table.
100- let sig = sig . map_bound ( |sig| self . tcx . mk_fn_sig (
97+ let sig = bound_sig . map_bound ( |sig| self . tcx . mk_fn_sig (
10198 iter:: once ( self . tcx . intern_tup ( sig. inputs ( ) , false ) ) ,
10299 sig. output ( ) ,
103100 sig. variadic ,
@@ -271,71 +268,214 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
271268 }
272269 }
273270
271+ fn sig_of_closure ( & self ,
272+ expr_def_id : DefId ,
273+ decl : & hir:: FnDecl ,
274+ body : & hir:: Body ,
275+ expected_sig : Option < ty:: FnSig < ' tcx > > )
276+ -> ClosureSignatures < ' tcx >
277+ {
278+ if let Some ( e) = expected_sig {
279+ self . sig_of_closure_with_expectation ( expr_def_id, decl, body, e)
280+ } else {
281+ self . sig_of_closure_no_expectation ( expr_def_id, decl, body)
282+ }
283+ }
284+
285+ /// If there is no expected signature, then we will convert the
286+ /// types that the user gave into a signature.
287+ fn sig_of_closure_no_expectation ( & self ,
288+ expr_def_id : DefId ,
289+ decl : & hir:: FnDecl ,
290+ body : & hir:: Body )
291+ -> ClosureSignatures < ' tcx >
292+ {
293+ debug ! ( "sig_of_closure_no_expectation()" ) ;
294+
295+ let bound_sig = self . supplied_sig_of_closure ( decl) ;
296+
297+ self . closure_sigs ( expr_def_id, body, bound_sig)
298+ }
299+
274300 /// Invoked to compute the signature of a closure expression. This
275301 /// combines any user-provided type annotations (e.g., `|x: u32|
276302 /// -> u32 { .. }`) with the expected signature.
277303 ///
278- /// The arguments here are a bit odd-ball:
304+ /// The approach is as follows:
305+ ///
306+ /// - Let `S` be the (higher-ranked) signature that we derive from the user's annotations.
307+ /// - Let `E` be the (higher-ranked) signature that we derive from the expectations, if any.
308+ /// - If we have no expectation `E`, then the signature of the closure is `S`.
309+ /// - Otherwise, the signature of the closure is E. Moreover:
310+ /// - Skolemize the late-bound regions in `E`, yielding `E'`.
311+ /// - Instantiate all the late-bound regions bound in the closure within `S`
312+ /// with fresh (existential) variables, yielding `S'`
313+ /// - Require that `E' = S'`
314+ /// - We could use some kind of subtyping relationship here,
315+ /// I imagine, but equality is easier and works fine for
316+ /// our purposes.
317+ ///
318+ /// The key intuition here is that the user's types must be valid
319+ /// from "the inside" of the closure, but the expectation
320+ /// ultimately drives the overall signature.
321+ ///
322+ /// # Examples
323+ ///
324+ /// ```
325+ /// fn with_closure<F>(_: F)
326+ /// where F: Fn(&u32) -> &u32 { .. }
327+ ///
328+ /// with_closure(|x: &u32| { ... })
329+ /// ```
330+ ///
331+ /// Here:
332+ /// - E would be `fn(&u32) -> &u32`.
333+ /// - S would be `fn(&u32) ->
334+ /// - E' is `&'!0 u32 -> &'!0 u32`
335+ /// - S' is `&'?0 u32 -> ?T`
336+ ///
337+ /// S' can be unified with E' with `['?0 = '!0, ?T = &'!10 u32]`.
338+ ///
339+ /// # Arguments
279340 ///
341+ /// - `expr_def_id`: the def-id of the closure expression
280342 /// - `decl`: the HIR declaration of the closure
343+ /// - `body`: the body of the closure
281344 /// - `expected_sig`: the expected signature (if any). Note that
282345 /// this is missing a binder: that is, there may be late-bound
283346 /// regions with depth 1, which are bound then by the closure.
284- fn ty_of_closure ( & self ,
285- decl : & hir:: FnDecl ,
286- expected_sig : Option < ty:: FnSig < ' tcx > > )
287- -> ty:: PolyFnSig < ' tcx >
347+ fn sig_of_closure_with_expectation ( & self ,
348+ expr_def_id : DefId ,
349+ decl : & hir:: FnDecl ,
350+ body : & hir:: Body ,
351+ expected_sig : ty:: FnSig < ' tcx > )
352+ -> ClosureSignatures < ' tcx >
288353 {
289- let astconv: & AstConv = self ;
290-
291- debug ! ( "ty_of_closure(expected_sig={:?})" ,
292- expected_sig) ;
354+ debug ! ( "sig_of_closure_with_expectation(expected_sig={:?})" , expected_sig) ;
355+
356+ // Watch out for some surprises and just ignore the
357+ // expectation if things don't see to match up with what we
358+ // expect.
359+ if expected_sig. variadic != decl. variadic {
360+ return self . sig_of_closure_no_expectation ( expr_def_id, decl, body) ;
361+ } else if expected_sig. inputs_and_output . len ( ) != decl. inputs . len ( ) + 1 {
362+ // we could probably handle this case more gracefully
363+ return self . sig_of_closure_no_expectation ( expr_def_id, decl, body) ;
364+ }
293365
294- let input_tys = decl. inputs . iter ( ) . enumerate ( ) . map ( |( i, a) | {
295- let expected_arg_ty = expected_sig. as_ref ( ) . and_then ( |e| {
296- // no guarantee that the correct number of expected args
297- // were supplied
298- if i < e. inputs ( ) . len ( ) {
299- Some ( e. inputs ( ) [ i] )
300- } else {
301- None
302- }
303- } ) ;
366+ // Create a `PolyFnSig`. Note the oddity that late bound
367+ // regions appearing free in `expected_sig` are now bound up
368+ // in this binder we are creating.
369+ assert ! ( !expected_sig. has_regions_escaping_depth( 1 ) ) ;
370+ let bound_sig =
371+ ty:: Binder ( self . tcx . mk_fn_sig (
372+ expected_sig. inputs ( ) . iter ( ) . cloned ( ) ,
373+ expected_sig. output ( ) ,
374+ decl. variadic ,
375+ hir:: Unsafety :: Normal ,
376+ Abi :: RustCall ) ) ;
377+
378+ // `deduce_expectations_from_expected_type` introduces
379+ // late-bound lifetimes defined elsewhere, which we now
380+ // anonymize away, so as not to confuse the user.
381+ let bound_sig = self . tcx . anonymize_late_bound_regions ( & bound_sig) ;
382+
383+ let closure_sigs = self . closure_sigs ( expr_def_id, body, bound_sig) ;
384+
385+ // Up till this point, we have ignored the annotations that the user
386+ // gave. This function will check that they unify successfully.
387+ // Along the way, it also writes out entries for types that the user
388+ // wrote into our tables, which are then later used by the privacy
389+ // check.
390+ self . check_supplied_sig_against_expectation ( decl, & closure_sigs) ;
391+
392+ closure_sigs
393+ }
304394
305- let input_ty = astconv. ty_of_arg ( a, expected_arg_ty) ;
306- debug ! ( "ty_of_closure: i={} input_ty={:?} expected_arg_ty={:?}" ,
307- i, input_ty, expected_arg_ty) ;
395+ /// Enforce the user's types against the expectation. See
396+ /// `sig_of_closure_with_expectation` for details on the overall
397+ /// strategy.
398+ fn check_supplied_sig_against_expectation ( & self ,
399+ decl : & hir:: FnDecl ,
400+ expected_sigs : & ClosureSignatures < ' tcx > )
401+ {
402+ // Get the signature S that the user gave.
403+ //
404+ // (See comment on `sig_of_closure_with_expectation` for the
405+ // meaning of these letters.)
406+ let supplied_sig = self . supplied_sig_of_closure ( decl) ;
407+
408+ debug ! ( "check_supplied_sig_against_expectation: supplied_sig={:?}" ,
409+ supplied_sig) ;
410+
411+ // The liberated version of this signature should be be a subtype
412+ // of the liberated form of the expectation.
413+ for ( ( hir_ty, & supplied_ty) , expected_ty) in
414+ decl. inputs . iter ( )
415+ . zip ( * supplied_sig. inputs ( ) . skip_binder ( ) ) // binder moved to (*) below
416+ . zip ( expected_sigs. liberated_sig . inputs ( ) ) // `liberated_sig` is E'.
417+ {
418+ // Instantiate (this part of..) S to S', i.e., with fresh variables.
419+ let ( supplied_ty, _) = self . infcx . replace_late_bound_regions_with_fresh_var (
420+ hir_ty. span ,
421+ LateBoundRegionConversionTime :: FnCall ,
422+ & ty:: Binder ( supplied_ty) ) ; // recreated from (*) above
423+
424+ // Check that E' = S'.
425+ self . demand_eqtype ( hir_ty. span , expected_ty, supplied_ty) ;
426+ }
308427
309- input_ty
310- } ) ;
428+ let ( supplied_output_ty, _) = self . infcx . replace_late_bound_regions_with_fresh_var (
429+ decl. output . span ( ) ,
430+ LateBoundRegionConversionTime :: FnCall ,
431+ & supplied_sig. output ( ) ) ;
432+ self . demand_eqtype ( decl. output . span ( ) ,
433+ expected_sigs. liberated_sig . output ( ) ,
434+ supplied_output_ty) ;
435+ }
311436
312- let expected_ret_ty = expected_sig. as_ref ( ) . map ( |e| e. output ( ) ) ;
437+ /// If there is no expected signature, then we will convert the
438+ /// types that the user gave into a signature.
439+ fn supplied_sig_of_closure ( & self ,
440+ decl : & hir:: FnDecl )
441+ -> ty:: PolyFnSig < ' tcx >
442+ {
443+ let astconv: & AstConv = self ;
313444
314- let output_ty = match decl. output {
315- hir:: Return ( ref output) => {
316- if let ( & hir:: TyInfer , Some ( expected_ret_ty) ) = ( & output. node , expected_ret_ty) {
317- astconv. record_ty ( output. hir_id , expected_ret_ty, output. span ) ;
318- expected_ret_ty
319- } else {
320- astconv. ast_ty_to_ty ( & output)
321- }
322- }
323- hir:: DefaultReturn ( span) => {
324- if let Some ( expected_ret_ty) = expected_ret_ty {
325- expected_ret_ty
326- } else {
327- astconv. ty_infer ( span)
328- }
329- }
445+ // First, convert the types that the user supplied (if any).
446+ let supplied_arguments =
447+ decl. inputs
448+ . iter ( )
449+ . map ( |a| astconv. ast_ty_to_ty ( a) ) ;
450+ let supplied_return = match decl. output {
451+ hir:: Return ( ref output) => astconv. ast_ty_to_ty ( & output) ,
452+ hir:: DefaultReturn ( _) => astconv. ty_infer ( decl. output . span ( ) ) ,
330453 } ;
331454
332- debug ! ( "ty_of_closure: output_ty={:?}" , output_ty) ;
333-
334- ty:: Binder ( self . tcx . mk_fn_sig (
335- input_tys,
336- output_ty,
455+ let result = ty:: Binder ( self . tcx . mk_fn_sig (
456+ supplied_arguments,
457+ supplied_return,
337458 decl. variadic ,
338459 hir:: Unsafety :: Normal ,
339- Abi :: RustCall ) )
460+ Abi :: RustCall ) ) ;
461+
462+ debug ! ( "supplied_sig_of_closure: result={:?}" , result) ;
463+
464+ result
465+ }
466+
467+ fn closure_sigs ( & self ,
468+ expr_def_id : DefId ,
469+ body : & hir:: Body ,
470+ bound_sig : ty:: PolyFnSig < ' tcx > )
471+ -> ClosureSignatures < ' tcx >
472+ {
473+ let liberated_sig = self . liberate_late_bound_regions ( expr_def_id, & bound_sig) ;
474+ let liberated_sig = self . inh . normalize_associated_types_in ( body. value . span ,
475+ body. value . id ,
476+ self . param_env ,
477+ & liberated_sig) ;
478+ ClosureSignatures { bound_sig, liberated_sig }
340479 }
341480}
481+
0 commit comments