1818//! contain revealed `impl Trait` values).
1919
2020use borrow_check:: nll:: universal_regions:: UniversalRegions ;
21+ use rustc:: infer:: LateBoundRegionConversionTime ;
2122use rustc:: mir:: * ;
2223use rustc:: ty:: Ty ;
2324
@@ -36,9 +37,47 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
3637 let ( & normalized_output_ty, normalized_input_tys) =
3738 normalized_inputs_and_output. split_last ( ) . unwrap ( ) ;
3839
40+ // If the user explicitly annotated the input types, extract
41+ // those.
42+ //
43+ // e.g. `|x: FxHashMap<_, &'static u32>| ...`
44+ let user_provided_sig;
45+ if !self . tcx ( ) . is_closure ( self . mir_def_id ) {
46+ user_provided_sig = None ;
47+ } else {
48+ let typeck_tables = self . tcx ( ) . typeck_tables_of ( self . mir_def_id ) ;
49+ user_provided_sig = match typeck_tables. user_provided_sigs . get ( & self . mir_def_id ) {
50+ None => None ,
51+ Some ( user_provided_poly_sig) => {
52+ // Instantiate the canonicalized variables from
53+ // user-provided signature (e.g. the `_` in the code
54+ // above) with fresh variables.
55+ let ( poly_sig, _) = self . infcx . instantiate_canonical_with_fresh_inference_vars (
56+ mir. span ,
57+ & user_provided_poly_sig,
58+ ) ;
59+
60+ // Replace the bound items in the fn sig with fresh
61+ // variables, so that they represent the view from
62+ // "inside" the closure.
63+ Some (
64+ self . infcx
65+ . replace_late_bound_regions_with_fresh_var (
66+ mir. span ,
67+ LateBoundRegionConversionTime :: FnCall ,
68+ & poly_sig,
69+ )
70+ . 0 ,
71+ )
72+ }
73+ }
74+ } ;
75+
3976 // Equate expected input tys with those in the MIR.
40- let argument_locals = ( 1 ..) . map ( Local :: new) ;
41- for ( & normalized_input_ty, local) in normalized_input_tys. iter ( ) . zip ( argument_locals) {
77+ for ( & normalized_input_ty, argument_index) in normalized_input_tys. iter ( ) . zip ( 0 ..) {
78+ // In MIR, argument N is stored in local N+1.
79+ let local = Local :: new ( argument_index + 1 ) ;
80+
4281 debug ! (
4382 "equate_inputs_and_outputs: normalized_input_ty = {:?}" ,
4483 normalized_input_ty
@@ -53,6 +92,27 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
5392 ) ;
5493 }
5594
95+ if let Some ( user_provided_sig) = user_provided_sig {
96+ for ( & user_provided_input_ty, argument_index) in
97+ user_provided_sig. inputs ( ) . iter ( ) . zip ( 0 ..)
98+ {
99+ // In MIR, closures begin an implicit `self`, so
100+ // argument N is stored in local N+2.
101+ let local = Local :: new ( argument_index + 2 ) ;
102+ let mir_input_ty = mir. local_decls [ local] . ty ;
103+ let mir_input_span = mir. local_decls [ local] . source_info . span ;
104+
105+ // If the user explicitly annotated the input types, enforce those.
106+ let user_provided_input_ty =
107+ self . normalize ( user_provided_input_ty, Locations :: All ( mir_input_span) ) ;
108+ self . equate_normalized_input_or_output (
109+ user_provided_input_ty,
110+ mir_input_ty,
111+ mir_input_span,
112+ ) ;
113+ }
114+ }
115+
56116 assert ! (
57117 mir. yield_ty. is_some( ) && universal_regions. yield_ty. is_some( )
58118 || mir. yield_ty. is_none( ) && universal_regions. yield_ty. is_none( )
@@ -83,6 +143,18 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
83143 terr
84144 ) ;
85145 } ;
146+
147+ // If the user explicitly annotated the output types, enforce those.
148+ if let Some ( user_provided_sig) = user_provided_sig {
149+ let user_provided_output_ty = user_provided_sig. output ( ) ;
150+ let user_provided_output_ty =
151+ self . normalize ( user_provided_output_ty, Locations :: All ( output_span) ) ;
152+ self . equate_normalized_input_or_output (
153+ user_provided_output_ty,
154+ mir_output_ty,
155+ output_span,
156+ ) ;
157+ }
86158 }
87159
88160 fn equate_normalized_input_or_output ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > , span : Span ) {
0 commit comments