]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir_typeck/src/writeback.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_hir_typeck / src / writeback.rs
CommitLineData
1a4d82fc
JJ
1// Type resolution: the phase that finds all the types in the AST with
2// unresolved type variables and replaces "ty_var" types with their
3// substitutions.
1a4d82fc 4
2b03887a 5use crate::FnCtxt;
064997fb
FG
6use hir::def_id::LocalDefId;
7use rustc_data_structures::fx::FxHashMap;
5e7ed085 8use rustc_errors::ErrorGuaranteed;
dfeec247 9use rustc_hir as hir;
5099ac24 10use rustc_hir::intravisit::{self, Visitor};
74b04a01
XL
11use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
12use rustc_infer::infer::InferCtxt;
6a06907d
XL
13use rustc_middle::hir::place::Place as HirPlace;
14use rustc_middle::mir::FakeReadCause;
ba9703b0 15use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
923072b8 16use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
9ffffee4 17use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
f2b60f7d 18use rustc_middle::ty::TypeckResults;
136023e0 19use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
dfeec247
XL
20use rustc_span::symbol::sym;
21use rustc_span::Span;
1a4d82fc 22
60c5eb7d 23use std::mem;
5e7ed085 24use std::ops::ControlFlow;
60c5eb7d 25
1a4d82fc 26///////////////////////////////////////////////////////////////////////////
32a655c1 27// Entry point
1a4d82fc 28
0731742a
XL
29// During type inference, partially inferred types are
30// represented using Type variables (ty::Infer). These don't appear in
3dfed10e
XL
31// the final TypeckResults since all of the types should have been
32// inferred once typeck is done.
0731742a 33// When type inference is running however, having to update the typeck
3dfed10e 34// typeck results every time a new type is inferred would be unreasonably slow,
0731742a
XL
35// so instead all of the replacement happens at the end in
36// resolve_type_vars_in_body, which creates a new TypeTables which
37// doesn't contain any inference types.
dc9dc135 38impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
dfeec247
XL
39 pub fn resolve_type_vars_in_body(
40 &self,
41 body: &'tcx hir::Body<'tcx>,
3dfed10e 42 ) -> &'tcx ty::TypeckResults<'tcx> {
9ffffee4 43 let item_def_id = self.tcx.hir().body_owner_def_id(body.id());
32a655c1 44
b7449926 45 // This attribute causes us to dump some writeback information
5099ac24 46 // in the form of errors, which is used for unit tests.
353b0b11 47 let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs);
b7449926
XL
48
49 let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs);
dfeec247 50 for param in body.params {
e1599b0c 51 wbcx.visit_node_id(param.pat.span, param.hir_id);
1a4d82fc 52 }
48663c56 53 // Type only exists for constants and statics, not functions.
5e7ed085 54 match self.tcx.hir().body_owner_kind(item_def_id) {
48663c56 55 hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
9ffffee4
FG
56 let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(item_def_id);
57 wbcx.visit_node_id(body.value.span, item_hir_id);
48663c56
XL
58 }
59 hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
60 }
32a655c1 61 wbcx.visit_body(body);
fc512014 62 wbcx.visit_min_capture_map();
136023e0 63 wbcx.eval_closure_size();
6a06907d 64 wbcx.visit_fake_reads_map();
a7813a04
XL
65 wbcx.visit_closures();
66 wbcx.visit_liberated_fn_sigs();
67 wbcx.visit_fru_field_types();
5e7ed085 68 wbcx.visit_opaque_types();
532ac7d7 69 wbcx.visit_coercion_casts();
0531ce1d 70 wbcx.visit_user_provided_tys();
0bf4aa26 71 wbcx.visit_user_provided_sigs();
e1599b0c 72 wbcx.visit_generator_interior_types();
8bb4bdeb 73
923072b8
FG
74 wbcx.typeck_results.rvalue_scopes =
75 mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
76
3dfed10e
XL
77 let used_trait_imports =
78 mem::take(&mut self.typeck_results.borrow_mut().used_trait_imports);
dfeec247 79 debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
3dfed10e 80 wbcx.typeck_results.used_trait_imports = used_trait_imports;
32a655c1 81
29967ef6
XL
82 wbcx.typeck_results.treat_byte_string_as_slice =
83 mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
84
487cf647
FG
85 if let Some(e) = self.tainted_by_errors() {
86 wbcx.typeck_results.tainted_by_errors = Some(e);
ba9703b0 87 }
8bb4bdeb 88
3dfed10e 89 debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
ff7c6d11 90
3dfed10e 91 self.tcx.arena.alloc(wbcx.typeck_results)
1a4d82fc 92 }
1a4d82fc
JJ
93}
94
95///////////////////////////////////////////////////////////////////////////
fc512014 96// The Writeback context. This visitor walks the HIR, checking the
3dfed10e 97// fn-specific typeck results to find references to types or regions. It
1a4d82fc 98// resolves those regions to remove inference variables and writes the
3dfed10e 99// final result back into the master typeck results in the tcx. Here and
1a4d82fc
JJ
100// there, it applies a few ad-hoc checks that were not convenient to
101// do elsewhere.
102
dc9dc135
XL
103struct WritebackCx<'cx, 'tcx> {
104 fcx: &'cx FnCtxt<'cx, 'tcx>,
5bcae85e 105
3dfed10e 106 typeck_results: ty::TypeckResults<'tcx>,
32a655c1 107
dfeec247 108 body: &'tcx hir::Body<'tcx>,
b7449926
XL
109
110 rustc_dump_user_substs: bool,
1a4d82fc
JJ
111}
112
dc9dc135 113impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
ff7c6d11 114 fn new(
dc9dc135 115 fcx: &'cx FnCtxt<'cx, 'tcx>,
dfeec247 116 body: &'tcx hir::Body<'tcx>,
b7449926 117 rustc_dump_user_substs: bool,
dc9dc135 118 ) -> WritebackCx<'cx, 'tcx> {
ba9703b0 119 let owner = body.id().hir_id.owner;
3b2f2976 120
3dfed10e
XL
121 WritebackCx {
122 fcx,
123 typeck_results: ty::TypeckResults::new(owner),
124 body,
125 rustc_dump_user_substs,
126 }
1a4d82fc
JJ
127 }
128
dc9dc135 129 fn tcx(&self) -> TyCtxt<'tcx> {
a7813a04 130 self.fcx.tcx
1a4d82fc 131 }
d9579d0f 132
3dfed10e
XL
133 fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
134 debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
5099ac24 135 assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
3dfed10e 136 self.typeck_results.node_types_mut().insert(hir_id, ty);
476ff2be
SL
137 }
138
d9579d0f
AL
139 // Hacky hack: During type-checking, we treat *all* operators
140 // as potentially overloaded. But then, during writeback, if
141 // we observe that something like `a+b` is (known to be)
142 // operating on scalars, we clear the overload.
dfeec247 143 fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr<'_>) {
e74abb32 144 match e.kind {
c295e0f8 145 hir::ExprKind::Unary(hir::UnOp::Neg | hir::UnOp::Not, inner) => {
3b2f2976 146 let inner_ty = self.fcx.node_ty(inner.hir_id);
fc512014 147 let inner_ty = self.fcx.resolve_vars_if_possible(inner_ty);
32a655c1
SL
148
149 if inner_ty.is_scalar() {
3dfed10e
XL
150 let mut typeck_results = self.fcx.typeck_results.borrow_mut();
151 typeck_results.type_dependent_defs_mut().remove(e.hir_id);
152 typeck_results.node_substs_mut().remove(e.hir_id);
32a655c1
SL
153 }
154 }
c295e0f8 155 hir::ExprKind::Binary(ref op, lhs, rhs) | hir::ExprKind::AssignOp(ref op, lhs, rhs) => {
3b2f2976 156 let lhs_ty = self.fcx.node_ty(lhs.hir_id);
fc512014 157 let lhs_ty = self.fcx.resolve_vars_if_possible(lhs_ty);
b039eaaf 158
3b2f2976 159 let rhs_ty = self.fcx.node_ty(rhs.hir_id);
fc512014 160 let rhs_ty = self.fcx.resolve_vars_if_possible(rhs_ty);
b039eaaf
SL
161
162 if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
3dfed10e
XL
163 let mut typeck_results = self.fcx.typeck_results.borrow_mut();
164 typeck_results.type_dependent_defs_mut().remove(e.hir_id);
165 typeck_results.node_substs_mut().remove(e.hir_id);
b039eaaf 166
e74abb32 167 match e.kind {
8faf50e0 168 hir::ExprKind::Binary(..) => {
54a0048b 169 if !op.node.is_by_value() {
3dfed10e 170 let mut adjustments = typeck_results.adjustments_mut();
f9f354fc
XL
171 if let Some(a) = adjustments.get_mut(lhs.hir_id) {
172 a.pop();
173 }
174 if let Some(a) = adjustments.get_mut(rhs.hir_id) {
175 a.pop();
176 }
b039eaaf 177 }
ff7c6d11 178 }
94222f64
XL
179 hir::ExprKind::AssignOp(..)
180 if let Some(a) = typeck_results.adjustments_mut().get_mut(lhs.hir_id) =>
181 {
182 a.pop();
ff7c6d11
XL
183 }
184 _ => {}
b039eaaf 185 }
d9579d0f
AL
186 }
187 }
ff7c6d11 188 _ => {}
d9579d0f
AL
189 }
190 }
2c00a5a8 191
f2b60f7d
FG
192 // (ouz-a 1005988): Normally `[T] : std::ops::Index<usize>` should be normalized
193 // into [T] but currently `Where` clause stops the normalization process for it,
194 // here we compare types of expr and base in a code without `Where` clause they would be equal
195 // if they are not we don't modify the expr, hence we bypass the ICE
196 fn is_builtin_index(
197 &mut self,
198 typeck_results: &TypeckResults<'tcx>,
199 e: &hir::Expr<'_>,
200 base_ty: Ty<'tcx>,
201 index_ty: Ty<'tcx>,
202 ) -> bool {
203 if let Some(elem_ty) = base_ty.builtin_index() {
204 let Some(exp_ty) = typeck_results.expr_ty_opt(e) else {return false;};
205 let resolved_exp_ty = self.resolve(exp_ty, &e.span);
206
207 elem_ty == resolved_exp_ty && index_ty == self.fcx.tcx.types.usize
208 } else {
209 false
210 }
211 }
212
2c00a5a8
XL
213 // Similar to operators, indexing is always assumed to be overloaded
214 // Here, correct cases where an indexing expression can be simplified
215 // to use builtin indexing because the index type is known to be
216 // usize-ish
dfeec247 217 fn fix_index_builtin_expr(&mut self, e: &hir::Expr<'_>) {
e74abb32 218 if let hir::ExprKind::Index(ref base, ref index) = e.kind {
3dfed10e 219 let mut typeck_results = self.fcx.typeck_results.borrow_mut();
2c00a5a8 220
e74abb32 221 // All valid indexing looks like this; might encounter non-valid indexes at this point.
fc512014 222 let base_ty = typeck_results
c295e0f8 223 .expr_ty_adjusted_opt(base)
fc512014 224 .map(|t| self.fcx.resolve_vars_if_possible(t).kind());
e74abb32
XL
225 if base_ty.is_none() {
226 // When encountering `return [0][0]` outside of a `fn` body we can encounter a base
227 // that isn't in the type table. We assume more relevant errors have already been
228 // emitted, so we delay an ICE if none have. (#64638)
229 self.tcx().sess.delay_span_bug(e.span, &format!("bad base: `{:?}`", base));
230 }
231 if let Some(ty::Ref(_, base_ty, _)) = base_ty {
c295e0f8 232 let index_ty = typeck_results.expr_ty_adjusted_opt(index).unwrap_or_else(|| {
e74abb32 233 // When encountering `return [0][0]` outside of a `fn` body we would attempt
5e7ed085 234 // to access an nonexistent index. We assume that more relevant errors will
e74abb32
XL
235 // already have been emitted, so we only gate on this with an ICE if no
236 // error has been emitted. (#64638)
f035d41b 237 self.fcx.tcx.ty_error_with_message(
e74abb32
XL
238 e.span,
239 &format!("bad index {:?} for base: `{:?}`", index, base),
f035d41b 240 )
e74abb32 241 });
fc512014 242 let index_ty = self.fcx.resolve_vars_if_possible(index_ty);
f2b60f7d 243 let resolved_base_ty = self.resolve(*base_ty, &base.span);
0bf4aa26 244
f2b60f7d 245 if self.is_builtin_index(&typeck_results, e, resolved_base_ty, index_ty) {
0bf4aa26 246 // Remove the method call record
3dfed10e
XL
247 typeck_results.type_dependent_defs_mut().remove(e.hir_id);
248 typeck_results.node_substs_mut().remove(e.hir_id);
0bf4aa26 249
3dfed10e 250 if let Some(a) = typeck_results.adjustments_mut().get_mut(base.hir_id) {
0bf4aa26 251 // Discard the need for a mutable borrow
ba9703b0
XL
252
253 // Extra adjustment made when indexing causes a drop
254 // of size information - we need to get rid of it
255 // Since this is "after" the other adjustment to be
256 // discarded, we do an extra `pop()`
257 if let Some(Adjustment {
258 kind: Adjust::Pointer(PointerCast::Unsize), ..
259 }) = a.pop()
260 {
261 // So the borrow discard actually happens here
262 a.pop();
0bf4aa26 263 }
f9f354fc 264 }
b7449926 265 }
2c00a5a8
XL
266 }
267 }
268 }
1a4d82fc
JJ
269}
270
271///////////////////////////////////////////////////////////////////////////
272// Impl of Visitor for Resolver
273//
274// This is the master code which walks the AST. It delegates most of
275// the heavy lifting to the generic visit and resolve functions
276// below. In general, a function is made into a `visitor` if it must
3dfed10e 277// traffic in node-ids or update typeck results in the type context etc.
1a4d82fc 278
dc9dc135 279impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
dfeec247 280 fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
32a655c1 281 self.fix_scalar_builtin_expr(e);
2c00a5a8 282 self.fix_index_builtin_expr(e);
c34b1796 283
e74abb32 284 match e.kind {
064997fb 285 hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
0731742a 286 let body = self.fcx.tcx.hir().body(body);
dfeec247 287 for param in body.params {
e1599b0c 288 self.visit_node_id(e.span, param.hir_id);
83c7162d 289 }
32a655c1 290
83c7162d
XL
291 self.visit_body(body);
292 }
dfeec247 293 hir::ExprKind::Struct(_, fields, _) => {
83c7162d 294 for field in fields {
532ac7d7 295 self.visit_field_id(field.hir_id);
83c7162d
XL
296 }
297 }
8faf50e0 298 hir::ExprKind::Field(..) => {
532ac7d7 299 self.visit_field_id(e.hir_id);
83c7162d 300 }
3c0e092e
XL
301 hir::ExprKind::ConstBlock(anon_const) => {
302 self.visit_node_id(e.span, anon_const.hir_id);
303
304 let body = self.tcx().hir().body(anon_const.body);
305 self.visit_body(body);
306 }
83c7162d 307 _ => {}
1a4d82fc
JJ
308 }
309
923072b8 310 self.visit_node_id(e.span, e.hir_id);
92a42be0 311 intravisit::walk_expr(self, e);
1a4d82fc
JJ
312 }
313
f2b60f7d
FG
314 fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
315 match &p.kind {
316 hir::GenericParamKind::Lifetime { .. } => {
317 // Nothing to write back here
318 }
319 hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => {
320 self.tcx().sess.delay_span_bug(p.span, format!("unexpected generic param: {p:?}"));
321 }
322 }
323 }
324
dfeec247 325 fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) {
3b2f2976 326 self.visit_node_id(b.span, b.hir_id);
92a42be0 327 intravisit::walk_block(self, b);
1a4d82fc
JJ
328 }
329
dfeec247 330 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
e74abb32 331 match p.kind {
3b2f2976 332 hir::PatKind::Binding(..) => {
3dfed10e
XL
333 let typeck_results = self.fcx.typeck_results.borrow();
334 if let Some(bm) =
335 typeck_results.extract_binding_mode(self.tcx().sess, p.hir_id, p.span)
336 {
337 self.typeck_results.pat_binding_modes_mut().insert(p.hir_id, bm);
8faf50e0 338 }
3b2f2976 339 }
dfeec247 340 hir::PatKind::Struct(_, fields, _) => {
83c7162d 341 for field in fields {
e1599b0c 342 self.visit_field_id(field.hir_id);
83c7162d
XL
343 }
344 }
3b2f2976
XL
345 _ => {}
346 };
347
ea8adc8c
XL
348 self.visit_pat_adjustments(p.span, p.hir_id);
349
3b2f2976 350 self.visit_node_id(p.span, p.hir_id);
92a42be0 351 intravisit::walk_pat(self, p);
1a4d82fc
JJ
352 }
353
dfeec247 354 fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
cc61c64b 355 intravisit::walk_local(self, l);
532ac7d7 356 let var_ty = self.fcx.local_ty(l.span, l.hir_id).decl_ty;
fc512014 357 let var_ty = self.resolve(var_ty, &l.span);
3dfed10e 358 self.write_ty_to_typeck_results(l.hir_id, var_ty);
1a4d82fc 359 }
ea8adc8c 360
dfeec247 361 fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
ea8adc8c 362 intravisit::walk_ty(self, hir_ty);
487cf647
FG
363 // If there are type checking errors, Type privacy pass will stop,
364 // so we may not get the type from hid_id, see #104513
365 if let Some(ty) = self.fcx.node_ty_opt(hir_ty.hir_id) {
366 let ty = self.resolve(ty, &hir_ty.span);
367 self.write_ty_to_typeck_results(hir_ty.hir_id, ty);
368 }
ea8adc8c 369 }
94222f64
XL
370
371 fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
372 intravisit::walk_inf(self, inf);
373 // Ignore cases where the inference is a const.
374 if let Some(ty) = self.fcx.node_ty_opt(inf.hir_id) {
375 let ty = self.resolve(ty, &inf.span);
376 self.write_ty_to_typeck_results(inf.hir_id, ty);
377 }
378 }
1a4d82fc
JJ
379}
380
dc9dc135 381impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
136023e0 382 fn eval_closure_size(&mut self) {
064997fb
FG
383 let mut res: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>> = Default::default();
384 for (&closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() {
385 let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
136023e0
XL
386
387 let data = self.resolve(*data, &closure_hir_id);
388
064997fb 389 res.insert(closure_def_id, data);
136023e0
XL
390 }
391
392 self.typeck_results.closure_size_eval = res;
393 }
fc512014
XL
394 fn visit_min_capture_map(&mut self) {
395 let mut min_captures_wb = ty::MinCaptureInformationMap::with_capacity_and_hasher(
396 self.fcx.typeck_results.borrow().closure_min_captures.len(),
397 Default::default(),
398 );
064997fb 399 for (&closure_def_id, root_min_captures) in
fc512014
XL
400 self.fcx.typeck_results.borrow().closure_min_captures.iter()
401 {
402 let mut root_var_map_wb = ty::RootVariableMinCaptureList::with_capacity_and_hasher(
403 root_min_captures.len(),
404 Default::default(),
405 );
406 for (var_hir_id, min_list) in root_min_captures.iter() {
407 let min_list_wb = min_list
408 .iter()
409 .map(|captured_place| {
6a06907d 410 let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| {
064997fb 411 self.tcx().hir().local_def_id_to_hir_id(closure_def_id)
6a06907d 412 });
fc512014
XL
413
414 self.resolve(captured_place.clone(), &locatable)
415 })
416 .collect();
417 root_var_map_wb.insert(*var_hir_id, min_list_wb);
418 }
064997fb 419 min_captures_wb.insert(closure_def_id, root_var_map_wb);
fc512014
XL
420 }
421
422 self.typeck_results.closure_min_captures = min_captures_wb;
423 }
424
6a06907d
XL
425 fn visit_fake_reads_map(&mut self) {
426 let mut resolved_closure_fake_reads: FxHashMap<
064997fb 427 LocalDefId,
6a06907d
XL
428 Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>,
429 > = Default::default();
064997fb 430 for (&closure_def_id, fake_reads) in
6a06907d
XL
431 self.fcx.typeck_results.borrow().closure_fake_reads.iter()
432 {
433 let mut resolved_fake_reads = Vec::<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>::new();
434 for (place, cause, hir_id) in fake_reads.iter() {
064997fb 435 let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
6a06907d
XL
436
437 let resolved_fake_read = self.resolve(place.clone(), &locatable);
438 resolved_fake_reads.push((resolved_fake_read, *cause, *hir_id));
439 }
064997fb 440 resolved_closure_fake_reads.insert(closure_def_id, resolved_fake_reads);
1a4d82fc 441 }
6a06907d 442 self.typeck_results.closure_fake_reads = resolved_closure_fake_reads;
1a4d82fc
JJ
443 }
444
8bb4bdeb 445 fn visit_closures(&mut self) {
3dfed10e
XL
446 let fcx_typeck_results = self.fcx.typeck_results.borrow();
447 assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
448 let common_hir_owner = fcx_typeck_results.hir_owner;
3b2f2976 449
9c376795
FG
450 let fcx_closure_kind_origins =
451 fcx_typeck_results.closure_kind_origins().items_in_stable_order();
452
453 for (local_id, origin) in fcx_closure_kind_origins {
454 let hir_id = hir::HirId { owner: common_hir_owner, local_id };
5869c6ff
XL
455 let place_span = origin.0;
456 let place = self.resolve(origin.1.clone(), &place_span);
457 self.typeck_results.closure_kind_origins_mut().insert(hir_id, (place_span, place));
1a4d82fc
JJ
458 }
459 }
460
532ac7d7 461 fn visit_coercion_casts(&mut self) {
3dfed10e 462 let fcx_typeck_results = self.fcx.typeck_results.borrow();
9c376795 463
3dfed10e 464 assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
3b2f2976 465
9c376795 466 let fcx_coercion_casts = fcx_typeck_results.coercion_casts().to_sorted_stable_ord();
532ac7d7 467 for local_id in fcx_coercion_casts {
9c376795 468 self.typeck_results.set_coercion_cast(local_id);
3b2f2976 469 }
8bb4bdeb
XL
470 }
471
0531ce1d 472 fn visit_user_provided_tys(&mut self) {
3dfed10e
XL
473 let fcx_typeck_results = self.fcx.typeck_results.borrow();
474 assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
475 let common_hir_owner = fcx_typeck_results.hir_owner;
0531ce1d 476
9c376795
FG
477 if self.rustc_dump_user_substs {
478 let sorted_user_provided_types =
479 fcx_typeck_results.user_provided_types().items_in_stable_order();
0531ce1d 480
9c376795
FG
481 let mut errors_buffer = Vec::new();
482 for (local_id, c_ty) in sorted_user_provided_types {
483 let hir_id = hir::HirId { owner: common_hir_owner, local_id };
0731742a 484
9c376795 485 if let ty::UserType::TypeOf(_, user_substs) = c_ty.value {
0731742a 486 // This is a unit-testing mechanism.
dc9dc135 487 let span = self.tcx().hir().span(hir_id);
0731742a
XL
488 // We need to buffer the errors in order to guarantee a consistent
489 // order when emitting them.
dfeec247
XL
490 let err = self
491 .tcx()
492 .sess
493 .struct_span_err(span, &format!("user substs: {:?}", user_substs));
0731742a
XL
494 err.buffer(&mut errors_buffer);
495 }
496 }
0731742a 497
9c376795
FG
498 if !errors_buffer.is_empty() {
499 errors_buffer.sort_by_key(|diag| diag.span.primary_span());
500 for mut diag in errors_buffer {
501 self.tcx().sess.diagnostic().emit_diagnostic(&mut diag);
502 }
0731742a 503 }
0531ce1d 504 }
9c376795
FG
505
506 self.typeck_results.user_provided_types_mut().extend(
507 fcx_typeck_results.user_provided_types().items().map(|(local_id, c_ty)| {
508 let hir_id = hir::HirId { owner: common_hir_owner, local_id };
509
510 if cfg!(debug_assertions) && c_ty.needs_infer() {
511 span_bug!(
512 hir_id.to_span(self.fcx.tcx),
513 "writeback: `{:?}` has inference variables",
514 c_ty
515 );
516 };
517
518 (hir_id, *c_ty)
519 }),
520 );
0531ce1d
XL
521 }
522
0bf4aa26 523 fn visit_user_provided_sigs(&mut self) {
3dfed10e
XL
524 let fcx_typeck_results = self.fcx.typeck_results.borrow();
525 assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
0bf4aa26 526
9c376795
FG
527 self.typeck_results.user_provided_sigs.extend(
528 fcx_typeck_results.user_provided_sigs.items().map(|(&def_id, c_sig)| {
529 if cfg!(debug_assertions) && c_sig.needs_infer() {
530 span_bug!(
531 self.fcx.tcx.def_span(def_id),
532 "writeback: `{:?}` has inference variables",
533 c_sig
534 );
535 };
536
537 (def_id, *c_sig)
538 }),
539 );
0bf4aa26
XL
540 }
541
e1599b0c 542 fn visit_generator_interior_types(&mut self) {
3dfed10e
XL
543 let fcx_typeck_results = self.fcx.typeck_results.borrow();
544 assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
545 self.typeck_results.generator_interior_types =
546 fcx_typeck_results.generator_interior_types.clone();
9ffffee4
FG
547 for (&expr_def_id, predicates) in fcx_typeck_results.generator_interior_predicates.iter() {
548 let predicates = self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id));
549 self.typeck_results.generator_interior_predicates.insert(expr_def_id, predicates);
550 }
e1599b0c
XL
551 }
552
5e7ed085
FG
553 #[instrument(skip(self), level = "debug")]
554 fn visit_opaque_types(&mut self) {
9c376795 555 let opaque_types = self.fcx.infcx.take_opaque_types();
5e7ed085 556 for (opaque_type_key, decl) in opaque_types {
2b03887a
FG
557 let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
558 let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
559
560 struct RecursionChecker {
561 def_id: LocalDefId,
562 }
9ffffee4 563 impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for RecursionChecker {
2b03887a
FG
564 type BreakTy = ();
565 fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
9c376795 566 if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
2b03887a
FG
567 if def_id == self.def_id.to_def_id() {
568 return ControlFlow::Break(());
5e7ed085 569 }
e74abb32 570 }
2b03887a 571 t.super_visit_with(self)
b7449926 572 }
2b03887a
FG
573 }
574 if hidden_type
575 .visit_with(&mut RecursionChecker { def_id: opaque_type_key.def_id })
576 .is_break()
577 {
578 continue;
579 }
580
581 let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
582 opaque_type_key,
583 self.fcx.infcx.tcx,
584 true,
2b03887a
FG
585 );
586
5e7ed085 587 self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type);
5bcae85e
SL
588 }
589 }
590
532ac7d7 591 fn visit_field_id(&mut self, hir_id: hir::HirId) {
3dfed10e
XL
592 if let Some(index) = self.fcx.typeck_results.borrow_mut().field_indices_mut().remove(hir_id)
593 {
594 self.typeck_results.field_indices_mut().insert(hir_id, index);
83c7162d
XL
595 }
596 }
597
c295e0f8 598 #[instrument(skip(self, span), level = "debug")]
3b2f2976 599 fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
b7449926 600 // Export associated path extensions and method resolutions.
3dfed10e
XL
601 if let Some(def) =
602 self.fcx.typeck_results.borrow_mut().type_dependent_defs_mut().remove(hir_id)
603 {
604 self.typeck_results.type_dependent_defs_mut().insert(hir_id, def);
476ff2be
SL
605 }
606
cc61c64b 607 // Resolve any borrowings for the node with id `node_id`
3b2f2976 608 self.visit_adjustments(span, hir_id);
1a4d82fc 609
cc61c64b 610 // Resolve the type of the node with id `node_id`
3b2f2976 611 let n_ty = self.fcx.node_ty(hir_id);
fc512014 612 let n_ty = self.resolve(n_ty, &span);
3dfed10e 613 self.write_ty_to_typeck_results(hir_id, n_ty);
c295e0f8 614 debug!(?n_ty);
1a4d82fc
JJ
615
616 // Resolve any substitutions
3dfed10e 617 if let Some(substs) = self.fcx.typeck_results.borrow().node_substs_opt(hir_id) {
fc512014 618 let substs = self.resolve(substs, &span);
3b2f2976 619 debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
a1dfa0c6 620 assert!(!substs.needs_infer() && !substs.has_placeholders());
3dfed10e 621 self.typeck_results.node_substs_mut().insert(hir_id, substs);
7cac9316 622 }
1a4d82fc
JJ
623 }
624
c295e0f8 625 #[instrument(skip(self, span), level = "debug")]
3b2f2976 626 fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
3dfed10e 627 let adjustment = self.fcx.typeck_results.borrow_mut().adjustments_mut().remove(hir_id);
7cac9316 628 match adjustment {
1a4d82fc 629 None => {
c295e0f8 630 debug!("no adjustments for node");
1a4d82fc
JJ
631 }
632
633 Some(adjustment) => {
fc512014 634 let resolved_adjustment = self.resolve(adjustment, &span);
c295e0f8 635 debug!(?resolved_adjustment);
3dfed10e 636 self.typeck_results.adjustments_mut().insert(hir_id, resolved_adjustment);
1a4d82fc
JJ
637 }
638 }
639 }
640
c295e0f8 641 #[instrument(skip(self, span), level = "debug")]
ea8adc8c 642 fn visit_pat_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
3dfed10e 643 let adjustment = self.fcx.typeck_results.borrow_mut().pat_adjustments_mut().remove(hir_id);
ea8adc8c
XL
644 match adjustment {
645 None => {
c295e0f8 646 debug!("no pat_adjustments for node");
ea8adc8c
XL
647 }
648
649 Some(adjustment) => {
fc512014 650 let resolved_adjustment = self.resolve(adjustment, &span);
c295e0f8 651 debug!(?resolved_adjustment);
3dfed10e 652 self.typeck_results.pat_adjustments_mut().insert(hir_id, resolved_adjustment);
ea8adc8c
XL
653 }
654 }
655 }
656
32a655c1 657 fn visit_liberated_fn_sigs(&mut self) {
3dfed10e
XL
658 let fcx_typeck_results = self.fcx.typeck_results.borrow();
659 assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
660 let common_hir_owner = fcx_typeck_results.hir_owner;
3b2f2976 661
9c376795
FG
662 let fcx_liberated_fn_sigs = fcx_typeck_results.liberated_fn_sigs().items_in_stable_order();
663
664 for (local_id, &fn_sig) in fcx_liberated_fn_sigs {
ba9703b0 665 let hir_id = hir::HirId { owner: common_hir_owner, local_id };
3b2f2976 666 let fn_sig = self.resolve(fn_sig, &hir_id);
3dfed10e 667 self.typeck_results.liberated_fn_sigs_mut().insert(hir_id, fn_sig);
92a42be0
SL
668 }
669 }
670
32a655c1 671 fn visit_fru_field_types(&mut self) {
3dfed10e
XL
672 let fcx_typeck_results = self.fcx.typeck_results.borrow();
673 assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
674 let common_hir_owner = fcx_typeck_results.hir_owner;
3b2f2976 675
9c376795
FG
676 let fcx_fru_field_types = fcx_typeck_results.fru_field_types().items_in_stable_order();
677
678 for (local_id, ftys) in fcx_fru_field_types {
ba9703b0 679 let hir_id = hir::HirId { owner: common_hir_owner, local_id };
fc512014 680 let ftys = self.resolve(ftys.clone(), &hir_id);
3dfed10e 681 self.typeck_results.fru_field_types_mut().insert(hir_id, ftys);
7453a54e
SL
682 }
683 }
684
fc512014 685 fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
ff7c6d11 686 where
9ffffee4 687 T: TypeFoldable<TyCtxt<'tcx>>,
a7813a04 688 {
ba9703b0
XL
689 let mut resolver = Resolver::new(self.fcx, span, self.body);
690 let x = x.fold_with(&mut resolver);
691 if cfg!(debug_assertions) && x.needs_infer() {
692 span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x);
693 }
694
695 // We may have introduced e.g. `ty::Error`, if inference failed, make sure
3dfed10e
XL
696 // to mark the `TypeckResults` as tainted in that case, so that downstream
697 // users of the typeck results don't produce extra errors, or worse, ICEs.
487cf647
FG
698 if let Some(e) = resolver.replaced_with_error {
699 self.typeck_results.tainted_by_errors = Some(e);
a7813a04 700 }
ba9703b0 701
dc9dc135 702 x
1a4d82fc
JJ
703 }
704}
705
923072b8 706pub(crate) trait Locatable {
dc9dc135 707 fn to_span(&self, tcx: TyCtxt<'_>) -> Span;
1a4d82fc
JJ
708}
709
cc61c64b 710impl Locatable for Span {
dc9dc135 711 fn to_span(&self, _: TyCtxt<'_>) -> Span {
ff7c6d11
XL
712 *self
713 }
cc61c64b
XL
714}
715
3b2f2976 716impl Locatable for hir::HirId {
dc9dc135
XL
717 fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
718 tcx.hir().span(*self)
3b2f2976
XL
719 }
720}
721
ba9703b0
XL
722/// The Resolver. This is the type folding engine that detects
723/// unresolved types and so forth.
cdc7bbd5 724struct Resolver<'cx, 'tcx> {
dc9dc135 725 tcx: TyCtxt<'tcx>,
2b03887a 726 infcx: &'cx InferCtxt<'tcx>,
8faf50e0 727 span: &'cx dyn Locatable,
dfeec247 728 body: &'tcx hir::Body<'tcx>,
ba9703b0 729
487cf647
FG
730 /// Set to `Some` if any `Ty` or `ty::Const` had to be replaced with an `Error`.
731 replaced_with_error: Option<ErrorGuaranteed>,
1a4d82fc
JJ
732}
733
dc9dc135 734impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
cdc7bbd5 735 fn new(
dc9dc135 736 fcx: &'cx FnCtxt<'cx, 'tcx>,
8faf50e0 737 span: &'cx dyn Locatable,
dfeec247 738 body: &'tcx hir::Body<'tcx>,
dc9dc135 739 ) -> Resolver<'cx, 'tcx> {
487cf647 740 Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: None }
1a4d82fc
JJ
741 }
742
487cf647
FG
743 fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
744 match self.tcx.sess.has_errors() {
745 Some(e) => e,
746 None => self
747 .infcx
2b03887a 748 .err_ctxt()
1b1a35ee 749 .emit_inference_failure_err(
353b0b11 750 self.tcx.hir().body_owner_def_id(self.body.id()),
1b1a35ee 751 self.span.to_span(self.tcx),
2b03887a 752 p.into(),
f9f354fc 753 E0282,
064997fb 754 false,
f9f354fc 755 )
487cf647 756 .emit(),
f9f354fc
XL
757 }
758 }
1a4d82fc
JJ
759}
760
c295e0f8
XL
761struct EraseEarlyRegions<'tcx> {
762 tcx: TyCtxt<'tcx>,
763}
764
9ffffee4
FG
765impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> {
766 fn interner(&self) -> TyCtxt<'tcx> {
c295e0f8
XL
767 self.tcx
768 }
769 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
5099ac24 770 if ty.has_type_flags(ty::TypeFlags::HAS_FREE_REGIONS) {
c295e0f8
XL
771 ty.super_fold_with(self)
772 } else {
773 ty
774 }
775 }
776 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
5099ac24 777 if r.is_late_bound() { r } else { self.tcx.lifetimes.re_erased }
c295e0f8
XL
778 }
779}
780
9ffffee4
FG
781impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
782 fn interner(&self) -> TyCtxt<'tcx> {
1a4d82fc
JJ
783 self.tcx
784 }
785
786 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fc512014 787 match self.infcx.fully_resolve(t) {
c295e0f8
XL
788 Ok(t) => {
789 // Do not anonymize late-bound regions
790 // (e.g. keep `for<'a>` named `for<'a>`).
791 // This allows NLL to generate error messages that
792 // refer to the higher-ranked lifetime names written by the user.
064997fb 793 EraseEarlyRegions { tcx: self.tcx }.fold_ty(t)
c295e0f8 794 }
cc61c64b 795 Err(_) => {
dfeec247 796 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
487cf647
FG
797 let e = self.report_error(t);
798 self.replaced_with_error = Some(e);
9ffffee4 799 self.interner().ty_error(e)
1a4d82fc
JJ
800 }
801 }
802 }
803
7cac9316 804 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
ba9703b0
XL
805 debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
806 self.tcx.lifetimes.re_erased
48663c56
XL
807 }
808
5099ac24 809 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
fc512014 810 match self.infcx.fully_resolve(ct) {
064997fb 811 Ok(ct) => self.tcx.erase_regions(ct),
48663c56 812 Err(_) => {
dfeec247 813 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
487cf647
FG
814 let e = self.report_error(ct);
815 self.replaced_with_error = Some(e);
9ffffee4 816 self.interner().const_error_with_guaranteed(ct.ty(), e)
48663c56
XL
817 }
818 }
1a4d82fc
JJ
819 }
820}
821
822///////////////////////////////////////////////////////////////////////////
823// During type check, we store promises with the result of trait
824// lookup rather than the actual results (because the results are not
825// necessarily available immediately). These routines unwind the
826// promises. It is expected that we will have already reported any
827// errors that may be encountered, so if the promises store an error,
828// a dummy result is returned.