]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/borrow_check/type_check/input_output.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_mir / borrow_check / type_check / input_output.rs
CommitLineData
ff7c6d11
XL
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
416331ca 4//! are supplied to us before normalization and may contain opaque
ff7c6d11
XL
5//! `impl Trait` instances. In contrast, the input/output types found in
6//! the MIR (specifically, in the special local variables for the
0bf4aa26 7//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
ff7c6d11
XL
8//! contain revealed `impl Trait` values).
9
74b04a01 10use rustc_infer::infer::LateBoundRegionConversionTime;
ba9703b0
XL
11use rustc_middle::mir::*;
12use rustc_middle::ty::Ty;
ff7c6d11 13
e74abb32 14use rustc_index::vec::Idx;
dfeec247 15use rustc_span::Span;
ff7c6d11 16
60c5eb7d
XL
17use crate::borrow_check::universal_regions::UniversalRegions;
18
83c7162d 19use super::{Locations, TypeChecker};
ff7c6d11 20
dc9dc135 21impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ff7c6d11
XL
22 pub(super) fn equate_inputs_and_outputs(
23 &mut self,
dc9dc135 24 body: &Body<'tcx>,
ff7c6d11 25 universal_regions: &UniversalRegions<'tcx>,
8faf50e0 26 normalized_inputs_and_output: &[Ty<'tcx>],
ff7c6d11 27 ) {
8faf50e0
XL
28 let (&normalized_output_ty, normalized_input_tys) =
29 normalized_inputs_and_output.split_last().unwrap();
0bf4aa26
XL
30
31 // If the user explicitly annotated the input types, extract
32 // those.
33 //
0731742a 34 // e.g., `|x: FxHashMap<_, &'static u32>| ...`
0bf4aa26 35 let user_provided_sig;
f9f354fc 36 if !self.tcx().is_closure(self.mir_def_id.to_def_id()) {
0bf4aa26
XL
37 user_provided_sig = None;
38 } else {
3dfed10e 39 let typeck_results = self.tcx().typeck(self.mir_def_id);
f9f354fc 40 user_provided_sig =
3dfed10e 41 match typeck_results.user_provided_sigs.get(&self.mir_def_id.to_def_id()) {
f9f354fc
XL
42 None => None,
43 Some(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, _) =
48 self.infcx.instantiate_canonical_with_fresh_inference_vars(
dc9dc135 49 body.span,
f9f354fc
XL
50 &user_provided_poly_sig,
51 );
52
53 // Replace the bound items in the fn sig with fresh
54 // variables, so that they represent the view from
55 // "inside" the closure.
56 Some(
57 self.infcx
58 .replace_bound_vars_with_fresh_vars(
59 body.span,
60 LateBoundRegionConversionTime::FnCall,
61 &poly_sig,
62 )
63 .0,
64 )
65 }
0bf4aa26 66 }
0bf4aa26 67 };
ff7c6d11 68
ba9703b0
XL
69 debug!(
70 "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
71 normalized_input_tys, body.local_decls
72 );
73
ff7c6d11 74 // Equate expected input tys with those in the MIR.
0bf4aa26
XL
75 for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) {
76 // In MIR, argument N is stored in local N+1.
77 let local = Local::new(argument_index + 1);
78
dc9dc135
XL
79 let mir_input_ty = body.local_decls[local].ty;
80 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
81 self.equate_normalized_input_or_output(
82 normalized_input_ty,
83 mir_input_ty,
84 mir_input_span,
85 );
86 }
87
88 if let Some(user_provided_sig) = user_provided_sig {
89 for (&user_provided_input_ty, argument_index) in
90 user_provided_sig.inputs().iter().zip(0..)
91 {
92 // In MIR, closures begin an implicit `self`, so
93 // argument N is stored in local N+2.
94 let local = Local::new(argument_index + 2);
dc9dc135
XL
95 let mir_input_ty = body.local_decls[local].ty;
96 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
97
98 // If the user explicitly annotated the input types, enforce those.
99 let user_provided_input_ty =
100 self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
101 self.equate_normalized_input_or_output(
102 user_provided_input_ty,
103 mir_input_ty,
104 mir_input_span,
105 );
106 }
ff7c6d11
XL
107 }
108
2c00a5a8 109 assert!(
dc9dc135
XL
110 body.yield_ty.is_some() && universal_regions.yield_ty.is_some()
111 || body.yield_ty.is_none() && universal_regions.yield_ty.is_none()
83c7162d 112 );
dc9dc135 113 if let Some(mir_yield_ty) = body.yield_ty {
2c00a5a8 114 let ur_yield_ty = universal_regions.yield_ty.unwrap();
dc9dc135 115 let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
0bf4aa26 116 self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
2c00a5a8
XL
117 }
118
416331ca 119 // Return types are a bit more complex. They may contain opaque `impl Trait` types.
dc9dc135
XL
120 let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
121 let output_span = body.local_decls[RETURN_PLACE].source_info.span;
0bf4aa26
XL
122 if let Err(terr) = self.eq_opaque_type_and_type(
123 mir_output_ty,
124 normalized_output_ty,
f035d41b 125 self.mir_def_id,
0bf4aa26
XL
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.
60c5eb7d 140 // Note that this only happens for closures.
0bf4aa26
XL
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));
60c5eb7d 145 if let Err(err) = self.eq_opaque_type_and_type(
0bf4aa26 146 mir_output_ty,
60c5eb7d 147 user_provided_output_ty,
f035d41b 148 self.mir_def_id,
60c5eb7d 149 Locations::All(output_span),
dfeec247 150 ConstraintCategory::BoringNoLocation,
60c5eb7d
XL
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 }
ff7c6d11
XL
161 }
162 }
163
0bf4aa26 164 fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
ff7c6d11
XL
165 debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
166
dfeec247
XL
167 if let Err(terr) =
168 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
169 {
ff7c6d11
XL
170 span_mirbug!(
171 self,
83c7162d 172 Location::START,
ff7c6d11
XL
173 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
174 a,
175 b,
176 terr
177 );
178 }
179 }
180}