]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/type_check/input_output.rs
New upstream version 1.70.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::*;
9c376795 13use rustc_middle::ty::{self, 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> {
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}