]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | // Type resolution: the phase that finds all the types in the AST with | |
12 | // unresolved type variables and replaces "ty_var" types with their | |
13 | // substitutions. | |
1a4d82fc | 14 | |
1a4d82fc | 15 | use check::FnCtxt; |
cc61c64b | 16 | use rustc::hir; |
3b2f2976 | 17 | use rustc::hir::def_id::{DefId, DefIndex}; |
ff7c6d11 XL |
18 | use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; |
19 | use rustc::infer::InferCtxt; | |
7cac9316 | 20 | use rustc::ty::{self, Ty, TyCtxt}; |
2c00a5a8 | 21 | use rustc::ty::adjustment::{Adjust, Adjustment}; |
ff7c6d11 | 22 | use rustc::ty::fold::{TypeFoldable, TypeFolder}; |
7cac9316 | 23 | use rustc::util::nodemap::DefIdSet; |
1a4d82fc | 24 | use syntax::ast; |
476ff2be | 25 | use syntax_pos::Span; |
cc61c64b | 26 | use std::mem; |
abe05a73 | 27 | use std::rc::Rc; |
1a4d82fc JJ |
28 | |
29 | /////////////////////////////////////////////////////////////////////////// | |
32a655c1 | 30 | // Entry point |
1a4d82fc | 31 | |
a7813a04 | 32 | impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { |
ff7c6d11 | 33 | pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> { |
32a655c1 SL |
34 | let item_id = self.tcx.hir.body_owner(body.id()); |
35 | let item_def_id = self.tcx.hir.local_def_id(item_id); | |
36 | ||
cc61c64b | 37 | let mut wbcx = WritebackCx::new(self, body); |
32a655c1 | 38 | for arg in &body.arguments { |
3b2f2976 | 39 | wbcx.visit_node_id(arg.pat.span, arg.hir_id); |
1a4d82fc | 40 | } |
32a655c1 | 41 | wbcx.visit_body(body); |
a7813a04 XL |
42 | wbcx.visit_upvar_borrow_map(); |
43 | wbcx.visit_closures(); | |
44 | wbcx.visit_liberated_fn_sigs(); | |
45 | wbcx.visit_fru_field_types(); | |
476ff2be | 46 | wbcx.visit_anon_types(); |
32a655c1 | 47 | wbcx.visit_cast_types(); |
8bb4bdeb XL |
48 | wbcx.visit_free_region_map(); |
49 | ||
ff7c6d11 XL |
50 | let used_trait_imports = mem::replace( |
51 | &mut self.tables.borrow_mut().used_trait_imports, | |
52 | Rc::new(DefIdSet()), | |
53 | ); | |
54 | debug!( | |
55 | "used_trait_imports({:?}) = {:?}", | |
56 | item_def_id, | |
57 | used_trait_imports | |
58 | ); | |
8bb4bdeb | 59 | wbcx.tables.used_trait_imports = used_trait_imports; |
32a655c1 | 60 | |
8bb4bdeb XL |
61 | wbcx.tables.tainted_by_errors = self.is_tainted_by_errors(); |
62 | ||
ff7c6d11 XL |
63 | debug!( |
64 | "writeback: tables for {:?} are {:#?}", | |
65 | item_def_id, | |
66 | wbcx.tables | |
67 | ); | |
68 | ||
8bb4bdeb | 69 | self.tcx.alloc_tables(wbcx.tables) |
1a4d82fc | 70 | } |
1a4d82fc JJ |
71 | } |
72 | ||
73 | /////////////////////////////////////////////////////////////////////////// | |
74 | // The Writerback context. This visitor walks the AST, checking the | |
75 | // fn-specific tables to find references to types or regions. It | |
76 | // resolves those regions to remove inference variables and writes the | |
77 | // final result back into the master tables in the tcx. Here and | |
78 | // there, it applies a few ad-hoc checks that were not convenient to | |
79 | // do elsewhere. | |
80 | ||
ff7c6d11 | 81 | struct WritebackCx<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> { |
a7813a04 | 82 | fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, |
5bcae85e | 83 | |
32a655c1 SL |
84 | tables: ty::TypeckTables<'gcx>, |
85 | ||
cc61c64b | 86 | body: &'gcx hir::Body, |
1a4d82fc JJ |
87 | } |
88 | ||
a7813a04 | 89 | impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { |
ff7c6d11 XL |
90 | fn new( |
91 | fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, | |
92 | body: &'gcx hir::Body, | |
93 | ) -> WritebackCx<'cx, 'gcx, 'tcx> { | |
3b2f2976 XL |
94 | let owner = fcx.tcx.hir.definitions().node_to_hir_id(body.id().node_id); |
95 | ||
7cac9316 | 96 | WritebackCx { |
3b2f2976 XL |
97 | fcx, |
98 | tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))), | |
99 | body, | |
5bcae85e | 100 | } |
1a4d82fc JJ |
101 | } |
102 | ||
a7813a04 XL |
103 | fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> { |
104 | self.fcx.tcx | |
1a4d82fc | 105 | } |
d9579d0f | 106 | |
3b2f2976 | 107 | fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) { |
ff7c6d11 | 108 | debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty); |
476ff2be | 109 | assert!(!ty.needs_infer()); |
3b2f2976 | 110 | self.tables.node_types_mut().insert(hir_id, ty); |
476ff2be SL |
111 | } |
112 | ||
d9579d0f AL |
113 | // Hacky hack: During type-checking, we treat *all* operators |
114 | // as potentially overloaded. But then, during writeback, if | |
115 | // we observe that something like `a+b` is (known to be) | |
116 | // operating on scalars, we clear the overload. | |
32a655c1 | 117 | fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr) { |
b039eaaf | 118 | match e.node { |
ff7c6d11 | 119 | hir::ExprUnary(hir::UnNeg, ref inner) | hir::ExprUnary(hir::UnNot, ref inner) => { |
3b2f2976 | 120 | let inner_ty = self.fcx.node_ty(inner.hir_id); |
32a655c1 SL |
121 | let inner_ty = self.fcx.resolve_type_vars_if_possible(&inner_ty); |
122 | ||
123 | if inner_ty.is_scalar() { | |
7cac9316 | 124 | let mut tables = self.fcx.tables.borrow_mut(); |
3b2f2976 XL |
125 | tables.type_dependent_defs_mut().remove(e.hir_id); |
126 | tables.node_substs_mut().remove(e.hir_id); | |
32a655c1 SL |
127 | } |
128 | } | |
ff7c6d11 XL |
129 | hir::ExprBinary(ref op, ref lhs, ref rhs) |
130 | | hir::ExprAssignOp(ref op, ref lhs, ref rhs) => { | |
3b2f2976 | 131 | let lhs_ty = self.fcx.node_ty(lhs.hir_id); |
a7813a04 | 132 | let lhs_ty = self.fcx.resolve_type_vars_if_possible(&lhs_ty); |
b039eaaf | 133 | |
3b2f2976 | 134 | let rhs_ty = self.fcx.node_ty(rhs.hir_id); |
a7813a04 | 135 | let rhs_ty = self.fcx.resolve_type_vars_if_possible(&rhs_ty); |
b039eaaf SL |
136 | |
137 | if lhs_ty.is_scalar() && rhs_ty.is_scalar() { | |
7cac9316 | 138 | let mut tables = self.fcx.tables.borrow_mut(); |
3b2f2976 XL |
139 | tables.type_dependent_defs_mut().remove(e.hir_id); |
140 | tables.node_substs_mut().remove(e.hir_id); | |
b039eaaf | 141 | |
b039eaaf SL |
142 | match e.node { |
143 | hir::ExprBinary(..) => { | |
54a0048b | 144 | if !op.node.is_by_value() { |
3b2f2976 XL |
145 | let mut adjustments = tables.adjustments_mut(); |
146 | adjustments.get_mut(lhs.hir_id).map(|a| a.pop()); | |
147 | adjustments.get_mut(rhs.hir_id).map(|a| a.pop()); | |
b039eaaf | 148 | } |
ff7c6d11 | 149 | } |
b039eaaf | 150 | hir::ExprAssignOp(..) => { |
ff7c6d11 XL |
151 | tables |
152 | .adjustments_mut() | |
153 | .get_mut(lhs.hir_id) | |
154 | .map(|a| a.pop()); | |
155 | } | |
156 | _ => {} | |
b039eaaf | 157 | } |
d9579d0f AL |
158 | } |
159 | } | |
ff7c6d11 | 160 | _ => {} |
d9579d0f AL |
161 | } |
162 | } | |
2c00a5a8 XL |
163 | |
164 | // Similar to operators, indexing is always assumed to be overloaded | |
165 | // Here, correct cases where an indexing expression can be simplified | |
166 | // to use builtin indexing because the index type is known to be | |
167 | // usize-ish | |
168 | fn fix_index_builtin_expr(&mut self, e: &hir::Expr) { | |
169 | if let hir::ExprIndex(ref base, ref index) = e.node { | |
170 | let mut tables = self.fcx.tables.borrow_mut(); | |
171 | ||
172 | match tables.expr_ty_adjusted(&base).sty { | |
173 | // All valid indexing looks like this | |
174 | ty::TyRef(_, ty::TypeAndMut { ty: ref base_ty, .. }) => { | |
175 | let index_ty = tables.expr_ty_adjusted(&index); | |
176 | let index_ty = self.fcx.resolve_type_vars_if_possible(&index_ty); | |
177 | ||
178 | if base_ty.builtin_index().is_some() | |
179 | && index_ty == self.fcx.tcx.types.usize { | |
180 | // Remove the method call record | |
181 | tables.type_dependent_defs_mut().remove(e.hir_id); | |
182 | tables.node_substs_mut().remove(e.hir_id); | |
183 | ||
184 | tables.adjustments_mut().get_mut(base.hir_id).map(|a| { | |
185 | // Discard the need for a mutable borrow | |
186 | match a.pop() { | |
187 | // Extra adjustment made when indexing causes a drop | |
188 | // of size information - we need to get rid of it | |
189 | // Since this is "after" the other adjustment to be | |
190 | // discarded, we do an extra `pop()` | |
191 | Some(Adjustment { kind: Adjust::Unsize, .. }) => { | |
192 | // So the borrow discard actually happens here | |
193 | a.pop(); | |
194 | }, | |
195 | _ => {} | |
196 | } | |
197 | }); | |
198 | } | |
199 | }, | |
200 | // Might encounter non-valid indexes at this point, so there | |
201 | // has to be a fall-through | |
202 | _ => {}, | |
203 | } | |
204 | } | |
205 | } | |
1a4d82fc JJ |
206 | } |
207 | ||
2c00a5a8 | 208 | |
1a4d82fc JJ |
209 | /////////////////////////////////////////////////////////////////////////// |
210 | // Impl of Visitor for Resolver | |
211 | // | |
212 | // This is the master code which walks the AST. It delegates most of | |
213 | // the heavy lifting to the generic visit and resolve functions | |
214 | // below. In general, a function is made into a `visitor` if it must | |
215 | // traffic in node-ids or update tables in the type context etc. | |
216 | ||
476ff2be SL |
217 | impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { |
218 | fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { | |
32a655c1 | 219 | NestedVisitorMap::None |
476ff2be SL |
220 | } |
221 | ||
476ff2be | 222 | fn visit_expr(&mut self, e: &'gcx hir::Expr) { |
32a655c1 | 223 | self.fix_scalar_builtin_expr(e); |
2c00a5a8 | 224 | self.fix_index_builtin_expr(e); |
c34b1796 | 225 | |
3b2f2976 | 226 | self.visit_node_id(e.span, e.hir_id); |
1a4d82fc | 227 | |
ea8adc8c | 228 | if let hir::ExprClosure(_, _, body, _, _) = e.node { |
32a655c1 SL |
229 | let body = self.fcx.tcx.hir.body(body); |
230 | for arg in &body.arguments { | |
3b2f2976 | 231 | self.visit_node_id(e.span, arg.hir_id); |
1a4d82fc | 232 | } |
32a655c1 SL |
233 | |
234 | self.visit_body(body); | |
1a4d82fc JJ |
235 | } |
236 | ||
92a42be0 | 237 | intravisit::walk_expr(self, e); |
1a4d82fc JJ |
238 | } |
239 | ||
476ff2be | 240 | fn visit_block(&mut self, b: &'gcx hir::Block) { |
3b2f2976 | 241 | self.visit_node_id(b.span, b.hir_id); |
92a42be0 | 242 | intravisit::walk_block(self, b); |
1a4d82fc JJ |
243 | } |
244 | ||
476ff2be | 245 | fn visit_pat(&mut self, p: &'gcx hir::Pat) { |
3b2f2976 XL |
246 | match p.node { |
247 | hir::PatKind::Binding(..) => { | |
248 | let bm = *self.fcx | |
ff7c6d11 XL |
249 | .tables |
250 | .borrow() | |
251 | .pat_binding_modes() | |
252 | .get(p.hir_id) | |
253 | .expect("missing binding mode"); | |
3b2f2976 XL |
254 | self.tables.pat_binding_modes_mut().insert(p.hir_id, bm); |
255 | } | |
256 | _ => {} | |
257 | }; | |
258 | ||
ea8adc8c XL |
259 | self.visit_pat_adjustments(p.span, p.hir_id); |
260 | ||
3b2f2976 | 261 | self.visit_node_id(p.span, p.hir_id); |
92a42be0 | 262 | intravisit::walk_pat(self, p); |
1a4d82fc JJ |
263 | } |
264 | ||
476ff2be | 265 | fn visit_local(&mut self, l: &'gcx hir::Local) { |
cc61c64b | 266 | intravisit::walk_local(self, l); |
1a4d82fc | 267 | let var_ty = self.fcx.local_ty(l.span, l.id); |
cc61c64b | 268 | let var_ty = self.resolve(&var_ty, &l.span); |
3b2f2976 | 269 | self.write_ty_to_tables(l.hir_id, var_ty); |
1a4d82fc | 270 | } |
ea8adc8c XL |
271 | |
272 | fn visit_ty(&mut self, hir_ty: &'gcx hir::Ty) { | |
273 | intravisit::walk_ty(self, hir_ty); | |
274 | let ty = self.fcx.node_ty(hir_ty.hir_id); | |
275 | let ty = self.resolve(&ty, &hir_ty.span); | |
276 | self.write_ty_to_tables(hir_ty.hir_id, ty); | |
277 | } | |
1a4d82fc JJ |
278 | } |
279 | ||
a7813a04 | 280 | impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { |
32a655c1 | 281 | fn visit_upvar_borrow_map(&mut self) { |
a7813a04 | 282 | for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() { |
85aaf69f SL |
283 | let new_upvar_capture = match *upvar_capture { |
284 | ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, | |
285 | ty::UpvarCapture::ByRef(ref upvar_borrow) => { | |
286 | let r = upvar_borrow.region; | |
cc61c64b | 287 | let r = self.resolve(&r, &upvar_id.var_id); |
ff7c6d11 XL |
288 | ty::UpvarCapture::ByRef(ty::UpvarBorrow { |
289 | kind: upvar_borrow.kind, | |
290 | region: r, | |
291 | }) | |
85aaf69f SL |
292 | } |
293 | }; | |
ff7c6d11 XL |
294 | debug!( |
295 | "Upvar capture for {:?} resolved to {:?}", | |
296 | upvar_id, | |
297 | new_upvar_capture | |
298 | ); | |
299 | self.tables | |
300 | .upvar_capture_map | |
301 | .insert(*upvar_id, new_upvar_capture); | |
1a4d82fc JJ |
302 | } |
303 | } | |
304 | ||
8bb4bdeb | 305 | fn visit_closures(&mut self) { |
3b2f2976 XL |
306 | let fcx_tables = self.fcx.tables.borrow(); |
307 | debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); | |
308 | let common_local_id_root = fcx_tables.local_id_root.unwrap(); | |
309 | ||
ff7c6d11 | 310 | for (&id, &origin) in fcx_tables.closure_kind_origins().iter() { |
3b2f2976 XL |
311 | let hir_id = hir::HirId { |
312 | owner: common_local_id_root.index, | |
313 | local_id: id, | |
314 | }; | |
ff7c6d11 XL |
315 | self.tables |
316 | .closure_kind_origins_mut() | |
317 | .insert(hir_id, origin); | |
1a4d82fc JJ |
318 | } |
319 | } | |
320 | ||
32a655c1 | 321 | fn visit_cast_types(&mut self) { |
3b2f2976 XL |
322 | let fcx_tables = self.fcx.tables.borrow(); |
323 | let fcx_cast_kinds = fcx_tables.cast_kinds(); | |
324 | debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); | |
325 | let mut self_cast_kinds = self.tables.cast_kinds_mut(); | |
326 | let common_local_id_root = fcx_tables.local_id_root.unwrap(); | |
327 | ||
328 | for (&local_id, &cast_kind) in fcx_cast_kinds.iter() { | |
329 | let hir_id = hir::HirId { | |
330 | owner: common_local_id_root.index, | |
331 | local_id, | |
332 | }; | |
333 | self_cast_kinds.insert(hir_id, cast_kind); | |
334 | } | |
8bb4bdeb XL |
335 | } |
336 | ||
337 | fn visit_free_region_map(&mut self) { | |
ff7c6d11 XL |
338 | let free_region_map = self.tcx() |
339 | .lift_to_global(&self.fcx.tables.borrow().free_region_map); | |
7cac9316 XL |
340 | let free_region_map = free_region_map.expect("all regions in free-region-map are global"); |
341 | self.tables.free_region_map = free_region_map; | |
8bb4bdeb | 342 | } |
5bcae85e | 343 | |
8bb4bdeb | 344 | fn visit_anon_types(&mut self) { |
5bcae85e | 345 | let gcx = self.tcx().global_tcx(); |
ff7c6d11 XL |
346 | for (&def_id, anon_defn) in self.fcx.anon_types.borrow().iter() { |
347 | let node_id = gcx.hir.as_local_node_id(def_id).unwrap(); | |
348 | let instantiated_ty = self.resolve(&anon_defn.concrete_ty, &node_id); | |
349 | let definition_ty = self.fcx.infer_anon_definition_from_instantiation( | |
350 | def_id, | |
351 | anon_defn, | |
352 | instantiated_ty, | |
353 | ); | |
3b2f2976 | 354 | let hir_id = self.tcx().hir.node_to_hir_id(node_id); |
ff7c6d11 | 355 | self.tables.node_types_mut().insert(hir_id, definition_ty); |
5bcae85e SL |
356 | } |
357 | } | |
358 | ||
3b2f2976 | 359 | fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) { |
7cac9316 | 360 | // Export associated path extensions and method resultions. |
3b2f2976 | 361 | if let Some(def) = self.fcx |
ff7c6d11 XL |
362 | .tables |
363 | .borrow_mut() | |
364 | .type_dependent_defs_mut() | |
365 | .remove(hir_id) | |
366 | { | |
3b2f2976 | 367 | self.tables.type_dependent_defs_mut().insert(hir_id, def); |
476ff2be SL |
368 | } |
369 | ||
cc61c64b | 370 | // Resolve any borrowings for the node with id `node_id` |
3b2f2976 | 371 | self.visit_adjustments(span, hir_id); |
1a4d82fc | 372 | |
cc61c64b | 373 | // Resolve the type of the node with id `node_id` |
3b2f2976 | 374 | let n_ty = self.fcx.node_ty(hir_id); |
cc61c64b | 375 | let n_ty = self.resolve(&n_ty, &span); |
3b2f2976 XL |
376 | self.write_ty_to_tables(hir_id, n_ty); |
377 | debug!("Node {:?} has type {:?}", hir_id, n_ty); | |
1a4d82fc JJ |
378 | |
379 | // Resolve any substitutions | |
3b2f2976 | 380 | if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) { |
7cac9316 | 381 | let substs = self.resolve(&substs, &span); |
3b2f2976 | 382 | debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs); |
7cac9316 | 383 | assert!(!substs.needs_infer()); |
3b2f2976 | 384 | self.tables.node_substs_mut().insert(hir_id, substs); |
7cac9316 | 385 | } |
1a4d82fc JJ |
386 | } |
387 | ||
3b2f2976 XL |
388 | fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) { |
389 | let adjustment = self.fcx | |
ff7c6d11 XL |
390 | .tables |
391 | .borrow_mut() | |
392 | .adjustments_mut() | |
393 | .remove(hir_id); | |
7cac9316 | 394 | match adjustment { |
1a4d82fc | 395 | None => { |
3b2f2976 | 396 | debug!("No adjustments for node {:?}", hir_id); |
1a4d82fc JJ |
397 | } |
398 | ||
399 | Some(adjustment) => { | |
7cac9316 | 400 | let resolved_adjustment = self.resolve(&adjustment, &span); |
ff7c6d11 XL |
401 | debug!( |
402 | "Adjustments for node {:?}: {:?}", | |
403 | hir_id, | |
404 | resolved_adjustment | |
405 | ); | |
406 | self.tables | |
407 | .adjustments_mut() | |
408 | .insert(hir_id, resolved_adjustment); | |
1a4d82fc JJ |
409 | } |
410 | } | |
411 | } | |
412 | ||
ea8adc8c XL |
413 | fn visit_pat_adjustments(&mut self, span: Span, hir_id: hir::HirId) { |
414 | let adjustment = self.fcx | |
ff7c6d11 XL |
415 | .tables |
416 | .borrow_mut() | |
417 | .pat_adjustments_mut() | |
418 | .remove(hir_id); | |
ea8adc8c XL |
419 | match adjustment { |
420 | None => { | |
421 | debug!("No pat_adjustments for node {:?}", hir_id); | |
422 | } | |
423 | ||
424 | Some(adjustment) => { | |
425 | let resolved_adjustment = self.resolve(&adjustment, &span); | |
ff7c6d11 XL |
426 | debug!( |
427 | "pat_adjustments for node {:?}: {:?}", | |
428 | hir_id, | |
429 | resolved_adjustment | |
430 | ); | |
431 | self.tables | |
432 | .pat_adjustments_mut() | |
433 | .insert(hir_id, resolved_adjustment); | |
ea8adc8c XL |
434 | } |
435 | } | |
436 | } | |
437 | ||
32a655c1 | 438 | fn visit_liberated_fn_sigs(&mut self) { |
3b2f2976 XL |
439 | let fcx_tables = self.fcx.tables.borrow(); |
440 | debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); | |
441 | let common_local_id_root = fcx_tables.local_id_root.unwrap(); | |
442 | ||
443 | for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() { | |
444 | let hir_id = hir::HirId { | |
445 | owner: common_local_id_root.index, | |
446 | local_id, | |
447 | }; | |
448 | let fn_sig = self.resolve(fn_sig, &hir_id); | |
ff7c6d11 XL |
449 | self.tables |
450 | .liberated_fn_sigs_mut() | |
451 | .insert(hir_id, fn_sig.clone()); | |
92a42be0 SL |
452 | } |
453 | } | |
454 | ||
32a655c1 | 455 | fn visit_fru_field_types(&mut self) { |
3b2f2976 XL |
456 | let fcx_tables = self.fcx.tables.borrow(); |
457 | debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); | |
458 | let common_local_id_root = fcx_tables.local_id_root.unwrap(); | |
459 | ||
460 | for (&local_id, ftys) in fcx_tables.fru_field_types().iter() { | |
461 | let hir_id = hir::HirId { | |
462 | owner: common_local_id_root.index, | |
463 | local_id, | |
464 | }; | |
465 | let ftys = self.resolve(ftys, &hir_id); | |
466 | self.tables.fru_field_types_mut().insert(hir_id, ftys); | |
7453a54e SL |
467 | } |
468 | } | |
469 | ||
cc61c64b | 470 | fn resolve<T>(&self, x: &T, span: &Locatable) -> T::Lifted |
ff7c6d11 XL |
471 | where |
472 | T: TypeFoldable<'tcx> + ty::Lift<'gcx>, | |
a7813a04 | 473 | { |
cc61c64b | 474 | let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body)); |
a7813a04 XL |
475 | if let Some(lifted) = self.tcx().lift_to_global(&x) { |
476 | lifted | |
477 | } else { | |
ff7c6d11 XL |
478 | span_bug!( |
479 | span.to_span(&self.fcx.tcx), | |
480 | "writeback: `{:?}` missing from the global type context", | |
481 | x | |
482 | ); | |
a7813a04 | 483 | } |
1a4d82fc JJ |
484 | } |
485 | } | |
486 | ||
cc61c64b XL |
487 | trait Locatable { |
488 | fn to_span(&self, tcx: &TyCtxt) -> Span; | |
1a4d82fc JJ |
489 | } |
490 | ||
cc61c64b | 491 | impl Locatable for Span { |
ff7c6d11 XL |
492 | fn to_span(&self, _: &TyCtxt) -> Span { |
493 | *self | |
494 | } | |
cc61c64b XL |
495 | } |
496 | ||
497 | impl Locatable for ast::NodeId { | |
ff7c6d11 XL |
498 | fn to_span(&self, tcx: &TyCtxt) -> Span { |
499 | tcx.hir.span(*self) | |
500 | } | |
1a4d82fc JJ |
501 | } |
502 | ||
3b2f2976 XL |
503 | impl Locatable for DefIndex { |
504 | fn to_span(&self, tcx: &TyCtxt) -> Span { | |
505 | let node_id = tcx.hir.def_index_to_node_id(*self); | |
506 | tcx.hir.span(node_id) | |
507 | } | |
508 | } | |
509 | ||
510 | impl Locatable for hir::HirId { | |
511 | fn to_span(&self, tcx: &TyCtxt) -> Span { | |
512 | let node_id = tcx.hir.definitions().find_node_for_hir_id(*self); | |
513 | tcx.hir.span(node_id) | |
514 | } | |
515 | } | |
516 | ||
1a4d82fc JJ |
517 | /////////////////////////////////////////////////////////////////////////// |
518 | // The Resolver. This is the type folding engine that detects | |
519 | // unresolved types and so forth. | |
520 | ||
ff7c6d11 | 521 | struct Resolver<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> { |
a7813a04 XL |
522 | tcx: TyCtxt<'cx, 'gcx, 'tcx>, |
523 | infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, | |
cc61c64b XL |
524 | span: &'cx Locatable, |
525 | body: &'gcx hir::Body, | |
1a4d82fc JJ |
526 | } |
527 | ||
a7813a04 | 528 | impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { |
ff7c6d11 XL |
529 | fn new( |
530 | fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, | |
531 | span: &'cx Locatable, | |
532 | body: &'gcx hir::Body, | |
533 | ) -> Resolver<'cx, 'gcx, 'tcx> { | |
cc61c64b XL |
534 | Resolver { |
535 | tcx: fcx.tcx, | |
536 | infcx: fcx, | |
3b2f2976 XL |
537 | span, |
538 | body, | |
cc61c64b | 539 | } |
1a4d82fc JJ |
540 | } |
541 | ||
cc61c64b | 542 | fn report_error(&self, t: Ty<'tcx>) { |
1a4d82fc | 543 | if !self.tcx.sess.has_errors() { |
ff7c6d11 XL |
544 | self.infcx |
545 | .need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t); | |
1a4d82fc JJ |
546 | } |
547 | } | |
548 | } | |
549 | ||
a7813a04 XL |
550 | impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Resolver<'cx, 'gcx, 'tcx> { |
551 | fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { | |
1a4d82fc JJ |
552 | self.tcx |
553 | } | |
554 | ||
555 | fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { | |
556 | match self.infcx.fully_resolve(&t) { | |
557 | Ok(t) => t, | |
cc61c64b | 558 | Err(_) => { |
ff7c6d11 XL |
559 | debug!( |
560 | "Resolver::fold_ty: input type `{:?}` not fully resolvable", | |
561 | t | |
562 | ); | |
cc61c64b | 563 | self.report_error(t); |
1a4d82fc JJ |
564 | self.tcx().types.err |
565 | } | |
566 | } | |
567 | } | |
568 | ||
cc61c64b XL |
569 | // FIXME This should be carefully checked |
570 | // We could use `self.report_error` but it doesn't accept a ty::Region, right now. | |
7cac9316 | 571 | fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { |
1a4d82fc JJ |
572 | match self.infcx.fully_resolve(&r) { |
573 | Ok(r) => r, | |
ff7c6d11 | 574 | Err(_) => self.tcx.types.re_static, |
1a4d82fc JJ |
575 | } |
576 | } | |
577 | } | |
578 | ||
579 | /////////////////////////////////////////////////////////////////////////// | |
580 | // During type check, we store promises with the result of trait | |
581 | // lookup rather than the actual results (because the results are not | |
582 | // necessarily available immediately). These routines unwind the | |
583 | // promises. It is expected that we will have already reported any | |
584 | // errors that may be encountered, so if the promises store an error, | |
585 | // a dummy result is returned. |