]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/writeback.rs
35f25b322e053fa3cf11cabecce552d51c793683
[rust.git] / src / librustc_typeck / check / writeback.rs
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.
4
5 use crate::check::FnCtxt;
6
7 use rustc::hir;
8 use rustc::hir::def_id::{DefId, DefIndex};
9 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
10 use rustc::infer::InferCtxt;
11 use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
12 use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
13 use rustc::ty::fold::{TypeFoldable, TypeFolder};
14 use rustc::ty::{self, Ty, TyCtxt};
15 use rustc::util::nodemap::DefIdSet;
16 use rustc_data_structures::sync::Lrc;
17 use syntax::symbol::sym;
18 use syntax_pos::Span;
19
20 use std::mem;
21
22 ///////////////////////////////////////////////////////////////////////////
23 // Entry point
24
25 // During type inference, partially inferred types are
26 // represented using Type variables (ty::Infer). These don't appear in
27 // the final TypeckTables since all of the types should have been
28 // inferred once typeck_tables_of is done.
29 // When type inference is running however, having to update the typeck
30 // tables every time a new type is inferred would be unreasonably slow,
31 // so instead all of the replacement happens at the end in
32 // resolve_type_vars_in_body, which creates a new TypeTables which
33 // doesn't contain any inference types.
34 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
35     pub fn resolve_type_vars_in_body(&self, body: &'tcx hir::Body) -> &'tcx ty::TypeckTables<'tcx> {
36         let item_id = self.tcx.hir().body_owner(body.id());
37         let item_def_id = self.tcx.hir().local_def_id(item_id);
38
39         // This attribute causes us to dump some writeback information
40         // in the form of errors, which is uSymbolfor unit tests.
41         let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs);
42
43         let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs);
44         for param in &body.params {
45             wbcx.visit_node_id(param.pat.span, param.hir_id);
46         }
47         // Type only exists for constants and statics, not functions.
48         match self.tcx.hir().body_owner_kind(item_id) {
49             hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
50                 wbcx.visit_node_id(body.value.span, item_id);
51             }
52             hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
53         }
54         wbcx.visit_body(body);
55         wbcx.visit_upvar_capture_map();
56         wbcx.visit_closures();
57         wbcx.visit_liberated_fn_sigs();
58         wbcx.visit_fru_field_types();
59         wbcx.visit_opaque_types(body.value.span);
60         wbcx.visit_coercion_casts();
61         wbcx.visit_free_region_map();
62         wbcx.visit_user_provided_tys();
63         wbcx.visit_user_provided_sigs();
64         wbcx.visit_generator_interior_types();
65
66         let used_trait_imports = mem::replace(
67             &mut self.tables.borrow_mut().used_trait_imports,
68             Lrc::new(DefIdSet::default()),
69         );
70         debug!(
71             "used_trait_imports({:?}) = {:?}",
72             item_def_id, used_trait_imports
73         );
74         wbcx.tables.used_trait_imports = used_trait_imports;
75
76         wbcx.tables.upvar_list = mem::replace(
77             &mut self.tables.borrow_mut().upvar_list,
78             Default::default(),
79         );
80
81         wbcx.tables.tainted_by_errors = self.is_tainted_by_errors();
82
83         debug!(
84             "writeback: tables for {:?} are {:#?}",
85             item_def_id, wbcx.tables
86         );
87
88         self.tcx.arena.alloc(wbcx.tables)
89     }
90 }
91
92 ///////////////////////////////////////////////////////////////////////////
93 // The Writeback context. This visitor walks the AST, checking the
94 // fn-specific tables to find references to types or regions. It
95 // resolves those regions to remove inference variables and writes the
96 // final result back into the master tables in the tcx. Here and
97 // there, it applies a few ad-hoc checks that were not convenient to
98 // do elsewhere.
99
100 struct WritebackCx<'cx, 'tcx> {
101     fcx: &'cx FnCtxt<'cx, 'tcx>,
102
103     tables: ty::TypeckTables<'tcx>,
104
105     body: &'tcx hir::Body,
106
107     rustc_dump_user_substs: bool,
108 }
109
110 impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
111     fn new(
112         fcx: &'cx FnCtxt<'cx, 'tcx>,
113         body: &'tcx hir::Body,
114         rustc_dump_user_substs: bool,
115     ) -> WritebackCx<'cx, 'tcx> {
116         let owner = body.id().hir_id;
117
118         WritebackCx {
119             fcx,
120             tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))),
121             body,
122             rustc_dump_user_substs,
123         }
124     }
125
126     fn tcx(&self) -> TyCtxt<'tcx> {
127         self.fcx.tcx
128     }
129
130     fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
131         debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
132         assert!(!ty.needs_infer() && !ty.has_placeholders());
133         self.tables.node_types_mut().insert(hir_id, ty);
134     }
135
136     // Hacky hack: During type-checking, we treat *all* operators
137     // as potentially overloaded. But then, during writeback, if
138     // we observe that something like `a+b` is (known to be)
139     // operating on scalars, we clear the overload.
140     fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr) {
141         match e.kind {
142             hir::ExprKind::Unary(hir::UnNeg, ref inner)
143             | hir::ExprKind::Unary(hir::UnNot, ref inner) => {
144                 let inner_ty = self.fcx.node_ty(inner.hir_id);
145                 let inner_ty = self.fcx.resolve_vars_if_possible(&inner_ty);
146
147                 if inner_ty.is_scalar() {
148                     let mut tables = self.fcx.tables.borrow_mut();
149                     tables.type_dependent_defs_mut().remove(e.hir_id);
150                     tables.node_substs_mut().remove(e.hir_id);
151                 }
152             }
153             hir::ExprKind::Binary(ref op, ref lhs, ref rhs)
154             | hir::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => {
155                 let lhs_ty = self.fcx.node_ty(lhs.hir_id);
156                 let lhs_ty = self.fcx.resolve_vars_if_possible(&lhs_ty);
157
158                 let rhs_ty = self.fcx.node_ty(rhs.hir_id);
159                 let rhs_ty = self.fcx.resolve_vars_if_possible(&rhs_ty);
160
161                 if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
162                     let mut tables = self.fcx.tables.borrow_mut();
163                     tables.type_dependent_defs_mut().remove(e.hir_id);
164                     tables.node_substs_mut().remove(e.hir_id);
165
166                     match e.kind {
167                         hir::ExprKind::Binary(..) => {
168                             if !op.node.is_by_value() {
169                                 let mut adjustments = tables.adjustments_mut();
170                                 adjustments.get_mut(lhs.hir_id).map(|a| a.pop());
171                                 adjustments.get_mut(rhs.hir_id).map(|a| a.pop());
172                             }
173                         }
174                         hir::ExprKind::AssignOp(..) => {
175                             tables
176                                 .adjustments_mut()
177                                 .get_mut(lhs.hir_id)
178                                 .map(|a| a.pop());
179                         }
180                         _ => {}
181                     }
182                 }
183             }
184             _ => {}
185         }
186     }
187
188     // Similar to operators, indexing is always assumed to be overloaded
189     // Here, correct cases where an indexing expression can be simplified
190     // to use builtin indexing because the index type is known to be
191     // usize-ish
192     fn fix_index_builtin_expr(&mut self, e: &hir::Expr) {
193         if let hir::ExprKind::Index(ref base, ref index) = e.kind {
194             let mut tables = self.fcx.tables.borrow_mut();
195
196             // All valid indexing looks like this; might encounter non-valid indexes at this point.
197             let base_ty = tables.expr_ty_adjusted_opt(&base).map(|t| &t.kind);
198             if base_ty.is_none() {
199                 // When encountering `return [0][0]` outside of a `fn` body we can encounter a base
200                 // that isn't in the type table. We assume more relevant errors have already been
201                 // emitted, so we delay an ICE if none have. (#64638)
202                 self.tcx().sess.delay_span_bug(e.span, &format!("bad base: `{:?}`", base));
203             }
204             if let Some(ty::Ref(_, base_ty, _)) = base_ty {
205                 let index_ty = tables.expr_ty_adjusted_opt(&index).unwrap_or_else(|| {
206                     // When encountering `return [0][0]` outside of a `fn` body we would attempt
207                     // to access an unexistend index. We assume that more relevant errors will
208                     // already have been emitted, so we only gate on this with an ICE if no
209                     // error has been emitted. (#64638)
210                     self.tcx().sess.delay_span_bug(
211                         e.span,
212                         &format!("bad index {:?} for base: `{:?}`", index, base),
213                     );
214                     self.fcx.tcx.types.err
215                 });
216                 let index_ty = self.fcx.resolve_vars_if_possible(&index_ty);
217
218                 if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize {
219                     // Remove the method call record
220                     tables.type_dependent_defs_mut().remove(e.hir_id);
221                     tables.node_substs_mut().remove(e.hir_id);
222
223                     tables.adjustments_mut().get_mut(base.hir_id).map(|a| {
224                         // Discard the need for a mutable borrow
225                         match a.pop() {
226                             // Extra adjustment made when indexing causes a drop
227                             // of size information - we need to get rid of it
228                             // Since this is "after" the other adjustment to be
229                             // discarded, we do an extra `pop()`
230                             Some(Adjustment {
231                                 kind: Adjust::Pointer(PointerCast::Unsize),
232                                 ..
233                             }) => {
234                                 // So the borrow discard actually happens here
235                                 a.pop();
236                             }
237                             _ => {}
238                         }
239                     });
240                 }
241             }
242         }
243     }
244 }
245
246 ///////////////////////////////////////////////////////////////////////////
247 // Impl of Visitor for Resolver
248 //
249 // This is the master code which walks the AST. It delegates most of
250 // the heavy lifting to the generic visit and resolve functions
251 // below. In general, a function is made into a `visitor` if it must
252 // traffic in node-ids or update tables in the type context etc.
253
254 impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
255     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
256         NestedVisitorMap::None
257     }
258
259     fn visit_expr(&mut self, e: &'tcx hir::Expr) {
260         self.fix_scalar_builtin_expr(e);
261         self.fix_index_builtin_expr(e);
262
263         self.visit_node_id(e.span, e.hir_id);
264
265         match e.kind {
266             hir::ExprKind::Closure(_, _, body, _, _) => {
267                 let body = self.fcx.tcx.hir().body(body);
268                 for param in &body.params {
269                     self.visit_node_id(e.span, param.hir_id);
270                 }
271
272                 self.visit_body(body);
273             }
274             hir::ExprKind::Struct(_, ref fields, _) => {
275                 for field in fields {
276                     self.visit_field_id(field.hir_id);
277                 }
278             }
279             hir::ExprKind::Field(..) => {
280                 self.visit_field_id(e.hir_id);
281             }
282             _ => {}
283         }
284
285         intravisit::walk_expr(self, e);
286     }
287
288     fn visit_block(&mut self, b: &'tcx hir::Block) {
289         self.visit_node_id(b.span, b.hir_id);
290         intravisit::walk_block(self, b);
291     }
292
293     fn visit_pat(&mut self, p: &'tcx hir::Pat) {
294         match p.kind {
295             hir::PatKind::Binding(..) => {
296                 if let Some(&bm) = self.fcx.tables.borrow().pat_binding_modes().get(p.hir_id) {
297                     self.tables.pat_binding_modes_mut().insert(p.hir_id, bm);
298                 } else {
299                     self.tcx()
300                         .sess
301                         .delay_span_bug(p.span, "missing binding mode");
302                 }
303             }
304             hir::PatKind::Struct(_, ref fields, _) => {
305                 for field in fields {
306                     self.visit_field_id(field.hir_id);
307                 }
308             }
309             _ => {}
310         };
311
312         self.visit_pat_adjustments(p.span, p.hir_id);
313
314         self.visit_node_id(p.span, p.hir_id);
315         intravisit::walk_pat(self, p);
316     }
317
318     fn visit_local(&mut self, l: &'tcx hir::Local) {
319         intravisit::walk_local(self, l);
320         let var_ty = self.fcx.local_ty(l.span, l.hir_id).decl_ty;
321         let var_ty = self.resolve(&var_ty, &l.span);
322         self.write_ty_to_tables(l.hir_id, var_ty);
323     }
324
325     fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty) {
326         intravisit::walk_ty(self, hir_ty);
327         let ty = self.fcx.node_ty(hir_ty.hir_id);
328         let ty = self.resolve(&ty, &hir_ty.span);
329         self.write_ty_to_tables(hir_ty.hir_id, ty);
330     }
331 }
332
333 impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
334     fn visit_upvar_capture_map(&mut self) {
335         for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() {
336             let new_upvar_capture = match *upvar_capture {
337                 ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
338                 ty::UpvarCapture::ByRef(ref upvar_borrow) => {
339                     let r = upvar_borrow.region;
340                     let r = self.resolve(&r, &upvar_id.var_path.hir_id);
341                     ty::UpvarCapture::ByRef(ty::UpvarBorrow {
342                         kind: upvar_borrow.kind,
343                         region: r,
344                     })
345                 }
346             };
347             debug!(
348                 "Upvar capture for {:?} resolved to {:?}",
349                 upvar_id, new_upvar_capture
350             );
351             self.tables
352                 .upvar_capture_map
353                 .insert(*upvar_id, new_upvar_capture);
354         }
355     }
356
357     fn visit_closures(&mut self) {
358         let fcx_tables = self.fcx.tables.borrow();
359         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
360         let common_local_id_root = fcx_tables.local_id_root.unwrap();
361
362         for (&id, &origin) in fcx_tables.closure_kind_origins().iter() {
363             let hir_id = hir::HirId {
364                 owner: common_local_id_root.index,
365                 local_id: id,
366             };
367             self.tables
368                 .closure_kind_origins_mut()
369                 .insert(hir_id, origin);
370         }
371     }
372
373     fn visit_coercion_casts(&mut self) {
374         let fcx_tables = self.fcx.tables.borrow();
375         let fcx_coercion_casts = fcx_tables.coercion_casts();
376         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
377
378         for local_id in fcx_coercion_casts {
379             self.tables.set_coercion_cast(*local_id);
380         }
381     }
382
383     fn visit_free_region_map(&mut self) {
384         self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
385         debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value()));
386     }
387
388     fn visit_user_provided_tys(&mut self) {
389         let fcx_tables = self.fcx.tables.borrow();
390         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
391         let common_local_id_root = fcx_tables.local_id_root.unwrap();
392
393         let mut errors_buffer = Vec::new();
394         for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() {
395             let hir_id = hir::HirId {
396                 owner: common_local_id_root.index,
397                 local_id,
398             };
399
400             if cfg!(debug_assertions) && c_ty.has_local_value() {
401                 span_bug!(
402                     hir_id.to_span(self.fcx.tcx),
403                     "writeback: `{:?}` is a local value",
404                     c_ty
405                 );
406             };
407
408             self.tables
409                 .user_provided_types_mut()
410                 .insert(hir_id, c_ty.clone());
411
412             if let ty::UserType::TypeOf(_, user_substs) = c_ty.value {
413                 if self.rustc_dump_user_substs {
414                     // This is a unit-testing mechanism.
415                     let span = self.tcx().hir().span(hir_id);
416                     // We need to buffer the errors in order to guarantee a consistent
417                     // order when emitting them.
418                     let err = self.tcx().sess.struct_span_err(
419                         span,
420                         &format!("user substs: {:?}", user_substs)
421                     );
422                     err.buffer(&mut errors_buffer);
423                 }
424             }
425         }
426
427         if !errors_buffer.is_empty() {
428             errors_buffer.sort_by_key(|diag| diag.span.primary_span());
429             for diag in errors_buffer.drain(..) {
430                 self.tcx().sess.diagnostic().emit_diagnostic(&diag);
431             }
432         }
433     }
434
435     fn visit_user_provided_sigs(&mut self) {
436         let fcx_tables = self.fcx.tables.borrow();
437         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
438
439         for (&def_id, c_sig) in fcx_tables.user_provided_sigs.iter() {
440             if cfg!(debug_assertions) && c_sig.has_local_value() {
441                 span_bug!(
442                     self.fcx.tcx.hir().span_if_local(def_id).unwrap(),
443                     "writeback: `{:?}` is a local value",
444                     c_sig
445                 );
446             };
447
448             self.tables
449                 .user_provided_sigs
450                 .insert(def_id, c_sig.clone());
451         }
452     }
453
454     fn visit_generator_interior_types(&mut self) {
455         let fcx_tables = self.fcx.tables.borrow();
456         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
457         self.tables.generator_interior_types = fcx_tables.generator_interior_types.clone();
458     }
459
460     fn visit_opaque_types(&mut self, span: Span) {
461         for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
462             let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap();
463             let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id);
464
465             debug_assert!(!instantiated_ty.has_escaping_bound_vars());
466
467             // Prevent:
468             // * `fn foo<T>() -> Foo<T>`
469             // * `fn foo<T: Bound + Other>() -> Foo<T>`
470             // from being defining.
471
472             // Also replace all generic params with the ones from the opaque type
473             // definition so that
474             // ```rust
475             // type Foo<T> = impl Baz + 'static;
476             // fn foo<U>() -> Foo<U> { .. }
477             // ```
478             // figures out the concrete type with `U`, but the stored type is with `T`.
479             let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
480                 def_id, opaque_defn, instantiated_ty, span);
481
482             let mut skip_add = false;
483
484             if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.kind {
485                 if let hir::OpaqueTyOrigin::TypeAlias = opaque_defn.origin {
486                     if def_id == defin_ty_def_id {
487                         debug!(
488                             "skipping adding concrete definition for opaque type {:?} {:?}",
489                             opaque_defn, defin_ty_def_id
490                         );
491                         skip_add = true;
492                     }
493                 }
494             }
495
496             if !opaque_defn.substs.has_local_value() {
497                 // We only want to add an entry into `concrete_opaque_types`
498                 // if we actually found a defining usage of this opaque type.
499                 // Otherwise, we do nothing - we'll either find a defining usage
500                 // in some other location, or we'll end up emitting an error due
501                 // to the lack of defining usage
502                 if !skip_add {
503                     let new = ty::ResolvedOpaqueTy {
504                         concrete_type: definition_ty,
505                         substs: opaque_defn.substs,
506                     };
507
508                     let old = self.tables
509                         .concrete_opaque_types
510                         .insert(def_id, new);
511                     if let Some(old) = old {
512                         if old.concrete_type != definition_ty || old.substs != opaque_defn.substs {
513                             span_bug!(
514                                 span,
515                                 "`visit_opaque_types` tried to write different types for the same \
516                                  opaque type: {:?}, {:?}, {:?}, {:?}",
517                                 def_id,
518                                 definition_ty,
519                                 opaque_defn,
520                                 old,
521                             );
522                         }
523                     }
524                 }
525             } else {
526                 self.tcx().sess.delay_span_bug(
527                     span,
528                     "`opaque_defn` is a local value",
529                 );
530             }
531         }
532     }
533
534     fn visit_field_id(&mut self, hir_id: hir::HirId) {
535         if let Some(index) = self.fcx
536             .tables
537             .borrow_mut()
538             .field_indices_mut()
539             .remove(hir_id)
540         {
541             self.tables.field_indices_mut().insert(hir_id, index);
542         }
543     }
544
545     fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
546         // Export associated path extensions and method resolutions.
547         if let Some(def) = self.fcx
548             .tables
549             .borrow_mut()
550             .type_dependent_defs_mut()
551             .remove(hir_id)
552         {
553             self.tables.type_dependent_defs_mut().insert(hir_id, def);
554         }
555
556         // Resolve any borrowings for the node with id `node_id`
557         self.visit_adjustments(span, hir_id);
558
559         // Resolve the type of the node with id `node_id`
560         let n_ty = self.fcx.node_ty(hir_id);
561         let n_ty = self.resolve(&n_ty, &span);
562         self.write_ty_to_tables(hir_id, n_ty);
563         debug!("node {:?} has type {:?}", hir_id, n_ty);
564
565         // Resolve any substitutions
566         if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) {
567             let substs = self.resolve(&substs, &span);
568             debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
569             assert!(!substs.needs_infer() && !substs.has_placeholders());
570             self.tables.node_substs_mut().insert(hir_id, substs);
571         }
572     }
573
574     fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
575         let adjustment = self.fcx
576             .tables
577             .borrow_mut()
578             .adjustments_mut()
579             .remove(hir_id);
580         match adjustment {
581             None => {
582                 debug!("no adjustments for node {:?}", hir_id);
583             }
584
585             Some(adjustment) => {
586                 let resolved_adjustment = self.resolve(&adjustment, &span);
587                 debug!(
588                     "adjustments for node {:?}: {:?}",
589                     hir_id, resolved_adjustment
590                 );
591                 self.tables
592                     .adjustments_mut()
593                     .insert(hir_id, resolved_adjustment);
594             }
595         }
596     }
597
598     fn visit_pat_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
599         let adjustment = self.fcx
600             .tables
601             .borrow_mut()
602             .pat_adjustments_mut()
603             .remove(hir_id);
604         match adjustment {
605             None => {
606                 debug!("no pat_adjustments for node {:?}", hir_id);
607             }
608
609             Some(adjustment) => {
610                 let resolved_adjustment = self.resolve(&adjustment, &span);
611                 debug!(
612                     "pat_adjustments for node {:?}: {:?}",
613                     hir_id, resolved_adjustment
614                 );
615                 self.tables
616                     .pat_adjustments_mut()
617                     .insert(hir_id, resolved_adjustment);
618             }
619         }
620     }
621
622     fn visit_liberated_fn_sigs(&mut self) {
623         let fcx_tables = self.fcx.tables.borrow();
624         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
625         let common_local_id_root = fcx_tables.local_id_root.unwrap();
626
627         for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() {
628             let hir_id = hir::HirId {
629                 owner: common_local_id_root.index,
630                 local_id,
631             };
632             let fn_sig = self.resolve(fn_sig, &hir_id);
633             self.tables
634                 .liberated_fn_sigs_mut()
635                 .insert(hir_id, fn_sig.clone());
636         }
637     }
638
639     fn visit_fru_field_types(&mut self) {
640         let fcx_tables = self.fcx.tables.borrow();
641         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
642         let common_local_id_root = fcx_tables.local_id_root.unwrap();
643
644         for (&local_id, ftys) in fcx_tables.fru_field_types().iter() {
645             let hir_id = hir::HirId {
646                 owner: common_local_id_root.index,
647                 local_id,
648             };
649             let ftys = self.resolve(ftys, &hir_id);
650             self.tables.fru_field_types_mut().insert(hir_id, ftys);
651         }
652     }
653
654     fn resolve<T>(&self, x: &T, span: &dyn Locatable) -> T
655     where
656         T: TypeFoldable<'tcx>,
657     {
658         let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body));
659         if cfg!(debug_assertions) && x.has_local_value() {
660             span_bug!(
661                 span.to_span(self.fcx.tcx),
662                 "writeback: `{:?}` is a local value",
663                 x
664             );
665         }
666         x
667     }
668 }
669
670 trait Locatable {
671     fn to_span(&self, tcx: TyCtxt<'_>) -> Span;
672 }
673
674 impl Locatable for Span {
675     fn to_span(&self, _: TyCtxt<'_>) -> Span {
676         *self
677     }
678 }
679
680 impl Locatable for DefIndex {
681     fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
682         let hir_id = tcx.hir().def_index_to_hir_id(*self);
683         tcx.hir().span(hir_id)
684     }
685 }
686
687 impl Locatable for hir::HirId {
688     fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
689         tcx.hir().span(*self)
690     }
691 }
692
693 ///////////////////////////////////////////////////////////////////////////
694 // The Resolver. This is the type folding engine that detects
695 // unresolved types and so forth.
696
697 struct Resolver<'cx, 'tcx> {
698     tcx: TyCtxt<'tcx>,
699     infcx: &'cx InferCtxt<'cx, 'tcx>,
700     span: &'cx dyn Locatable,
701     body: &'tcx hir::Body,
702 }
703
704 impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
705     fn new(
706         fcx: &'cx FnCtxt<'cx, 'tcx>,
707         span: &'cx dyn Locatable,
708         body: &'tcx hir::Body,
709     ) -> Resolver<'cx, 'tcx> {
710         Resolver {
711             tcx: fcx.tcx,
712             infcx: fcx,
713             span,
714             body,
715         }
716     }
717
718     fn report_error(&self, t: Ty<'tcx>) {
719         if !self.tcx.sess.has_errors() {
720             self.infcx
721                 .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282)
722                 .emit();
723         }
724     }
725 }
726
727 impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
728     fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
729         self.tcx
730     }
731
732     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
733         match self.infcx.fully_resolve(&t) {
734             Ok(t) => t,
735             Err(_) => {
736                 debug!(
737                     "Resolver::fold_ty: input type `{:?}` not fully resolvable",
738                     t
739                 );
740                 self.report_error(t);
741                 self.tcx().types.err
742             }
743         }
744     }
745
746     // FIXME This should be carefully checked
747     // We could use `self.report_error` but it doesn't accept a ty::Region, right now.
748     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
749         self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static)
750     }
751
752     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
753         match self.infcx.fully_resolve(&ct) {
754             Ok(ct) => ct,
755             Err(_) => {
756                 debug!(
757                     "Resolver::fold_const: input const `{:?}` not fully resolvable",
758                     ct
759                 );
760                 // FIXME: we'd like to use `self.report_error`, but it doesn't yet
761                 // accept a &'tcx ty::Const.
762                 self.tcx().consts.err
763             }
764         }
765     }
766 }
767
768 ///////////////////////////////////////////////////////////////////////////
769 // During type check, we store promises with the result of trait
770 // lookup rather than the actual results (because the results are not
771 // necessarily available immediately). These routines unwind the
772 // promises. It is expected that we will have already reported any
773 // errors that may be encountered, so if the promises store an error,
774 // a dummy result is returned.