]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/type_check/input_output.rs
Update const_forget.rs
[rust.git] / src / librustc_mir / borrow_check / type_check / input_output.rs
1 //! This module contains code to equate the input/output types appearing
2 //! in the MIR with the expected input/output types from the function
3 //! signature. This requires a bit of processing, as the expected types
4 //! are supplied to us before normalization and may contain opaque
5 //! `impl Trait` instances. In contrast, the input/output types found in
6 //! the MIR (specifically, in the special local variables for the
7 //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
8 //! contain revealed `impl Trait` values).
9
10 use rustc::mir::*;
11 use rustc::ty::Ty;
12 use rustc_infer::infer::LateBoundRegionConversionTime;
13
14 use rustc_index::vec::Idx;
15 use rustc_span::Span;
16
17 use crate::borrow_check::universal_regions::UniversalRegions;
18
19 use super::{Locations, TypeChecker};
20
21 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22     pub(super) fn equate_inputs_and_outputs(
23         &mut self,
24         body: &Body<'tcx>,
25         universal_regions: &UniversalRegions<'tcx>,
26         normalized_inputs_and_output: &[Ty<'tcx>],
27     ) {
28         let (&normalized_output_ty, normalized_input_tys) =
29             normalized_inputs_and_output.split_last().unwrap();
30
31         // If the user explicitly annotated the input types, extract
32         // those.
33         //
34         // e.g., `|x: FxHashMap<_, &'static u32>| ...`
35         let user_provided_sig;
36         if !self.tcx().is_closure(self.mir_def_id) {
37             user_provided_sig = None;
38         } else {
39             let typeck_tables = self.tcx().typeck_tables_of(self.mir_def_id);
40             user_provided_sig = match typeck_tables.user_provided_sigs.get(&self.mir_def_id) {
41                 None => None,
42                 Some(user_provided_poly_sig) => {
43                     // Instantiate the canonicalized variables from
44                     // user-provided signature (e.g., the `_` in the code
45                     // above) with fresh variables.
46                     let (poly_sig, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
47                         body.span,
48                         &user_provided_poly_sig,
49                     );
50
51                     // Replace the bound items in the fn sig with fresh
52                     // variables, so that they represent the view from
53                     // "inside" the closure.
54                     Some(
55                         self.infcx
56                             .replace_bound_vars_with_fresh_vars(
57                                 body.span,
58                                 LateBoundRegionConversionTime::FnCall,
59                                 &poly_sig,
60                             )
61                             .0,
62                     )
63                 }
64             }
65         };
66
67         // Equate expected input tys with those in the MIR.
68         for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) {
69             // In MIR, argument N is stored in local N+1.
70             let local = Local::new(argument_index + 1);
71
72             debug!("equate_inputs_and_outputs: normalized_input_ty = {:?}", normalized_input_ty);
73
74             let mir_input_ty = body.local_decls[local].ty;
75             let mir_input_span = body.local_decls[local].source_info.span;
76             self.equate_normalized_input_or_output(
77                 normalized_input_ty,
78                 mir_input_ty,
79                 mir_input_span,
80             );
81         }
82
83         if let Some(user_provided_sig) = user_provided_sig {
84             for (&user_provided_input_ty, argument_index) in
85                 user_provided_sig.inputs().iter().zip(0..)
86             {
87                 // In MIR, closures begin an implicit `self`, so
88                 // argument N is stored in local N+2.
89                 let local = Local::new(argument_index + 2);
90                 let mir_input_ty = body.local_decls[local].ty;
91                 let mir_input_span = body.local_decls[local].source_info.span;
92
93                 // If the user explicitly annotated the input types, enforce those.
94                 let user_provided_input_ty =
95                     self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
96                 self.equate_normalized_input_or_output(
97                     user_provided_input_ty,
98                     mir_input_ty,
99                     mir_input_span,
100                 );
101             }
102         }
103
104         assert!(
105             body.yield_ty.is_some() && universal_regions.yield_ty.is_some()
106                 || body.yield_ty.is_none() && universal_regions.yield_ty.is_none()
107         );
108         if let Some(mir_yield_ty) = body.yield_ty {
109             let ur_yield_ty = universal_regions.yield_ty.unwrap();
110             let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
111             self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
112         }
113
114         // Return types are a bit more complex. They may contain opaque `impl Trait` types.
115         let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
116         let output_span = body.local_decls[RETURN_PLACE].source_info.span;
117         if let Err(terr) = self.eq_opaque_type_and_type(
118             mir_output_ty,
119             normalized_output_ty,
120             self.mir_def_id,
121             Locations::All(output_span),
122             ConstraintCategory::BoringNoLocation,
123         ) {
124             span_mirbug!(
125                 self,
126                 Location::START,
127                 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
128                 normalized_output_ty,
129                 mir_output_ty,
130                 terr
131             );
132         };
133
134         // If the user explicitly annotated the output types, enforce those.
135         // Note that this only happens for closures.
136         if let Some(user_provided_sig) = user_provided_sig {
137             let user_provided_output_ty = user_provided_sig.output();
138             let user_provided_output_ty =
139                 self.normalize(user_provided_output_ty, Locations::All(output_span));
140             if let Err(err) = self.eq_opaque_type_and_type(
141                 mir_output_ty,
142                 user_provided_output_ty,
143                 self.mir_def_id,
144                 Locations::All(output_span),
145                 ConstraintCategory::BoringNoLocation,
146             ) {
147                 span_mirbug!(
148                     self,
149                     Location::START,
150                     "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
151                     mir_output_ty,
152                     user_provided_output_ty,
153                     err
154                 );
155             }
156         }
157     }
158
159     fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
160         debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
161
162         if let Err(terr) =
163             self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
164         {
165             span_mirbug!(
166                 self,
167                 Location::START,
168                 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
169                 a,
170                 b,
171                 terr
172             );
173         }
174     }
175 }