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).
10 use crate::type_check
::constraint_conversion
::ConstraintConversion
;
11 use rustc_index
::vec
::Idx
;
12 use rustc_infer
::infer
::LateBoundRegionConversionTime
;
13 use rustc_middle
::mir
::*;
14 use rustc_middle
::ty
::Ty
;
16 use rustc_span
::DUMMY_SP
;
17 use rustc_trait_selection
::traits
::query
::type_op
::{self, TypeOp}
;
18 use rustc_trait_selection
::traits
::query
::Fallible
;
19 use type_op
::TypeOpOutput
;
21 use crate::universal_regions
::UniversalRegions
;
23 use super::{Locations, TypeChecker}
;
25 impl<'a
, 'tcx
> TypeChecker
<'a
, 'tcx
> {
26 #[instrument(skip(self, body, universal_regions), level = "debug")]
27 pub(super) fn equate_inputs_and_outputs(
30 universal_regions
: &UniversalRegions
<'tcx
>,
31 normalized_inputs_and_output
: &[Ty
<'tcx
>],
33 let (&normalized_output_ty
, normalized_input_tys
) =
34 normalized_inputs_and_output
.split_last().unwrap();
36 debug
!(?normalized_output_ty
);
37 debug
!(?normalized_input_tys
);
39 let mir_def_id
= body
.source
.def_id().expect_local();
41 // If the user explicitly annotated the input types, extract
44 // e.g., `|x: FxHashMap<_, &'static u32>| ...`
45 let user_provided_sig
;
46 if !self.tcx().is_closure(mir_def_id
.to_def_id()) {
47 user_provided_sig
= None
;
49 let typeck_results
= self.tcx().typeck(mir_def_id
);
50 user_provided_sig
= typeck_results
.user_provided_sigs
.get(&mir_def_id
.to_def_id()).map(
51 |user_provided_poly_sig
| {
52 // Instantiate the canonicalized variables from
53 // user-provided signature (e.g., the `_` in the code
54 // above) with fresh variables.
55 let poly_sig
= self.instantiate_canonical_with_fresh_inference_vars(
57 &user_provided_poly_sig
,
60 // Replace the bound items in the fn sig with fresh
61 // variables, so that they represent the view from
62 // "inside" the closure.
64 .replace_bound_vars_with_fresh_vars(
66 LateBoundRegionConversionTime
::FnCall
,
74 debug
!(?normalized_input_tys
, ?body
.local_decls
);
76 // Equate expected input tys with those in the MIR.
77 for (argument_index
, &normalized_input_ty
) in normalized_input_tys
.iter().enumerate() {
78 if argument_index
+ 1 >= body
.local_decls
.len() {
81 .delay_span_bug(body
.span
, "found more normalized_input_ty than local_decls");
85 // In MIR, argument N is stored in local N+1.
86 let local
= Local
::new(argument_index
+ 1);
88 let mir_input_ty
= body
.local_decls
[local
].ty
;
90 let mir_input_span
= body
.local_decls
[local
].source_info
.span
;
91 self.equate_normalized_input_or_output(
98 if let Some(user_provided_sig
) = user_provided_sig
{
99 for (argument_index
, &user_provided_input_ty
) in
100 user_provided_sig
.inputs().iter().enumerate()
102 // In MIR, closures begin an implicit `self`, so
103 // argument N is stored in local N+2.
104 let local
= Local
::new(argument_index
+ 2);
105 let mir_input_ty
= body
.local_decls
[local
].ty
;
106 let mir_input_span
= body
.local_decls
[local
].source_info
.span
;
108 // If the user explicitly annotated the input types, enforce those.
109 let user_provided_input_ty
=
110 self.normalize(user_provided_input_ty
, Locations
::All(mir_input_span
));
112 self.equate_normalized_input_or_output(
113 user_provided_input_ty
,
121 "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
123 universal_regions
.yield_ty
126 // We will not have a universal_regions.yield_ty if we yield (by accident)
127 // outside of a generator and return an `impl Trait`, so emit a delay_span_bug
128 // because we don't want to panic in an assert here if we've already got errors.
129 if body
.yield_ty().is_some() != universal_regions
.yield_ty
.is_some() {
130 self.tcx().sess
.delay_span_bug(
133 "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
135 universal_regions
.yield_ty
,
140 if let (Some(mir_yield_ty
), Some(ur_yield_ty
)) =
141 (body
.yield_ty(), universal_regions
.yield_ty
)
143 let yield_span
= body
.local_decls
[RETURN_PLACE
].source_info
.span
;
144 self.equate_normalized_input_or_output(ur_yield_ty
, mir_yield_ty
, yield_span
);
147 // Return types are a bit more complex. They may contain opaque `impl Trait` types.
148 let mir_output_ty
= body
.local_decls
[RETURN_PLACE
].ty
;
149 let output_span
= body
.local_decls
[RETURN_PLACE
].source_info
.span
;
150 if let Err(terr
) = self.eq_opaque_type_and_type(
152 normalized_output_ty
,
153 Locations
::All(output_span
),
154 ConstraintCategory
::BoringNoLocation
,
159 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
160 normalized_output_ty
,
166 // If the user explicitly annotated the output types, enforce those.
167 // Note that this only happens for closures.
168 if let Some(user_provided_sig
) = user_provided_sig
{
169 let user_provided_output_ty
= user_provided_sig
.output();
170 let user_provided_output_ty
=
171 self.normalize(user_provided_output_ty
, Locations
::All(output_span
));
172 if let Err(err
) = self.eq_opaque_type_and_type(
174 user_provided_output_ty
,
175 Locations
::All(output_span
),
176 ConstraintCategory
::BoringNoLocation
,
181 "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
183 user_provided_output_ty
,
190 #[instrument(skip(self, span), level = "debug")]
191 fn equate_normalized_input_or_output(&mut self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>, span
: Span
) {
193 self.eq_types(a
, b
, Locations
::All(span
), ConstraintCategory
::BoringNoLocation
)
195 // FIXME(jackh726): This is a hack. It's somewhat like
196 // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
197 // like to normalize *before* inserting into `local_decls`, but
198 // doing so ends up causing some other trouble.
199 let b
= match self.normalize_and_add_constraints(b
) {
202 debug
!("equate_inputs_and_outputs: NoSolution");
207 // Note: if we have to introduce new placeholders during normalization above, then we won't have
208 // added those universes to the universe info, which we would want in `relate_tys`.
210 self.eq_types(a
, b
, Locations
::All(span
), ConstraintCategory
::BoringNoLocation
)
215 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
224 pub(crate) fn normalize_and_add_constraints(&mut self, t
: Ty
<'tcx
>) -> Fallible
<Ty
<'tcx
>> {
225 let TypeOpOutput { output: norm_ty, constraints, .. }
=
226 self.param_env
.and(type_op
::normalize
::Normalize
::new(t
)).fully_perform(self.infcx
)?
;
228 debug
!("{:?} normalized to {:?}", t
, norm_ty
);
230 for data
in constraints
.into_iter().collect
::<Vec
<_
>>() {
231 ConstraintConversion
::new(
233 &self.borrowck_context
.universal_regions
,
234 &self.region_bound_pairs
,
235 Some(self.implicit_region_bound
),
237 Locations
::All(DUMMY_SP
),
238 ConstraintCategory
::Internal
,
239 &mut self.borrowck_context
.constraints
,
241 .convert_all(&*data
);