]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / compiler / rustc_mir / src / 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 30
29967ef6
XL
31 let mir_def_id = body.source.def_id().expect_local();
32
0bf4aa26
XL
33 // If the user explicitly annotated the input types, extract
34 // those.
35 //
0731742a 36 // e.g., `|x: FxHashMap<_, &'static u32>| ...`
0bf4aa26 37 let user_provided_sig;
29967ef6 38 if !self.tcx().is_closure(mir_def_id.to_def_id()) {
0bf4aa26
XL
39 user_provided_sig = None;
40 } else {
29967ef6 41 let typeck_results = self.tcx().typeck(mir_def_id);
5869c6ff
XL
42 user_provided_sig = typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id()).map(
43 |user_provided_poly_sig| {
29967ef6
XL
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.
5869c6ff
XL
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 }
ff7c6d11 65
ba9703b0
XL
66 debug!(
67 "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
68 normalized_input_tys, body.local_decls
69 );
70
ff7c6d11 71 // Equate expected input tys with those in the MIR.
29967ef6 72 for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
0bf4aa26
XL
73 // In MIR, argument N is stored in local N+1.
74 let local = Local::new(argument_index + 1);
75
dc9dc135
XL
76 let mir_input_ty = body.local_decls[local].ty;
77 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
78 self.equate_normalized_input_or_output(
79 normalized_input_ty,
80 mir_input_ty,
81 mir_input_span,
82 );
83 }
84
85 if let Some(user_provided_sig) = user_provided_sig {
29967ef6
XL
86 for (argument_index, &user_provided_input_ty) in
87 user_provided_sig.inputs().iter().enumerate()
0bf4aa26
XL
88 {
89 // In MIR, closures begin an implicit `self`, so
90 // argument N is stored in local N+2.
91 let local = Local::new(argument_index + 2);
dc9dc135
XL
92 let mir_input_ty = body.local_decls[local].ty;
93 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
94
95 // If the user explicitly annotated the input types, enforce those.
96 let user_provided_input_ty =
97 self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
98 self.equate_normalized_input_or_output(
99 user_provided_input_ty,
100 mir_input_ty,
101 mir_input_span,
102 );
103 }
ff7c6d11
XL
104 }
105
2c00a5a8 106 assert!(
dc9dc135
XL
107 body.yield_ty.is_some() && universal_regions.yield_ty.is_some()
108 || body.yield_ty.is_none() && universal_regions.yield_ty.is_none()
83c7162d 109 );
dc9dc135 110 if let Some(mir_yield_ty) = body.yield_ty {
2c00a5a8 111 let ur_yield_ty = universal_regions.yield_ty.unwrap();
dc9dc135 112 let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
0bf4aa26 113 self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
2c00a5a8
XL
114 }
115
416331ca 116 // Return types are a bit more complex. They may contain opaque `impl Trait` types.
dc9dc135
XL
117 let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
118 let output_span = body.local_decls[RETURN_PLACE].source_info.span;
0bf4aa26
XL
119 if let Err(terr) = self.eq_opaque_type_and_type(
120 mir_output_ty,
121 normalized_output_ty,
29967ef6 122 mir_def_id,
0bf4aa26
XL
123 Locations::All(output_span),
124 ConstraintCategory::BoringNoLocation,
125 ) {
126 span_mirbug!(
127 self,
128 Location::START,
129 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
130 normalized_output_ty,
131 mir_output_ty,
132 terr
133 );
134 };
135
136 // If the user explicitly annotated the output types, enforce those.
60c5eb7d 137 // Note that this only happens for closures.
0bf4aa26
XL
138 if let Some(user_provided_sig) = user_provided_sig {
139 let user_provided_output_ty = user_provided_sig.output();
140 let user_provided_output_ty =
141 self.normalize(user_provided_output_ty, Locations::All(output_span));
60c5eb7d 142 if let Err(err) = self.eq_opaque_type_and_type(
0bf4aa26 143 mir_output_ty,
60c5eb7d 144 user_provided_output_ty,
29967ef6 145 mir_def_id,
60c5eb7d 146 Locations::All(output_span),
dfeec247 147 ConstraintCategory::BoringNoLocation,
60c5eb7d
XL
148 ) {
149 span_mirbug!(
150 self,
151 Location::START,
152 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
153 mir_output_ty,
154 user_provided_output_ty,
155 err
156 );
157 }
ff7c6d11
XL
158 }
159 }
160
0bf4aa26 161 fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
ff7c6d11
XL
162 debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
163
dfeec247
XL
164 if let Err(terr) =
165 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
166 {
ff7c6d11
XL
167 span_mirbug!(
168 self,
83c7162d 169 Location::START,
ff7c6d11
XL
170 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
171 a,
172 b,
173 terr
174 );
175 }
176 }
177}