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).
12 use rustc_infer::infer::LateBoundRegionConversionTime;
14 use rustc_index::vec::Idx;
17 use crate::borrow_check::universal_regions::UniversalRegions;
19 use super::{Locations, TypeChecker};
21 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22 pub(super) fn equate_inputs_and_outputs(
25 universal_regions: &UniversalRegions<'tcx>,
26 normalized_inputs_and_output: &[Ty<'tcx>],
28 let (&normalized_output_ty, normalized_input_tys) =
29 normalized_inputs_and_output.split_last().unwrap();
31 // If the user explicitly annotated the input types, extract
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;
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) {
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(
48 &user_provided_poly_sig,
51 // Replace the bound items in the fn sig with fresh
52 // variables, so that they represent the view from
53 // "inside" the closure.
56 .replace_bound_vars_with_fresh_vars(
58 LateBoundRegionConversionTime::FnCall,
68 "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
69 normalized_input_tys, body.local_decls
72 // Equate expected input tys with those in the MIR.
73 for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) {
74 // In MIR, argument N is stored in local N+1.
75 let local = Local::new(argument_index + 1);
77 let mir_input_ty = body.local_decls[local].ty;
78 let mir_input_span = body.local_decls[local].source_info.span;
79 self.equate_normalized_input_or_output(
86 if let Some(user_provided_sig) = user_provided_sig {
87 for (&user_provided_input_ty, argument_index) in
88 user_provided_sig.inputs().iter().zip(0..)
90 // In MIR, closures begin an implicit `self`, so
91 // argument N is stored in local N+2.
92 let local = Local::new(argument_index + 2);
93 let mir_input_ty = body.local_decls[local].ty;
94 let mir_input_span = body.local_decls[local].source_info.span;
96 // If the user explicitly annotated the input types, enforce those.
97 let user_provided_input_ty =
98 self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
99 self.equate_normalized_input_or_output(
100 user_provided_input_ty,
108 body.yield_ty.is_some() && universal_regions.yield_ty.is_some()
109 || body.yield_ty.is_none() && universal_regions.yield_ty.is_none()
111 if let Some(mir_yield_ty) = body.yield_ty {
112 let ur_yield_ty = universal_regions.yield_ty.unwrap();
113 let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
114 self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
117 // Return types are a bit more complex. They may contain opaque `impl Trait` types.
118 let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
119 let output_span = body.local_decls[RETURN_PLACE].source_info.span;
120 if let Err(terr) = self.eq_opaque_type_and_type(
122 normalized_output_ty,
124 Locations::All(output_span),
125 ConstraintCategory::BoringNoLocation,
130 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
131 normalized_output_ty,
137 // If the user explicitly annotated the output types, enforce those.
138 // Note that this only happens for closures.
139 if let Some(user_provided_sig) = user_provided_sig {
140 let user_provided_output_ty = user_provided_sig.output();
141 let user_provided_output_ty =
142 self.normalize(user_provided_output_ty, Locations::All(output_span));
143 if let Err(err) = self.eq_opaque_type_and_type(
145 user_provided_output_ty,
147 Locations::All(output_span),
148 ConstraintCategory::BoringNoLocation,
153 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
155 user_provided_output_ty,
162 fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
163 debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
166 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
171 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",