]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/type_check/input_output.rs
bump version to 1.79.0+dfsg1-1~bpo12+pve2
[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
c620b35d
FG
10use std::assert_matches::assert_matches;
11
c0240ec0 12use itertools::Itertools;
c620b35d 13use rustc_hir as hir;
e8be2606 14use rustc_infer::infer::type_variable::TypeVariableOrigin;
c620b35d 15use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
ba9703b0 16use rustc_middle::mir::*;
9c376795 17use rustc_middle::ty::{self, Ty};
dfeec247 18use rustc_span::Span;
ff7c6d11 19
c620b35d
FG
20use crate::renumber::RegionCtxt;
21use crate::universal_regions::{DefiningTy, UniversalRegions};
60c5eb7d 22
83c7162d 23use super::{Locations, TypeChecker};
ff7c6d11 24
dc9dc135 25impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
9c376795 26 /// Check explicit closure signature annotation,
353b0b11 27 /// e.g., `|x: FxIndexMap<_, &'static u32>| ...`.
9c376795
FG
28 #[instrument(skip(self, body), level = "debug")]
29 pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) {
30 let mir_def_id = body.source.def_id().expect_local();
c620b35d
FG
31
32 if !self.tcx().is_closure_like(mir_def_id.to_def_id()) {
9c376795
FG
33 return;
34 }
c620b35d 35
9ffffee4 36 let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
9c376795
FG
37
38 // Instantiate the canonicalized variables from user-provided signature
39 // (e.g., the `_` in the code above) with fresh variables.
40 // Then replace the bound items in the fn sig with fresh variables,
41 // so that they represent the view from "inside" the closure.
e8be2606 42 let user_provided_sig = self.instantiate_canonical(body.span, &user_provided_poly_sig);
c620b35d 43 let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars(
9c376795 44 body.span,
4b012472 45 BoundRegionConversionTime::FnCall,
9c376795
FG
46 user_provided_sig,
47 );
48
c620b35d
FG
49 // FIXME(async_closures): It's kind of wacky that we must apply this
50 // transformation here, since we do the same thing in HIR typeck.
51 // Maybe we could just fix up the canonicalized signature during HIR typeck?
52 if let DefiningTy::CoroutineClosure(_, args) =
53 self.borrowck_context.universal_regions.defining_ty
54 {
55 assert_matches!(
56 self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)),
57 Some(hir::CoroutineKind::Desugared(
58 hir::CoroutineDesugaring::Async,
59 hir::CoroutineSource::Closure
60 )),
61 "this needs to be modified if we're lowering non-async closures"
62 );
63 // Make sure to use the args from `DefiningTy` so the right NLL region vids are prepopulated
64 // into the type.
65 let args = args.as_coroutine_closure();
66 let tupled_upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
67 self.tcx(),
68 args.kind(),
69 Ty::new_tup(self.tcx(), user_provided_sig.inputs()),
70 args.tupled_upvars_ty(),
71 args.coroutine_captures_by_ref_ty(),
72 self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(body.span), || {
73 RegionCtxt::Unknown
74 }),
75 );
76
77 let next_ty_var = || {
e8be2606 78 self.infcx.next_ty_var(TypeVariableOrigin { span: body.span, param_def_id: None })
c620b35d
FG
79 };
80 let output_ty = Ty::new_coroutine(
81 self.tcx(),
82 self.tcx().coroutine_for_closure(mir_def_id),
83 ty::CoroutineArgs::new(
84 self.tcx(),
85 ty::CoroutineArgsParts {
86 parent_args: args.parent_args(),
e8be2606 87 kind_ty: Ty::from_coroutine_closure_kind(self.tcx(), args.kind()),
c620b35d
FG
88 return_ty: user_provided_sig.output(),
89 tupled_upvars_ty,
90 // For async closures, none of these can be annotated, so just fill
91 // them with fresh ty vars.
92 resume_ty: next_ty_var(),
93 yield_ty: next_ty_var(),
94 witness: next_ty_var(),
95 },
96 )
97 .args,
98 );
99
100 user_provided_sig = self.tcx().mk_fn_sig(
101 user_provided_sig.inputs().iter().copied(),
102 output_ty,
103 user_provided_sig.c_variadic,
104 user_provided_sig.unsafety,
105 user_provided_sig.abi,
106 );
107 }
108
c0240ec0
FG
109 let is_coroutine_with_implicit_resume_ty = self.tcx().is_coroutine(mir_def_id.to_def_id())
110 && user_provided_sig.inputs().is_empty();
111
112 for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq(
113 // In MIR, closure args begin with an implicit `self`.
114 // Also, coroutines have a resume type which may be implicitly `()`.
115 body.args_iter()
116 .skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 })
117 .map(|local| &body.local_decls[local]),
9c376795
FG
118 ) {
119 self.ascribe_user_type_skip_wf(
120 arg_decl.ty,
121 ty::UserType::Ty(user_ty),
122 arg_decl.source_info.span,
123 );
124 }
125
126 // If the user explicitly annotated the output type, enforce it.
127 let output_decl = &body.local_decls[RETURN_PLACE];
128 self.ascribe_user_type_skip_wf(
129 output_decl.ty,
130 ty::UserType::Ty(user_provided_sig.output()),
131 output_decl.source_info.span,
132 );
133 }
134
c295e0f8 135 #[instrument(skip(self, body, universal_regions), level = "debug")]
ff7c6d11
XL
136 pub(super) fn equate_inputs_and_outputs(
137 &mut self,
dc9dc135 138 body: &Body<'tcx>,
ff7c6d11 139 universal_regions: &UniversalRegions<'tcx>,
8faf50e0 140 normalized_inputs_and_output: &[Ty<'tcx>],
ff7c6d11 141 ) {
8faf50e0
XL
142 let (&normalized_output_ty, normalized_input_tys) =
143 normalized_inputs_and_output.split_last().unwrap();
0bf4aa26 144
3c0e092e
XL
145 debug!(?normalized_output_ty);
146 debug!(?normalized_input_tys);
147
ff7c6d11 148 // Equate expected input tys with those in the MIR.
29967ef6 149 for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
cdc7bbd5
XL
150 if argument_index + 1 >= body.local_decls.len() {
151 self.tcx()
c0240ec0 152 .dcx()
c620b35d 153 .span_bug(body.span, "found more normalized_input_ty than local_decls");
cdc7bbd5 154 }
3c0e092e 155
0bf4aa26 156 // In MIR, argument N is stored in local N+1.
49aad941 157 let local = Local::from_usize(argument_index + 1);
0bf4aa26 158
dc9dc135 159 let mir_input_ty = body.local_decls[local].ty;
3c0e092e 160
dc9dc135 161 let mir_input_span = body.local_decls[local].source_info.span;
0bf4aa26
XL
162 self.equate_normalized_input_or_output(
163 normalized_input_ty,
164 mir_input_ty,
165 mir_input_span,
166 );
167 }
168
c0240ec0
FG
169 if let Some(mir_yield_ty) = body.yield_ty() {
170 let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
171 self.equate_normalized_input_or_output(
172 universal_regions.yield_ty.unwrap(),
173 mir_yield_ty,
174 yield_span,
a2a8927a
XL
175 );
176 }
177
c0240ec0 178 if let Some(mir_resume_ty) = body.resume_ty() {
dc9dc135 179 let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
c0240ec0
FG
180 self.equate_normalized_input_or_output(
181 universal_regions.resume_ty.unwrap(),
182 mir_resume_ty,
183 yield_span,
184 );
2c00a5a8
XL
185 }
186
416331ca 187 // Return types are a bit more complex. They may contain opaque `impl Trait` types.
dc9dc135
XL
188 let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
189 let output_span = body.local_decls[RETURN_PLACE].source_info.span;
fe692bf9 190 self.equate_normalized_input_or_output(normalized_output_ty, mir_output_ty, output_span);
ff7c6d11
XL
191 }
192
2b03887a 193 #[instrument(skip(self), level = "debug")]
0bf4aa26 194 fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
94222f64 195 if let Err(_) =
dfeec247
XL
196 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
197 {
94222f64
XL
198 // FIXME(jackh726): This is a hack. It's somewhat like
199 // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
200 // like to normalize *before* inserting into `local_decls`, but
201 // doing so ends up causing some other trouble.
2b03887a 202 let b = self.normalize(b, Locations::All(span));
3c0e092e 203
c295e0f8
XL
204 // Note: if we have to introduce new placeholders during normalization above, then we won't have
205 // added those universes to the universe info, which we would want in `relate_tys`.
94222f64
XL
206 if let Err(terr) =
207 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
208 {
209 span_mirbug!(
210 self,
211 Location::START,
212 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
213 a,
214 b,
215 terr
216 );
217 }
ff7c6d11
XL
218 }
219 }
220}