]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/type_check/input_output.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / 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
c295e0f8 10use rustc_index::vec::Idx;
74b04a01 11use rustc_infer::infer::LateBoundRegionConversionTime;
ba9703b0 12use rustc_middle::mir::*;
3c0e092e 13use rustc_middle::ty::Ty;
dfeec247 14use rustc_span::Span;
ff7c6d11 15
c295e0f8 16use crate::universal_regions::UniversalRegions;
60c5eb7d 17
83c7162d 18use super::{Locations, TypeChecker};
ff7c6d11 19
dc9dc135 20impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
c295e0f8 21 #[instrument(skip(self, body, universal_regions), level = "debug")]
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 30
3c0e092e
XL
31 debug!(?normalized_output_ty);
32 debug!(?normalized_input_tys);
33
29967ef6
XL
34 let mir_def_id = body.source.def_id().expect_local();
35
0bf4aa26
XL
36 // If the user explicitly annotated the input types, extract
37 // those.
38 //
0731742a 39 // e.g., `|x: FxHashMap<_, &'static u32>| ...`
0bf4aa26 40 let user_provided_sig;
29967ef6 41 if !self.tcx().is_closure(mir_def_id.to_def_id()) {
0bf4aa26
XL
42 user_provided_sig = None;
43 } else {
29967ef6 44 let typeck_results = self.tcx().typeck(mir_def_id);
5869c6ff
XL
45 user_provided_sig = typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id()).map(
46 |user_provided_poly_sig| {
29967ef6
XL
47 // Instantiate the canonicalized variables from
48 // user-provided signature (e.g., the `_` in the code
49 // above) with fresh variables.
94222f64 50 let poly_sig = self.instantiate_canonical_with_fresh_inference_vars(
29967ef6
XL
51 body.span,
52 &user_provided_poly_sig,
53 );
54
55 // Replace the bound items in the fn sig with fresh
56 // variables, so that they represent the view from
57 // "inside" the closure.
923072b8
FG
58 self.infcx.replace_bound_vars_with_fresh_vars(
59 body.span,
60 LateBoundRegionConversionTime::FnCall,
61 poly_sig,
62 )
5869c6ff
XL
63 },
64 );
65 }
ff7c6d11 66
c295e0f8 67 debug!(?normalized_input_tys, ?body.local_decls);
ba9703b0 68
ff7c6d11 69 // Equate expected input tys with those in the MIR.
29967ef6 70 for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
cdc7bbd5
XL
71 if argument_index + 1 >= body.local_decls.len() {
72 self.tcx()
73 .sess
74 .delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
75 break;
76 }
3c0e092e 77
0bf4aa26
XL
78 // In MIR, argument N is stored in local N+1.
79 let local = Local::new(argument_index + 1);
80
dc9dc135 81 let mir_input_ty = body.local_decls[local].ty;
3c0e092e 82
dc9dc135 83 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
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 {
29967ef6
XL
92 for (argument_index, &user_provided_input_ty) in
93 user_provided_sig.inputs().iter().enumerate()
0bf4aa26
XL
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);
dc9dc135
XL
98 let mir_input_ty = body.local_decls[local].ty;
99 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
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));
3c0e092e 104
0bf4aa26
XL
105 self.equate_normalized_input_or_output(
106 user_provided_input_ty,
107 mir_input_ty,
108 mir_input_span,
109 );
110 }
ff7c6d11
XL
111 }
112
a2a8927a
XL
113 debug!(
114 "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
115 body.yield_ty(),
116 universal_regions.yield_ty
117 );
118
119 // We will not have a universal_regions.yield_ty if we yield (by accident)
120 // outside of a generator and return an `impl Trait`, so emit a delay_span_bug
121 // because we don't want to panic in an assert here if we've already got errors.
122 if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
123 self.tcx().sess.delay_span_bug(
124 body.span,
125 &format!(
126 "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
127 body.yield_ty(),
128 universal_regions.yield_ty,
129 ),
130 );
131 }
132
133 if let (Some(mir_yield_ty), Some(ur_yield_ty)) =
134 (body.yield_ty(), universal_regions.yield_ty)
135 {
dc9dc135 136 let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
0bf4aa26 137 self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
2c00a5a8
XL
138 }
139
416331ca 140 // Return types are a bit more complex. They may contain opaque `impl Trait` types.
dc9dc135
XL
141 let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
142 let output_span = body.local_decls[RETURN_PLACE].source_info.span;
5e7ed085 143 if let Err(terr) = self.eq_types(
0bf4aa26 144 normalized_output_ty,
5e7ed085 145 mir_output_ty,
0bf4aa26
XL
146 Locations::All(output_span),
147 ConstraintCategory::BoringNoLocation,
148 ) {
149 span_mirbug!(
150 self,
151 Location::START,
152 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
153 normalized_output_ty,
154 mir_output_ty,
155 terr
156 );
157 };
158
159 // If the user explicitly annotated the output types, enforce those.
60c5eb7d 160 // Note that this only happens for closures.
0bf4aa26
XL
161 if let Some(user_provided_sig) = user_provided_sig {
162 let user_provided_output_ty = user_provided_sig.output();
163 let user_provided_output_ty =
164 self.normalize(user_provided_output_ty, Locations::All(output_span));
5e7ed085 165 if let Err(err) = self.eq_types(
60c5eb7d 166 user_provided_output_ty,
5e7ed085 167 mir_output_ty,
60c5eb7d 168 Locations::All(output_span),
dfeec247 169 ConstraintCategory::BoringNoLocation,
60c5eb7d
XL
170 ) {
171 span_mirbug!(
172 self,
173 Location::START,
174 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
175 mir_output_ty,
176 user_provided_output_ty,
177 err
178 );
179 }
ff7c6d11
XL
180 }
181 }
182
2b03887a 183 #[instrument(skip(self), level = "debug")]
0bf4aa26 184 fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
94222f64 185 if let Err(_) =
dfeec247
XL
186 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
187 {
94222f64
XL
188 // FIXME(jackh726): This is a hack. It's somewhat like
189 // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
190 // like to normalize *before* inserting into `local_decls`, but
191 // doing so ends up causing some other trouble.
2b03887a 192 let b = self.normalize(b, Locations::All(span));
3c0e092e 193
c295e0f8
XL
194 // Note: if we have to introduce new placeholders during normalization above, then we won't have
195 // added those universes to the universe info, which we would want in `relate_tys`.
94222f64
XL
196 if let Err(terr) =
197 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
198 {
199 span_mirbug!(
200 self,
201 Location::START,
202 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
203 a,
204 b,
205 terr
206 );
207 }
ff7c6d11
XL
208 }
209 }
210}