18
18
//! contain revealed `impl Trait` values).
19
19
20
20
use borrow_check:: nll:: universal_regions:: UniversalRegions ;
21
+ use rustc:: infer:: LateBoundRegionConversionTime ;
21
22
use rustc:: mir:: * ;
22
23
use rustc:: ty:: Ty ;
23
24
@@ -36,9 +37,47 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
36
37
let ( & normalized_output_ty, normalized_input_tys) =
37
38
normalized_inputs_and_output. split_last ( ) . unwrap ( ) ;
38
39
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
+
39
76
// 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
+
42
81
debug ! (
43
82
"equate_inputs_and_outputs: normalized_input_ty = {:?}" ,
44
83
normalized_input_ty
@@ -53,6 +92,27 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
53
92
) ;
54
93
}
55
94
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
+
56
116
assert ! (
57
117
mir. yield_ty. is_some( ) && universal_regions. yield_ty. is_some( )
58
118
|| mir. yield_ty. is_none( ) && universal_regions. yield_ty. is_none( )
@@ -83,6 +143,18 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
83
143
terr
84
144
) ;
85
145
} ;
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
+ }
86
158
}
87
159
88
160
fn equate_normalized_input_or_output ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > , span : Span ) {
0 commit comments