]>
Commit | Line | Data |
---|---|---|
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 | 10 | use rustc_index::vec::Idx; |
74b04a01 | 11 | use rustc_infer::infer::LateBoundRegionConversionTime; |
ba9703b0 | 12 | use rustc_middle::mir::*; |
9c376795 | 13 | use rustc_middle::ty::{self, Ty}; |
dfeec247 | 14 | use rustc_span::Span; |
ff7c6d11 | 15 | |
c295e0f8 | 16 | use crate::universal_regions::UniversalRegions; |
60c5eb7d | 17 | |
83c7162d | 18 | use super::{Locations, TypeChecker}; |
ff7c6d11 | 19 | |
dc9dc135 | 20 | impl<'a, 'tcx> TypeChecker<'a, 'tcx> { |
9c376795 | 21 | /// Check explicit closure signature annotation, |
353b0b11 | 22 | /// e.g., `|x: FxIndexMap<_, &'static u32>| ...`. |
9c376795 FG |
23 | #[instrument(skip(self, body), level = "debug")] |
24 | pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) { | |
25 | let mir_def_id = body.source.def_id().expect_local(); | |
26 | if !self.tcx().is_closure(mir_def_id.to_def_id()) { | |
27 | return; | |
28 | } | |
9ffffee4 | 29 | let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id); |
9c376795 FG |
30 | |
31 | // Instantiate the canonicalized variables from user-provided signature | |
32 | // (e.g., the `_` in the code above) with fresh variables. | |
33 | // Then replace the bound items in the fn sig with fresh variables, | |
34 | // so that they represent the view from "inside" the closure. | |
35 | let user_provided_sig = self | |
36 | .instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig); | |
9ffffee4 | 37 | let user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( |
9c376795 FG |
38 | body.span, |
39 | LateBoundRegionConversionTime::FnCall, | |
40 | user_provided_sig, | |
41 | ); | |
42 | ||
43 | for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip( | |
44 | // In MIR, closure args begin with an implicit `self`. Skip it! | |
45 | body.args_iter().skip(1).map(|local| &body.local_decls[local]), | |
46 | ) { | |
47 | self.ascribe_user_type_skip_wf( | |
48 | arg_decl.ty, | |
49 | ty::UserType::Ty(user_ty), | |
50 | arg_decl.source_info.span, | |
51 | ); | |
52 | } | |
53 | ||
54 | // If the user explicitly annotated the output type, enforce it. | |
55 | let output_decl = &body.local_decls[RETURN_PLACE]; | |
56 | self.ascribe_user_type_skip_wf( | |
57 | output_decl.ty, | |
58 | ty::UserType::Ty(user_provided_sig.output()), | |
59 | output_decl.source_info.span, | |
60 | ); | |
61 | } | |
62 | ||
c295e0f8 | 63 | #[instrument(skip(self, body, universal_regions), level = "debug")] |
ff7c6d11 XL |
64 | pub(super) fn equate_inputs_and_outputs( |
65 | &mut self, | |
dc9dc135 | 66 | body: &Body<'tcx>, |
ff7c6d11 | 67 | universal_regions: &UniversalRegions<'tcx>, |
8faf50e0 | 68 | normalized_inputs_and_output: &[Ty<'tcx>], |
ff7c6d11 | 69 | ) { |
8faf50e0 XL |
70 | let (&normalized_output_ty, normalized_input_tys) = |
71 | normalized_inputs_and_output.split_last().unwrap(); | |
0bf4aa26 | 72 | |
3c0e092e XL |
73 | debug!(?normalized_output_ty); |
74 | debug!(?normalized_input_tys); | |
75 | ||
ff7c6d11 | 76 | // Equate expected input tys with those in the MIR. |
29967ef6 | 77 | for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() { |
cdc7bbd5 XL |
78 | if argument_index + 1 >= body.local_decls.len() { |
79 | self.tcx() | |
80 | .sess | |
81 | .delay_span_bug(body.span, "found more normalized_input_ty than local_decls"); | |
82 | break; | |
83 | } | |
3c0e092e | 84 | |
0bf4aa26 XL |
85 | // In MIR, argument N is stored in local N+1. |
86 | let local = Local::new(argument_index + 1); | |
87 | ||
dc9dc135 | 88 | let mir_input_ty = body.local_decls[local].ty; |
3c0e092e | 89 | |
dc9dc135 | 90 | let mir_input_span = body.local_decls[local].source_info.span; |
0bf4aa26 XL |
91 | self.equate_normalized_input_or_output( |
92 | normalized_input_ty, | |
93 | mir_input_ty, | |
94 | mir_input_span, | |
95 | ); | |
96 | } | |
97 | ||
a2a8927a XL |
98 | debug!( |
99 | "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}", | |
100 | body.yield_ty(), | |
101 | universal_regions.yield_ty | |
102 | ); | |
103 | ||
104 | // We will not have a universal_regions.yield_ty if we yield (by accident) | |
105 | // outside of a generator and return an `impl Trait`, so emit a delay_span_bug | |
106 | // because we don't want to panic in an assert here if we've already got errors. | |
107 | if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() { | |
108 | self.tcx().sess.delay_span_bug( | |
109 | body.span, | |
110 | &format!( | |
111 | "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})", | |
112 | body.yield_ty(), | |
113 | universal_regions.yield_ty, | |
114 | ), | |
115 | ); | |
116 | } | |
117 | ||
118 | if let (Some(mir_yield_ty), Some(ur_yield_ty)) = | |
119 | (body.yield_ty(), universal_regions.yield_ty) | |
120 | { | |
dc9dc135 | 121 | let yield_span = body.local_decls[RETURN_PLACE].source_info.span; |
0bf4aa26 | 122 | self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span); |
2c00a5a8 XL |
123 | } |
124 | ||
416331ca | 125 | // Return types are a bit more complex. They may contain opaque `impl Trait` types. |
dc9dc135 XL |
126 | let mir_output_ty = body.local_decls[RETURN_PLACE].ty; |
127 | let output_span = body.local_decls[RETURN_PLACE].source_info.span; | |
5e7ed085 | 128 | if let Err(terr) = self.eq_types( |
0bf4aa26 | 129 | normalized_output_ty, |
5e7ed085 | 130 | mir_output_ty, |
0bf4aa26 XL |
131 | Locations::All(output_span), |
132 | ConstraintCategory::BoringNoLocation, | |
133 | ) { | |
134 | span_mirbug!( | |
135 | self, | |
136 | Location::START, | |
137 | "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`", | |
138 | normalized_output_ty, | |
139 | mir_output_ty, | |
140 | terr | |
141 | ); | |
142 | }; | |
ff7c6d11 XL |
143 | } |
144 | ||
2b03887a | 145 | #[instrument(skip(self), level = "debug")] |
0bf4aa26 | 146 | fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) { |
94222f64 | 147 | if let Err(_) = |
dfeec247 XL |
148 | self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation) |
149 | { | |
94222f64 XL |
150 | // FIXME(jackh726): This is a hack. It's somewhat like |
151 | // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd | |
152 | // like to normalize *before* inserting into `local_decls`, but | |
153 | // doing so ends up causing some other trouble. | |
2b03887a | 154 | let b = self.normalize(b, Locations::All(span)); |
3c0e092e | 155 | |
c295e0f8 XL |
156 | // Note: if we have to introduce new placeholders during normalization above, then we won't have |
157 | // added those universes to the universe info, which we would want in `relate_tys`. | |
94222f64 XL |
158 | if let Err(terr) = |
159 | self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation) | |
160 | { | |
161 | span_mirbug!( | |
162 | self, | |
163 | Location::START, | |
164 | "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`", | |
165 | a, | |
166 | b, | |
167 | terr | |
168 | ); | |
169 | } | |
ff7c6d11 XL |
170 | } |
171 | } | |
172 | } |