]>
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. | |
14 | use self::ResolveReason::*; | |
15 | ||
16 | use astconv::AstConv; | |
17 | use check::FnCtxt; | |
e9174d1e | 18 | use middle::def_id::DefId; |
1a4d82fc | 19 | use middle::pat_util; |
9cc50fc6 | 20 | use middle::ty::{self, Ty, MethodCall, MethodCallee}; |
e9174d1e SL |
21 | use middle::ty::adjustment; |
22 | use middle::ty::fold::{TypeFolder,TypeFoldable}; | |
1a4d82fc JJ |
23 | use middle::infer; |
24 | use write_substs_to_tcx; | |
25 | use write_ty_to_tcx; | |
1a4d82fc JJ |
26 | |
27 | use std::cell::Cell; | |
28 | ||
29 | use syntax::ast; | |
30 | use syntax::codemap::{DUMMY_SP, Span}; | |
e9174d1e | 31 | use rustc_front::print::pprust::pat_to_string; |
92a42be0 | 32 | use rustc_front::intravisit::{self, Visitor}; |
e9174d1e SL |
33 | use rustc_front::util as hir_util; |
34 | use rustc_front::hir; | |
1a4d82fc JJ |
35 | |
36 | /////////////////////////////////////////////////////////////////////////// | |
37 | // Entry point functions | |
38 | ||
e9174d1e | 39 | pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &hir::Expr) { |
1a4d82fc JJ |
40 | assert_eq!(fcx.writeback_errors.get(), false); |
41 | let mut wbcx = WritebackCx::new(fcx); | |
42 | wbcx.visit_expr(e); | |
43 | wbcx.visit_upvar_borrow_map(); | |
85aaf69f | 44 | wbcx.visit_closures(); |
92a42be0 | 45 | wbcx.visit_liberated_fn_sigs(); |
1a4d82fc JJ |
46 | } |
47 | ||
48 | pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, | |
e9174d1e SL |
49 | decl: &hir::FnDecl, |
50 | blk: &hir::Block) { | |
1a4d82fc JJ |
51 | assert_eq!(fcx.writeback_errors.get(), false); |
52 | let mut wbcx = WritebackCx::new(fcx); | |
53 | wbcx.visit_block(blk); | |
85aaf69f | 54 | for arg in &decl.inputs { |
1a4d82fc JJ |
55 | wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id); |
56 | wbcx.visit_pat(&*arg.pat); | |
57 | ||
58 | // Privacy needs the type for the whole pattern, not just each binding | |
92a42be0 | 59 | if !pat_util::pat_is_binding(&fcx.tcx().def_map.borrow(), &*arg.pat) { |
1a4d82fc JJ |
60 | wbcx.visit_node_id(ResolvingPattern(arg.pat.span), |
61 | arg.pat.id); | |
62 | } | |
63 | } | |
64 | wbcx.visit_upvar_borrow_map(); | |
85aaf69f | 65 | wbcx.visit_closures(); |
92a42be0 | 66 | wbcx.visit_liberated_fn_sigs(); |
1a4d82fc JJ |
67 | } |
68 | ||
69 | /////////////////////////////////////////////////////////////////////////// | |
70 | // The Writerback context. This visitor walks the AST, checking the | |
71 | // fn-specific tables to find references to types or regions. It | |
72 | // resolves those regions to remove inference variables and writes the | |
73 | // final result back into the master tables in the tcx. Here and | |
74 | // there, it applies a few ad-hoc checks that were not convenient to | |
75 | // do elsewhere. | |
76 | ||
77 | struct WritebackCx<'cx, 'tcx: 'cx> { | |
78 | fcx: &'cx FnCtxt<'cx, 'tcx>, | |
79 | } | |
80 | ||
81 | impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { | |
82 | fn new(fcx: &'cx FnCtxt<'cx, 'tcx>) -> WritebackCx<'cx, 'tcx> { | |
83 | WritebackCx { fcx: fcx } | |
84 | } | |
85 | ||
86 | fn tcx(&self) -> &'cx ty::ctxt<'tcx> { | |
87 | self.fcx.tcx() | |
88 | } | |
d9579d0f AL |
89 | |
90 | // Hacky hack: During type-checking, we treat *all* operators | |
91 | // as potentially overloaded. But then, during writeback, if | |
92 | // we observe that something like `a+b` is (known to be) | |
93 | // operating on scalars, we clear the overload. | |
e9174d1e | 94 | fn fix_scalar_binary_expr(&mut self, e: &hir::Expr) { |
b039eaaf SL |
95 | match e.node { |
96 | hir::ExprBinary(ref op, ref lhs, ref rhs) | | |
97 | hir::ExprAssignOp(ref op, ref lhs, ref rhs) => { | |
98 | let lhs_ty = self.fcx.node_ty(lhs.id); | |
99 | let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty); | |
100 | ||
101 | let rhs_ty = self.fcx.node_ty(rhs.id); | |
102 | let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty); | |
103 | ||
104 | if lhs_ty.is_scalar() && rhs_ty.is_scalar() { | |
105 | self.fcx.inh.tables.borrow_mut().method_map.remove(&MethodCall::expr(e.id)); | |
106 | ||
107 | // weird but true: the by-ref binops put an | |
108 | // adjustment on the lhs but not the rhs; the | |
109 | // adjustment for rhs is kind of baked into the | |
110 | // system. | |
111 | match e.node { | |
112 | hir::ExprBinary(..) => { | |
113 | if !hir_util::is_by_value_binop(op.node) { | |
114 | self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id); | |
115 | } | |
116 | }, | |
117 | hir::ExprAssignOp(..) => { | |
118 | self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id); | |
119 | }, | |
120 | _ => {}, | |
121 | } | |
122 | } else { | |
123 | let tcx = self.tcx(); | |
124 | ||
9cc50fc6 | 125 | if let hir::ExprAssignOp(_, ref lhs, ref rhs) = e.node { |
b039eaaf SL |
126 | if |
127 | !tcx.sess.features.borrow().augmented_assignments && | |
9cc50fc6 SL |
128 | !self.fcx.expr_ty(e).references_error() && |
129 | !self.fcx.expr_ty(lhs).references_error() && | |
130 | !self.fcx.expr_ty(rhs).references_error() | |
b039eaaf | 131 | { |
9cc50fc6 SL |
132 | tcx.sess.struct_span_err(e.span, |
133 | "overloaded augmented assignments \ | |
134 | are not stable") | |
135 | .fileline_help(e.span, | |
136 | "add #![feature(augmented_assignments)] to the \ | |
137 | crate root to enable") | |
138 | .emit() | |
b039eaaf SL |
139 | } |
140 | } | |
d9579d0f AL |
141 | } |
142 | } | |
b039eaaf | 143 | _ => {}, |
d9579d0f AL |
144 | } |
145 | } | |
1a4d82fc JJ |
146 | } |
147 | ||
148 | /////////////////////////////////////////////////////////////////////////// | |
149 | // Impl of Visitor for Resolver | |
150 | // | |
151 | // This is the master code which walks the AST. It delegates most of | |
152 | // the heavy lifting to the generic visit and resolve functions | |
153 | // below. In general, a function is made into a `visitor` if it must | |
154 | // traffic in node-ids or update tables in the type context etc. | |
155 | ||
156 | impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> { | |
e9174d1e | 157 | fn visit_stmt(&mut self, s: &hir::Stmt) { |
1a4d82fc JJ |
158 | if self.fcx.writeback_errors.get() { |
159 | return; | |
160 | } | |
161 | ||
e9174d1e | 162 | self.visit_node_id(ResolvingExpr(s.span), hir_util::stmt_id(s)); |
92a42be0 | 163 | intravisit::walk_stmt(self, s); |
1a4d82fc JJ |
164 | } |
165 | ||
e9174d1e | 166 | fn visit_expr(&mut self, e: &hir::Expr) { |
1a4d82fc JJ |
167 | if self.fcx.writeback_errors.get() { |
168 | return; | |
169 | } | |
170 | ||
d9579d0f | 171 | self.fix_scalar_binary_expr(e); |
c34b1796 | 172 | |
1a4d82fc JJ |
173 | self.visit_node_id(ResolvingExpr(e.span), e.id); |
174 | self.visit_method_map_entry(ResolvingExpr(e.span), | |
175 | MethodCall::expr(e.id)); | |
176 | ||
e9174d1e | 177 | if let hir::ExprClosure(_, ref decl, _) = e.node { |
d9579d0f AL |
178 | for input in &decl.inputs { |
179 | self.visit_node_id(ResolvingExpr(e.span), input.id); | |
1a4d82fc | 180 | } |
1a4d82fc JJ |
181 | } |
182 | ||
92a42be0 | 183 | intravisit::walk_expr(self, e); |
1a4d82fc JJ |
184 | } |
185 | ||
e9174d1e | 186 | fn visit_block(&mut self, b: &hir::Block) { |
1a4d82fc JJ |
187 | if self.fcx.writeback_errors.get() { |
188 | return; | |
189 | } | |
190 | ||
191 | self.visit_node_id(ResolvingExpr(b.span), b.id); | |
92a42be0 | 192 | intravisit::walk_block(self, b); |
1a4d82fc JJ |
193 | } |
194 | ||
e9174d1e | 195 | fn visit_pat(&mut self, p: &hir::Pat) { |
1a4d82fc JJ |
196 | if self.fcx.writeback_errors.get() { |
197 | return; | |
198 | } | |
199 | ||
200 | self.visit_node_id(ResolvingPattern(p.span), p.id); | |
201 | ||
62682a34 | 202 | debug!("Type for pattern binding {} (id {}) resolved to {:?}", |
1a4d82fc JJ |
203 | pat_to_string(p), |
204 | p.id, | |
c1a9b12d | 205 | self.tcx().node_id_to_type(p.id)); |
1a4d82fc | 206 | |
92a42be0 | 207 | intravisit::walk_pat(self, p); |
1a4d82fc JJ |
208 | } |
209 | ||
e9174d1e | 210 | fn visit_local(&mut self, l: &hir::Local) { |
1a4d82fc JJ |
211 | if self.fcx.writeback_errors.get() { |
212 | return; | |
213 | } | |
214 | ||
215 | let var_ty = self.fcx.local_ty(l.span, l.id); | |
216 | let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span)); | |
217 | write_ty_to_tcx(self.tcx(), l.id, var_ty); | |
92a42be0 | 218 | intravisit::walk_local(self, l); |
1a4d82fc JJ |
219 | } |
220 | ||
e9174d1e | 221 | fn visit_ty(&mut self, t: &hir::Ty) { |
1a4d82fc | 222 | match t.node { |
e9174d1e | 223 | hir::TyFixedLengthVec(ref ty, ref count_expr) => { |
1a4d82fc | 224 | self.visit_ty(&**ty); |
c34b1796 | 225 | write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.usize); |
1a4d82fc | 226 | } |
b039eaaf | 227 | hir::TyBareFn(ref function_declaration) => { |
92a42be0 | 228 | intravisit::walk_fn_decl_nopat(self, &function_declaration.decl); |
b039eaaf SL |
229 | walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes); |
230 | } | |
92a42be0 | 231 | _ => intravisit::walk_ty(self, t) |
1a4d82fc JJ |
232 | } |
233 | } | |
234 | } | |
235 | ||
236 | impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { | |
237 | fn visit_upvar_borrow_map(&self) { | |
238 | if self.fcx.writeback_errors.get() { | |
239 | return; | |
240 | } | |
241 | ||
c1a9b12d | 242 | for (upvar_id, upvar_capture) in self.fcx.inh.tables.borrow().upvar_capture_map.iter() { |
85aaf69f SL |
243 | let new_upvar_capture = match *upvar_capture { |
244 | ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, | |
245 | ty::UpvarCapture::ByRef(ref upvar_borrow) => { | |
246 | let r = upvar_borrow.region; | |
247 | let r = self.resolve(&r, ResolvingUpvar(*upvar_id)); | |
248 | ty::UpvarCapture::ByRef( | |
249 | ty::UpvarBorrow { kind: upvar_borrow.kind, region: r }) | |
250 | } | |
251 | }; | |
62682a34 SL |
252 | debug!("Upvar capture for {:?} resolved to {:?}", |
253 | upvar_id, | |
254 | new_upvar_capture); | |
c1a9b12d SL |
255 | self.fcx.tcx() |
256 | .tables | |
257 | .borrow_mut() | |
258 | .upvar_capture_map | |
259 | .insert(*upvar_id, new_upvar_capture); | |
1a4d82fc JJ |
260 | } |
261 | } | |
262 | ||
85aaf69f | 263 | fn visit_closures(&self) { |
1a4d82fc JJ |
264 | if self.fcx.writeback_errors.get() { |
265 | return | |
266 | } | |
267 | ||
c1a9b12d | 268 | for (def_id, closure_ty) in self.fcx.inh.tables.borrow().closure_tys.iter() { |
85aaf69f | 269 | let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id)); |
c1a9b12d | 270 | self.fcx.tcx().tables.borrow_mut().closure_tys.insert(*def_id, closure_ty); |
85aaf69f SL |
271 | } |
272 | ||
c1a9b12d SL |
273 | for (def_id, &closure_kind) in self.fcx.inh.tables.borrow().closure_kinds.iter() { |
274 | self.fcx.tcx().tables.borrow_mut().closure_kinds.insert(*def_id, closure_kind); | |
1a4d82fc JJ |
275 | } |
276 | } | |
277 | ||
1a4d82fc JJ |
278 | fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) { |
279 | // Resolve any borrowings for the node with id `id` | |
280 | self.visit_adjustments(reason, id); | |
281 | ||
282 | // Resolve the type of the node with id `id` | |
283 | let n_ty = self.fcx.node_ty(id); | |
284 | let n_ty = self.resolve(&n_ty, reason); | |
285 | write_ty_to_tcx(self.tcx(), id, n_ty); | |
62682a34 | 286 | debug!("Node {} has type {:?}", id, n_ty); |
1a4d82fc JJ |
287 | |
288 | // Resolve any substitutions | |
289 | self.fcx.opt_node_ty_substs(id, |item_substs| { | |
290 | write_substs_to_tcx(self.tcx(), id, | |
291 | self.resolve(item_substs, reason)); | |
292 | }); | |
293 | } | |
294 | ||
295 | fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) { | |
c1a9b12d SL |
296 | let adjustments = self.fcx.inh.tables.borrow_mut().adjustments.remove(&id); |
297 | match adjustments { | |
1a4d82fc JJ |
298 | None => { |
299 | debug!("No adjustments for node {}", id); | |
300 | } | |
301 | ||
302 | Some(adjustment) => { | |
1a4d82fc | 303 | let resolved_adjustment = match adjustment { |
e9174d1e SL |
304 | adjustment::AdjustReifyFnPointer => { |
305 | adjustment::AdjustReifyFnPointer | |
306 | } | |
1a4d82fc | 307 | |
e9174d1e SL |
308 | adjustment::AdjustUnsafeFnPointer => { |
309 | adjustment::AdjustUnsafeFnPointer | |
c34b1796 AL |
310 | } |
311 | ||
e9174d1e | 312 | adjustment::AdjustDerefRef(adj) => { |
85aaf69f | 313 | for autoderef in 0..adj.autoderefs { |
9346a6ac | 314 | let method_call = MethodCall::autoderef(id, autoderef as u32); |
1a4d82fc JJ |
315 | self.visit_method_map_entry(reason, method_call); |
316 | } | |
317 | ||
e9174d1e | 318 | adjustment::AdjustDerefRef(adjustment::AutoDerefRef { |
1a4d82fc JJ |
319 | autoderefs: adj.autoderefs, |
320 | autoref: self.resolve(&adj.autoref, reason), | |
9346a6ac | 321 | unsize: self.resolve(&adj.unsize, reason), |
1a4d82fc JJ |
322 | }) |
323 | } | |
324 | }; | |
325 | debug!("Adjustments for node {}: {:?}", id, resolved_adjustment); | |
c1a9b12d | 326 | self.tcx().tables.borrow_mut().adjustments.insert( |
1a4d82fc JJ |
327 | id, resolved_adjustment); |
328 | } | |
329 | } | |
330 | } | |
331 | ||
332 | fn visit_method_map_entry(&self, | |
333 | reason: ResolveReason, | |
334 | method_call: MethodCall) { | |
335 | // Resolve any method map entry | |
c1a9b12d | 336 | let new_method = match self.fcx.inh.tables.borrow_mut().method_map.remove(&method_call) { |
1a4d82fc | 337 | Some(method) => { |
62682a34 | 338 | debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})", |
1a4d82fc | 339 | method_call, |
62682a34 | 340 | method); |
1a4d82fc | 341 | let new_method = MethodCallee { |
c1a9b12d | 342 | def_id: method.def_id, |
1a4d82fc | 343 | ty: self.resolve(&method.ty, reason), |
c1a9b12d | 344 | substs: self.tcx().mk_substs(self.resolve(method.substs, reason)), |
1a4d82fc JJ |
345 | }; |
346 | ||
c1a9b12d SL |
347 | Some(new_method) |
348 | } | |
349 | None => None | |
350 | }; | |
351 | ||
352 | //NB(jroesch): We need to match twice to avoid a double borrow which would cause an ICE | |
353 | match new_method { | |
354 | Some(method) => { | |
355 | self.tcx().tables.borrow_mut().method_map.insert( | |
1a4d82fc | 356 | method_call, |
c1a9b12d | 357 | method); |
1a4d82fc JJ |
358 | } |
359 | None => {} | |
360 | } | |
361 | } | |
362 | ||
92a42be0 SL |
363 | fn visit_liberated_fn_sigs(&self) { |
364 | for (&node_id, fn_sig) in self.fcx.inh.tables.borrow().liberated_fn_sigs.iter() { | |
365 | let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id)); | |
366 | self.tcx().tables.borrow_mut().liberated_fn_sigs.insert(node_id, fn_sig.clone()); | |
367 | } | |
368 | } | |
369 | ||
1a4d82fc JJ |
370 | fn resolve<T:TypeFoldable<'tcx>>(&self, t: &T, reason: ResolveReason) -> T { |
371 | t.fold_with(&mut Resolver::new(self.fcx, reason)) | |
372 | } | |
373 | } | |
374 | ||
375 | /////////////////////////////////////////////////////////////////////////// | |
376 | // Resolution reason. | |
377 | ||
c34b1796 | 378 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
379 | enum ResolveReason { |
380 | ResolvingExpr(Span), | |
381 | ResolvingLocal(Span), | |
382 | ResolvingPattern(Span), | |
383 | ResolvingUpvar(ty::UpvarId), | |
e9174d1e | 384 | ResolvingClosure(DefId), |
92a42be0 | 385 | ResolvingFnSig(ast::NodeId), |
1a4d82fc JJ |
386 | } |
387 | ||
388 | impl ResolveReason { | |
389 | fn span(&self, tcx: &ty::ctxt) -> Span { | |
390 | match *self { | |
391 | ResolvingExpr(s) => s, | |
392 | ResolvingLocal(s) => s, | |
393 | ResolvingPattern(s) => s, | |
394 | ResolvingUpvar(upvar_id) => { | |
c1a9b12d | 395 | tcx.expr_span(upvar_id.closure_expr_id) |
1a4d82fc | 396 | } |
92a42be0 SL |
397 | ResolvingFnSig(id) => { |
398 | tcx.map.span(id) | |
399 | } | |
85aaf69f | 400 | ResolvingClosure(did) => { |
b039eaaf SL |
401 | if let Some(node_id) = tcx.map.as_local_node_id(did) { |
402 | tcx.expr_span(node_id) | |
1a4d82fc JJ |
403 | } else { |
404 | DUMMY_SP | |
405 | } | |
406 | } | |
407 | } | |
408 | } | |
409 | } | |
410 | ||
411 | /////////////////////////////////////////////////////////////////////////// | |
412 | // The Resolver. This is the type folding engine that detects | |
413 | // unresolved types and so forth. | |
414 | ||
415 | struct Resolver<'cx, 'tcx: 'cx> { | |
416 | tcx: &'cx ty::ctxt<'tcx>, | |
417 | infcx: &'cx infer::InferCtxt<'cx, 'tcx>, | |
418 | writeback_errors: &'cx Cell<bool>, | |
419 | reason: ResolveReason, | |
420 | } | |
421 | ||
422 | impl<'cx, 'tcx> Resolver<'cx, 'tcx> { | |
423 | fn new(fcx: &'cx FnCtxt<'cx, 'tcx>, | |
424 | reason: ResolveReason) | |
425 | -> Resolver<'cx, 'tcx> | |
426 | { | |
427 | Resolver::from_infcx(fcx.infcx(), &fcx.writeback_errors, reason) | |
428 | } | |
429 | ||
430 | fn from_infcx(infcx: &'cx infer::InferCtxt<'cx, 'tcx>, | |
431 | writeback_errors: &'cx Cell<bool>, | |
432 | reason: ResolveReason) | |
433 | -> Resolver<'cx, 'tcx> | |
434 | { | |
435 | Resolver { infcx: infcx, | |
436 | tcx: infcx.tcx, | |
437 | writeback_errors: writeback_errors, | |
438 | reason: reason } | |
439 | } | |
440 | ||
c1a9b12d | 441 | fn report_error(&self, e: infer::FixupError) { |
1a4d82fc JJ |
442 | self.writeback_errors.set(true); |
443 | if !self.tcx.sess.has_errors() { | |
444 | match self.reason { | |
445 | ResolvingExpr(span) => { | |
446 | span_err!(self.tcx.sess, span, E0101, | |
447 | "cannot determine a type for this expression: {}", | |
448 | infer::fixup_err_to_string(e)); | |
449 | } | |
450 | ||
451 | ResolvingLocal(span) => { | |
452 | span_err!(self.tcx.sess, span, E0102, | |
453 | "cannot determine a type for this local variable: {}", | |
454 | infer::fixup_err_to_string(e)); | |
455 | } | |
456 | ||
457 | ResolvingPattern(span) => { | |
458 | span_err!(self.tcx.sess, span, E0103, | |
459 | "cannot determine a type for this pattern binding: {}", | |
460 | infer::fixup_err_to_string(e)); | |
461 | } | |
462 | ||
463 | ResolvingUpvar(upvar_id) => { | |
464 | let span = self.reason.span(self.tcx); | |
465 | span_err!(self.tcx.sess, span, E0104, | |
466 | "cannot resolve lifetime for captured variable `{}`: {}", | |
c1a9b12d | 467 | self.tcx.local_var_name_str(upvar_id.var_id).to_string(), |
1a4d82fc JJ |
468 | infer::fixup_err_to_string(e)); |
469 | } | |
470 | ||
85aaf69f | 471 | ResolvingClosure(_) => { |
1a4d82fc | 472 | let span = self.reason.span(self.tcx); |
85aaf69f SL |
473 | span_err!(self.tcx.sess, span, E0196, |
474 | "cannot determine a type for this closure") | |
1a4d82fc | 475 | } |
92a42be0 SL |
476 | |
477 | ResolvingFnSig(id) => { | |
478 | // any failures here should also fail when | |
479 | // resolving the patterns, closure types, or | |
480 | // something else. | |
481 | let span = self.reason.span(self.tcx); | |
482 | self.tcx.sess.delay_span_bug( | |
483 | span, | |
484 | &format!("cannot resolve some aspect of fn sig for {:?}", id)); | |
485 | } | |
1a4d82fc JJ |
486 | } |
487 | } | |
488 | } | |
489 | } | |
490 | ||
491 | impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { | |
492 | fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { | |
493 | self.tcx | |
494 | } | |
495 | ||
496 | fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { | |
497 | match self.infcx.fully_resolve(&t) { | |
498 | Ok(t) => t, | |
499 | Err(e) => { | |
62682a34 SL |
500 | debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", |
501 | t); | |
1a4d82fc JJ |
502 | self.report_error(e); |
503 | self.tcx().types.err | |
504 | } | |
505 | } | |
506 | } | |
507 | ||
508 | fn fold_region(&mut self, r: ty::Region) -> ty::Region { | |
509 | match self.infcx.fully_resolve(&r) { | |
510 | Ok(r) => r, | |
511 | Err(e) => { | |
512 | self.report_error(e); | |
513 | ty::ReStatic | |
514 | } | |
515 | } | |
516 | } | |
517 | } | |
518 | ||
519 | /////////////////////////////////////////////////////////////////////////// | |
520 | // During type check, we store promises with the result of trait | |
521 | // lookup rather than the actual results (because the results are not | |
522 | // necessarily available immediately). These routines unwind the | |
523 | // promises. It is expected that we will have already reported any | |
524 | // errors that may be encountered, so if the promises store an error, | |
525 | // a dummy result is returned. |