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