]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
Allow combining -Cprofile-generate and -Cpanic=unwind when targeting
[rust.git] / compiler / rustc_mir / src / 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_infer::infer::LateBoundRegionConversionTime;
11 use rustc_middle::mir::*;
12 use rustc_middle::ty::Ty;
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         let mir_def_id = body.source.def_id().expect_local();
32
33         // If the user explicitly annotated the input types, extract
34         // those.
35         //
36         // e.g., `|x: FxHashMap<_, &'static u32>| ...`
37         let user_provided_sig;
38         if !self.tcx().is_closure(mir_def_id.to_def_id()) {
39             user_provided_sig = None;
40         } else {
41             let typeck_results = self.tcx().typeck(mir_def_id);
42             user_provided_sig = typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id()).map(
43                 |user_provided_poly_sig| {
44                     // Instantiate the canonicalized variables from
45                     // user-provided signature (e.g., the `_` in the code
46                     // above) with fresh variables.
47                     let (poly_sig, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
48                         body.span,
49                         &user_provided_poly_sig,
50                     );
51
52                     // Replace the bound items in the fn sig with fresh
53                     // variables, so that they represent the view from
54                     // "inside" the closure.
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         debug!(
67             "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
68             normalized_input_tys, body.local_decls
69         );
70
71         // Equate expected input tys with those in the MIR.
72         for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
73             if argument_index + 1 >= body.local_decls.len() {
74                 self.tcx()
75                     .sess
76                     .delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
77                 break;
78             }
79             // In MIR, argument N is stored in local N+1.
80             let local = Local::new(argument_index + 1);
81
82             let mir_input_ty = body.local_decls[local].ty;
83             let mir_input_span = body.local_decls[local].source_info.span;
84             self.equate_normalized_input_or_output(
85                 normalized_input_ty,
86                 mir_input_ty,
87                 mir_input_span,
88             );
89         }
90
91         if let Some(user_provided_sig) = user_provided_sig {
92             for (argument_index, &user_provided_input_ty) in
93                 user_provided_sig.inputs().iter().enumerate()
94             {
95                 // In MIR, closures begin an implicit `self`, so
96                 // argument N is stored in local N+2.
97                 let local = Local::new(argument_index + 2);
98                 let mir_input_ty = body.local_decls[local].ty;
99                 let mir_input_span = body.local_decls[local].source_info.span;
100
101                 // If the user explicitly annotated the input types, enforce those.
102                 let user_provided_input_ty =
103                     self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
104                 self.equate_normalized_input_or_output(
105                     user_provided_input_ty,
106                     mir_input_ty,
107                     mir_input_span,
108                 );
109             }
110         }
111
112         assert!(body.yield_ty().is_some() == universal_regions.yield_ty.is_some());
113         if let Some(mir_yield_ty) = body.yield_ty() {
114             let ur_yield_ty = universal_regions.yield_ty.unwrap();
115             let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
116             self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
117         }
118
119         // Return types are a bit more complex. They may contain opaque `impl Trait` types.
120         let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
121         let output_span = body.local_decls[RETURN_PLACE].source_info.span;
122         if let Err(terr) = self.eq_opaque_type_and_type(
123             mir_output_ty,
124             normalized_output_ty,
125             mir_def_id,
126             Locations::All(output_span),
127             ConstraintCategory::BoringNoLocation,
128         ) {
129             span_mirbug!(
130                 self,
131                 Location::START,
132                 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
133                 normalized_output_ty,
134                 mir_output_ty,
135                 terr
136             );
137         };
138
139         // If the user explicitly annotated the output types, enforce those.
140         // Note that this only happens for closures.
141         if let Some(user_provided_sig) = user_provided_sig {
142             let user_provided_output_ty = user_provided_sig.output();
143             let user_provided_output_ty =
144                 self.normalize(user_provided_output_ty, Locations::All(output_span));
145             if let Err(err) = self.eq_opaque_type_and_type(
146                 mir_output_ty,
147                 user_provided_output_ty,
148                 mir_def_id,
149                 Locations::All(output_span),
150                 ConstraintCategory::BoringNoLocation,
151             ) {
152                 span_mirbug!(
153                     self,
154                     Location::START,
155                     "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
156                     mir_output_ty,
157                     user_provided_output_ty,
158                     err
159                 );
160             }
161         }
162     }
163
164     fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
165         debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
166
167         if let Err(terr) =
168             self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
169         {
170             span_mirbug!(
171                 self,
172                 Location::START,
173                 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
174                 a,
175                 b,
176                 terr
177             );
178         }
179     }
180 }