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
5 use crate::check
::FnCtxt
;
7 use rustc_errors
::ErrorReported
;
9 use rustc_hir
::intravisit
::{self, NestedVisitorMap, Visitor}
;
10 use rustc_infer
::infer
::error_reporting
::TypeAnnotationNeeded
::E0282
;
11 use rustc_infer
::infer
::InferCtxt
;
12 use rustc_middle
::ty
::adjustment
::{Adjust, Adjustment, PointerCast}
;
13 use rustc_middle
::ty
::fold
::{TypeFoldable, TypeFolder}
;
14 use rustc_middle
::ty
::{self, Ty, TyCtxt}
;
15 use rustc_span
::symbol
::sym
;
17 use rustc_trait_selection
::opaque_types
::InferCtxtExt
;
21 ///////////////////////////////////////////////////////////////////////////
24 // During type inference, partially inferred types are
25 // represented using Type variables (ty::Infer). These don't appear in
26 // the final TypeckResults since all of the types should have been
27 // inferred once typeck is done.
28 // When type inference is running however, having to update the typeck
29 // typeck results every time a new type is inferred would be unreasonably slow,
30 // so instead all of the replacement happens at the end in
31 // resolve_type_vars_in_body, which creates a new TypeTables which
32 // doesn't contain any inference types.
33 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
34 pub fn resolve_type_vars_in_body(
36 body
: &'tcx hir
::Body
<'tcx
>,
37 ) -> &'tcx ty
::TypeckResults
<'tcx
> {
38 let item_id
= self.tcx
.hir().body_owner(body
.id());
39 let item_def_id
= self.tcx
.hir().local_def_id(item_id
);
41 // This attribute causes us to dump some writeback information
42 // in the form of errors, which is uSymbol for unit tests.
43 let rustc_dump_user_substs
=
44 self.tcx
.has_attr(item_def_id
.to_def_id(), sym
::rustc_dump_user_substs
);
46 let mut wbcx
= WritebackCx
::new(self, body
, rustc_dump_user_substs
);
47 for param
in body
.params
{
48 wbcx
.visit_node_id(param
.pat
.span
, param
.hir_id
);
50 // Type only exists for constants and statics, not functions.
51 match self.tcx
.hir().body_owner_kind(item_id
) {
52 hir
::BodyOwnerKind
::Const
| hir
::BodyOwnerKind
::Static(_
) => {
53 wbcx
.visit_node_id(body
.value
.span
, item_id
);
55 hir
::BodyOwnerKind
::Closure
| hir
::BodyOwnerKind
::Fn
=> (),
57 wbcx
.visit_body(body
);
58 wbcx
.visit_upvar_capture_map();
59 wbcx
.visit_closures();
60 wbcx
.visit_liberated_fn_sigs();
61 wbcx
.visit_fru_field_types();
62 wbcx
.visit_opaque_types(body
.value
.span
);
63 wbcx
.visit_coercion_casts();
64 wbcx
.visit_user_provided_tys();
65 wbcx
.visit_user_provided_sigs();
66 wbcx
.visit_generator_interior_types();
68 let used_trait_imports
=
69 mem
::take(&mut self.typeck_results
.borrow_mut().used_trait_imports
);
70 debug
!("used_trait_imports({:?}) = {:?}", item_def_id
, used_trait_imports
);
71 wbcx
.typeck_results
.used_trait_imports
= used_trait_imports
;
73 wbcx
.typeck_results
.closure_captures
=
74 mem
::take(&mut self.typeck_results
.borrow_mut().closure_captures
);
76 if self.is_tainted_by_errors() {
77 // FIXME(eddyb) keep track of `ErrorReported` from where the error was emitted.
78 wbcx
.typeck_results
.tainted_by_errors
= Some(ErrorReported
);
81 debug
!("writeback: typeck results for {:?} are {:#?}", item_def_id
, wbcx
.typeck_results
);
83 self.tcx
.arena
.alloc(wbcx
.typeck_results
)
87 ///////////////////////////////////////////////////////////////////////////
88 // The Writeback context. This visitor walks the AST, checking the
89 // fn-specific typeck results to find references to types or regions. It
90 // resolves those regions to remove inference variables and writes the
91 // final result back into the master typeck results in the tcx. Here and
92 // there, it applies a few ad-hoc checks that were not convenient to
95 struct WritebackCx
<'cx
, 'tcx
> {
96 fcx
: &'cx FnCtxt
<'cx
, 'tcx
>,
98 typeck_results
: ty
::TypeckResults
<'tcx
>,
100 body
: &'tcx hir
::Body
<'tcx
>,
102 rustc_dump_user_substs
: bool
,
105 impl<'cx
, 'tcx
> WritebackCx
<'cx
, 'tcx
> {
107 fcx
: &'cx FnCtxt
<'cx
, 'tcx
>,
108 body
: &'tcx hir
::Body
<'tcx
>,
109 rustc_dump_user_substs
: bool
,
110 ) -> WritebackCx
<'cx
, 'tcx
> {
111 let owner
= body
.id().hir_id
.owner
;
115 typeck_results
: ty
::TypeckResults
::new(owner
),
117 rustc_dump_user_substs
,
121 fn tcx(&self) -> TyCtxt
<'tcx
> {
125 fn write_ty_to_typeck_results(&mut self, hir_id
: hir
::HirId
, ty
: Ty
<'tcx
>) {
126 debug
!("write_ty_to_typeck_results({:?}, {:?})", hir_id
, ty
);
127 assert
!(!ty
.needs_infer() && !ty
.has_placeholders() && !ty
.has_free_regions());
128 self.typeck_results
.node_types_mut().insert(hir_id
, ty
);
131 // Hacky hack: During type-checking, we treat *all* operators
132 // as potentially overloaded. But then, during writeback, if
133 // we observe that something like `a+b` is (known to be)
134 // operating on scalars, we clear the overload.
135 fn fix_scalar_builtin_expr(&mut self, e
: &hir
::Expr
<'_
>) {
137 hir
::ExprKind
::Unary(hir
::UnOp
::UnNeg
| hir
::UnOp
::UnNot
, ref inner
) => {
138 let inner_ty
= self.fcx
.node_ty(inner
.hir_id
);
139 let inner_ty
= self.fcx
.resolve_vars_if_possible(&inner_ty
);
141 if inner_ty
.is_scalar() {
142 let mut typeck_results
= self.fcx
.typeck_results
.borrow_mut();
143 typeck_results
.type_dependent_defs_mut().remove(e
.hir_id
);
144 typeck_results
.node_substs_mut().remove(e
.hir_id
);
147 hir
::ExprKind
::Binary(ref op
, ref lhs
, ref rhs
)
148 | hir
::ExprKind
::AssignOp(ref op
, ref lhs
, ref rhs
) => {
149 let lhs_ty
= self.fcx
.node_ty(lhs
.hir_id
);
150 let lhs_ty
= self.fcx
.resolve_vars_if_possible(&lhs_ty
);
152 let rhs_ty
= self.fcx
.node_ty(rhs
.hir_id
);
153 let rhs_ty
= self.fcx
.resolve_vars_if_possible(&rhs_ty
);
155 if lhs_ty
.is_scalar() && rhs_ty
.is_scalar() {
156 let mut typeck_results
= self.fcx
.typeck_results
.borrow_mut();
157 typeck_results
.type_dependent_defs_mut().remove(e
.hir_id
);
158 typeck_results
.node_substs_mut().remove(e
.hir_id
);
161 hir
::ExprKind
::Binary(..) => {
162 if !op
.node
.is_by_value() {
163 let mut adjustments
= typeck_results
.adjustments_mut();
164 if let Some(a
) = adjustments
.get_mut(lhs
.hir_id
) {
167 if let Some(a
) = adjustments
.get_mut(rhs
.hir_id
) {
172 hir
::ExprKind
::AssignOp(..) => {
173 if let Some(a
) = typeck_results
.adjustments_mut().get_mut(lhs
.hir_id
) {
185 // Similar to operators, indexing is always assumed to be overloaded
186 // Here, correct cases where an indexing expression can be simplified
187 // to use builtin indexing because the index type is known to be
189 fn fix_index_builtin_expr(&mut self, e
: &hir
::Expr
<'_
>) {
190 if let hir
::ExprKind
::Index(ref base
, ref index
) = e
.kind
{
191 let mut typeck_results
= self.fcx
.typeck_results
.borrow_mut();
193 // All valid indexing looks like this; might encounter non-valid indexes at this point.
194 let base_ty
= typeck_results
.expr_ty_adjusted_opt(&base
).map(|t
| t
.kind());
195 if base_ty
.is_none() {
196 // When encountering `return [0][0]` outside of a `fn` body we can encounter a base
197 // that isn't in the type table. We assume more relevant errors have already been
198 // emitted, so we delay an ICE if none have. (#64638)
199 self.tcx().sess
.delay_span_bug(e
.span
, &format
!("bad base: `{:?}`", base
));
201 if let Some(ty
::Ref(_
, base_ty
, _
)) = base_ty
{
202 let index_ty
= typeck_results
.expr_ty_adjusted_opt(&index
).unwrap_or_else(|| {
203 // When encountering `return [0][0]` outside of a `fn` body we would attempt
204 // to access an unexistend index. We assume that more relevant errors will
205 // already have been emitted, so we only gate on this with an ICE if no
206 // error has been emitted. (#64638)
207 self.fcx
.tcx
.ty_error_with_message(
209 &format
!("bad index {:?} for base: `{:?}`", index
, base
),
212 let index_ty
= self.fcx
.resolve_vars_if_possible(&index_ty
);
214 if base_ty
.builtin_index().is_some() && index_ty
== self.fcx
.tcx
.types
.usize {
215 // Remove the method call record
216 typeck_results
.type_dependent_defs_mut().remove(e
.hir_id
);
217 typeck_results
.node_substs_mut().remove(e
.hir_id
);
219 if let Some(a
) = typeck_results
.adjustments_mut().get_mut(base
.hir_id
) {
220 // Discard the need for a mutable borrow
222 // Extra adjustment made when indexing causes a drop
223 // of size information - we need to get rid of it
224 // Since this is "after" the other adjustment to be
225 // discarded, we do an extra `pop()`
226 if let Some(Adjustment
{
227 kind
: Adjust
::Pointer(PointerCast
::Unsize
), ..
230 // So the borrow discard actually happens here
240 ///////////////////////////////////////////////////////////////////////////
241 // Impl of Visitor for Resolver
243 // This is the master code which walks the AST. It delegates most of
244 // the heavy lifting to the generic visit and resolve functions
245 // below. In general, a function is made into a `visitor` if it must
246 // traffic in node-ids or update typeck results in the type context etc.
248 impl<'cx
, 'tcx
> Visitor
<'tcx
> for WritebackCx
<'cx
, 'tcx
> {
249 type Map
= intravisit
::ErasedMap
<'tcx
>;
251 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
252 NestedVisitorMap
::None
255 fn visit_expr(&mut self, e
: &'tcx hir
::Expr
<'tcx
>) {
256 self.fix_scalar_builtin_expr(e
);
257 self.fix_index_builtin_expr(e
);
259 self.visit_node_id(e
.span
, e
.hir_id
);
262 hir
::ExprKind
::Closure(_
, _
, body
, _
, _
) => {
263 let body
= self.fcx
.tcx
.hir().body(body
);
264 for param
in body
.params
{
265 self.visit_node_id(e
.span
, param
.hir_id
);
268 self.visit_body(body
);
270 hir
::ExprKind
::Struct(_
, fields
, _
) => {
271 for field
in fields
{
272 self.visit_field_id(field
.hir_id
);
275 hir
::ExprKind
::Field(..) => {
276 self.visit_field_id(e
.hir_id
);
281 intravisit
::walk_expr(self, e
);
284 fn visit_block(&mut self, b
: &'tcx hir
::Block
<'tcx
>) {
285 self.visit_node_id(b
.span
, b
.hir_id
);
286 intravisit
::walk_block(self, b
);
289 fn visit_pat(&mut self, p
: &'tcx hir
::Pat
<'tcx
>) {
291 hir
::PatKind
::Binding(..) => {
292 let typeck_results
= self.fcx
.typeck_results
.borrow();
294 typeck_results
.extract_binding_mode(self.tcx().sess
, p
.hir_id
, p
.span
)
296 self.typeck_results
.pat_binding_modes_mut().insert(p
.hir_id
, bm
);
299 hir
::PatKind
::Struct(_
, fields
, _
) => {
300 for field
in fields
{
301 self.visit_field_id(field
.hir_id
);
307 self.visit_pat_adjustments(p
.span
, p
.hir_id
);
309 self.visit_node_id(p
.span
, p
.hir_id
);
310 intravisit
::walk_pat(self, p
);
313 fn visit_local(&mut self, l
: &'tcx hir
::Local
<'tcx
>) {
314 intravisit
::walk_local(self, l
);
315 let var_ty
= self.fcx
.local_ty(l
.span
, l
.hir_id
).decl_ty
;
316 let var_ty
= self.resolve(&var_ty
, &l
.span
);
317 self.write_ty_to_typeck_results(l
.hir_id
, var_ty
);
320 fn visit_ty(&mut self, hir_ty
: &'tcx hir
::Ty
<'tcx
>) {
321 intravisit
::walk_ty(self, hir_ty
);
322 let ty
= self.fcx
.node_ty(hir_ty
.hir_id
);
323 let ty
= self.resolve(&ty
, &hir_ty
.span
);
324 self.write_ty_to_typeck_results(hir_ty
.hir_id
, ty
);
328 impl<'cx
, 'tcx
> WritebackCx
<'cx
, 'tcx
> {
329 fn visit_upvar_capture_map(&mut self) {
330 for (upvar_id
, upvar_capture
) in self.fcx
.typeck_results
.borrow().upvar_capture_map
.iter() {
331 let new_upvar_capture
= match *upvar_capture
{
332 ty
::UpvarCapture
::ByValue(span
) => ty
::UpvarCapture
::ByValue(span
),
333 ty
::UpvarCapture
::ByRef(ref upvar_borrow
) => {
334 ty
::UpvarCapture
::ByRef(ty
::UpvarBorrow
{
335 kind
: upvar_borrow
.kind
,
336 region
: self.tcx().lifetimes
.re_erased
,
340 debug
!("Upvar capture for {:?} resolved to {:?}", upvar_id
, new_upvar_capture
);
341 self.typeck_results
.upvar_capture_map
.insert(*upvar_id
, new_upvar_capture
);
345 fn visit_closures(&mut self) {
346 let fcx_typeck_results
= self.fcx
.typeck_results
.borrow();
347 assert_eq
!(fcx_typeck_results
.hir_owner
, self.typeck_results
.hir_owner
);
348 let common_hir_owner
= fcx_typeck_results
.hir_owner
;
350 for (&id
, &origin
) in fcx_typeck_results
.closure_kind_origins().iter() {
351 let hir_id
= hir
::HirId { owner: common_hir_owner, local_id: id }
;
352 self.typeck_results
.closure_kind_origins_mut().insert(hir_id
, origin
);
356 fn visit_coercion_casts(&mut self) {
357 let fcx_typeck_results
= self.fcx
.typeck_results
.borrow();
358 let fcx_coercion_casts
= fcx_typeck_results
.coercion_casts();
359 assert_eq
!(fcx_typeck_results
.hir_owner
, self.typeck_results
.hir_owner
);
361 for local_id
in fcx_coercion_casts
{
362 self.typeck_results
.set_coercion_cast(*local_id
);
366 fn visit_user_provided_tys(&mut self) {
367 let fcx_typeck_results
= self.fcx
.typeck_results
.borrow();
368 assert_eq
!(fcx_typeck_results
.hir_owner
, self.typeck_results
.hir_owner
);
369 let common_hir_owner
= fcx_typeck_results
.hir_owner
;
371 let mut errors_buffer
= Vec
::new();
372 for (&local_id
, c_ty
) in fcx_typeck_results
.user_provided_types().iter() {
373 let hir_id
= hir
::HirId { owner: common_hir_owner, local_id }
;
375 if cfg
!(debug_assertions
) && c_ty
.needs_infer() {
377 hir_id
.to_span(self.fcx
.tcx
),
378 "writeback: `{:?}` has inference variables",
383 self.typeck_results
.user_provided_types_mut().insert(hir_id
, *c_ty
);
385 if let ty
::UserType
::TypeOf(_
, user_substs
) = c_ty
.value
{
386 if self.rustc_dump_user_substs
{
387 // This is a unit-testing mechanism.
388 let span
= self.tcx().hir().span(hir_id
);
389 // We need to buffer the errors in order to guarantee a consistent
390 // order when emitting them.
394 .struct_span_err(span
, &format
!("user substs: {:?}", user_substs
));
395 err
.buffer(&mut errors_buffer
);
400 if !errors_buffer
.is_empty() {
401 errors_buffer
.sort_by_key(|diag
| diag
.span
.primary_span());
402 for diag
in errors_buffer
.drain(..) {
403 self.tcx().sess
.diagnostic().emit_diagnostic(&diag
);
408 fn visit_user_provided_sigs(&mut self) {
409 let fcx_typeck_results
= self.fcx
.typeck_results
.borrow();
410 assert_eq
!(fcx_typeck_results
.hir_owner
, self.typeck_results
.hir_owner
);
412 for (&def_id
, c_sig
) in fcx_typeck_results
.user_provided_sigs
.iter() {
413 if cfg
!(debug_assertions
) && c_sig
.needs_infer() {
415 self.fcx
.tcx
.hir().span_if_local(def_id
).unwrap(),
416 "writeback: `{:?}` has inference variables",
421 self.typeck_results
.user_provided_sigs
.insert(def_id
, *c_sig
);
425 fn visit_generator_interior_types(&mut self) {
426 let fcx_typeck_results
= self.fcx
.typeck_results
.borrow();
427 assert_eq
!(fcx_typeck_results
.hir_owner
, self.typeck_results
.hir_owner
);
428 self.typeck_results
.generator_interior_types
=
429 fcx_typeck_results
.generator_interior_types
.clone();
432 fn visit_opaque_types(&mut self, span
: Span
) {
433 for (&def_id
, opaque_defn
) in self.fcx
.opaque_types
.borrow().iter() {
434 let hir_id
= self.tcx().hir().local_def_id_to_hir_id(def_id
.expect_local());
435 let instantiated_ty
= self.resolve(&opaque_defn
.concrete_ty
, &hir_id
);
437 debug_assert
!(!instantiated_ty
.has_escaping_bound_vars());
440 // * `fn foo<T>() -> Foo<T>`
441 // * `fn foo<T: Bound + Other>() -> Foo<T>`
442 // from being defining.
444 // Also replace all generic params with the ones from the opaque type
445 // definition so that
447 // type Foo<T> = impl Baz + 'static;
448 // fn foo<U>() -> Foo<U> { .. }
450 // figures out the concrete type with `U`, but the stored type is with `T`.
451 let definition_ty
= self.fcx
.infer_opaque_definition_from_instantiation(
458 let mut skip_add
= false;
460 if let ty
::Opaque(defin_ty_def_id
, _substs
) = *definition_ty
.kind() {
461 if let hir
::OpaqueTyOrigin
::Misc
= opaque_defn
.origin
{
462 if def_id
== defin_ty_def_id
{
464 "skipping adding concrete definition for opaque type {:?} {:?}",
465 opaque_defn
, defin_ty_def_id
472 if !opaque_defn
.substs
.needs_infer() {
473 // We only want to add an entry into `concrete_opaque_types`
474 // if we actually found a defining usage of this opaque type.
475 // Otherwise, we do nothing - we'll either find a defining usage
476 // in some other location, or we'll end up emitting an error due
477 // to the lack of defining usage
479 let new
= ty
::ResolvedOpaqueTy
{
480 concrete_type
: definition_ty
,
481 substs
: opaque_defn
.substs
,
484 let old
= self.typeck_results
.concrete_opaque_types
.insert(def_id
, new
);
485 if let Some(old
) = old
{
486 if old
.concrete_type
!= definition_ty
|| old
.substs
!= opaque_defn
.substs
{
489 "`visit_opaque_types` tried to write different types for the same \
490 opaque type: {:?}, {:?}, {:?}, {:?}",
500 self.tcx().sess
.delay_span_bug(span
, "`opaque_defn` has inference variables");
505 fn visit_field_id(&mut self, hir_id
: hir
::HirId
) {
506 if let Some(index
) = self.fcx
.typeck_results
.borrow_mut().field_indices_mut().remove(hir_id
)
508 self.typeck_results
.field_indices_mut().insert(hir_id
, index
);
512 fn visit_node_id(&mut self, span
: Span
, hir_id
: hir
::HirId
) {
513 // Export associated path extensions and method resolutions.
515 self.fcx
.typeck_results
.borrow_mut().type_dependent_defs_mut().remove(hir_id
)
517 self.typeck_results
.type_dependent_defs_mut().insert(hir_id
, def
);
520 // Resolve any borrowings for the node with id `node_id`
521 self.visit_adjustments(span
, hir_id
);
523 // Resolve the type of the node with id `node_id`
524 let n_ty
= self.fcx
.node_ty(hir_id
);
525 let n_ty
= self.resolve(&n_ty
, &span
);
526 self.write_ty_to_typeck_results(hir_id
, n_ty
);
527 debug
!("node {:?} has type {:?}", hir_id
, n_ty
);
529 // Resolve any substitutions
530 if let Some(substs
) = self.fcx
.typeck_results
.borrow().node_substs_opt(hir_id
) {
531 let substs
= self.resolve(&substs
, &span
);
532 debug
!("write_substs_to_tcx({:?}, {:?})", hir_id
, substs
);
533 assert
!(!substs
.needs_infer() && !substs
.has_placeholders());
534 self.typeck_results
.node_substs_mut().insert(hir_id
, substs
);
538 fn visit_adjustments(&mut self, span
: Span
, hir_id
: hir
::HirId
) {
539 let adjustment
= self.fcx
.typeck_results
.borrow_mut().adjustments_mut().remove(hir_id
);
542 debug
!("no adjustments for node {:?}", hir_id
);
545 Some(adjustment
) => {
546 let resolved_adjustment
= self.resolve(&adjustment
, &span
);
547 debug
!("adjustments for node {:?}: {:?}", hir_id
, resolved_adjustment
);
548 self.typeck_results
.adjustments_mut().insert(hir_id
, resolved_adjustment
);
553 fn visit_pat_adjustments(&mut self, span
: Span
, hir_id
: hir
::HirId
) {
554 let adjustment
= self.fcx
.typeck_results
.borrow_mut().pat_adjustments_mut().remove(hir_id
);
557 debug
!("no pat_adjustments for node {:?}", hir_id
);
560 Some(adjustment
) => {
561 let resolved_adjustment
= self.resolve(&adjustment
, &span
);
562 debug
!("pat_adjustments for node {:?}: {:?}", hir_id
, resolved_adjustment
);
563 self.typeck_results
.pat_adjustments_mut().insert(hir_id
, resolved_adjustment
);
568 fn visit_liberated_fn_sigs(&mut self) {
569 let fcx_typeck_results
= self.fcx
.typeck_results
.borrow();
570 assert_eq
!(fcx_typeck_results
.hir_owner
, self.typeck_results
.hir_owner
);
571 let common_hir_owner
= fcx_typeck_results
.hir_owner
;
573 for (&local_id
, fn_sig
) in fcx_typeck_results
.liberated_fn_sigs().iter() {
574 let hir_id
= hir
::HirId { owner: common_hir_owner, local_id }
;
575 let fn_sig
= self.resolve(fn_sig
, &hir_id
);
576 self.typeck_results
.liberated_fn_sigs_mut().insert(hir_id
, fn_sig
);
580 fn visit_fru_field_types(&mut self) {
581 let fcx_typeck_results
= self.fcx
.typeck_results
.borrow();
582 assert_eq
!(fcx_typeck_results
.hir_owner
, self.typeck_results
.hir_owner
);
583 let common_hir_owner
= fcx_typeck_results
.hir_owner
;
585 for (&local_id
, ftys
) in fcx_typeck_results
.fru_field_types().iter() {
586 let hir_id
= hir
::HirId { owner: common_hir_owner, local_id }
;
587 let ftys
= self.resolve(ftys
, &hir_id
);
588 self.typeck_results
.fru_field_types_mut().insert(hir_id
, ftys
);
592 fn resolve
<T
>(&mut self, x
: &T
, span
: &dyn Locatable
) -> T
594 T
: TypeFoldable
<'tcx
>,
596 let mut resolver
= Resolver
::new(self.fcx
, span
, self.body
);
597 let x
= x
.fold_with(&mut resolver
);
598 if cfg
!(debug_assertions
) && x
.needs_infer() {
599 span_bug
!(span
.to_span(self.fcx
.tcx
), "writeback: `{:?}` has inference variables", x
);
602 // We may have introduced e.g. `ty::Error`, if inference failed, make sure
603 // to mark the `TypeckResults` as tainted in that case, so that downstream
604 // users of the typeck results don't produce extra errors, or worse, ICEs.
605 if resolver
.replaced_with_error
{
606 // FIXME(eddyb) keep track of `ErrorReported` from where the error was emitted.
607 self.typeck_results
.tainted_by_errors
= Some(ErrorReported
);
615 fn to_span(&self, tcx
: TyCtxt
<'_
>) -> Span
;
618 impl Locatable
for Span
{
619 fn to_span(&self, _
: TyCtxt
<'_
>) -> Span
{
624 impl Locatable
for hir
::HirId
{
625 fn to_span(&self, tcx
: TyCtxt
<'_
>) -> Span
{
626 tcx
.hir().span(*self)
630 /// The Resolver. This is the type folding engine that detects
631 /// unresolved types and so forth.
632 struct Resolver
<'cx
, 'tcx
> {
634 infcx
: &'cx InferCtxt
<'cx
, 'tcx
>,
635 span
: &'cx
dyn Locatable
,
636 body
: &'tcx hir
::Body
<'tcx
>,
638 /// Set to `true` if any `Ty` or `ty::Const` had to be replaced with an `Error`.
639 replaced_with_error
: bool
,
642 impl<'cx
, 'tcx
> Resolver
<'cx
, 'tcx
> {
644 fcx
: &'cx FnCtxt
<'cx
, 'tcx
>,
645 span
: &'cx
dyn Locatable
,
646 body
: &'tcx hir
::Body
<'tcx
>,
647 ) -> Resolver
<'cx
, 'tcx
> {
648 Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: false }
651 fn report_type_error(&self, t
: Ty
<'tcx
>) {
652 if !self.tcx
.sess
.has_errors() {
654 .emit_inference_failure_err(
655 Some(self.body
.id()),
656 self.span
.to_span(self.tcx
),
664 fn report_const_error(&self, c
: &'tcx ty
::Const
<'tcx
>) {
665 if !self.tcx
.sess
.has_errors() {
667 .emit_inference_failure_err(
668 Some(self.body
.id()),
669 self.span
.to_span(self.tcx
),
678 impl<'cx
, 'tcx
> TypeFolder
<'tcx
> for Resolver
<'cx
, 'tcx
> {
679 fn tcx
<'a
>(&'a
self) -> TyCtxt
<'tcx
> {
683 fn fold_ty(&mut self, t
: Ty
<'tcx
>) -> Ty
<'tcx
> {
684 match self.infcx
.fully_resolve(&t
) {
685 Ok(t
) => self.infcx
.tcx
.erase_regions(&t
),
687 debug
!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t
);
688 self.report_type_error(t
);
689 self.replaced_with_error
= true;
690 self.tcx().ty_error()
695 fn fold_region(&mut self, r
: ty
::Region
<'tcx
>) -> ty
::Region
<'tcx
> {
696 debug_assert
!(!r
.is_late_bound(), "Should not be resolving bound region.");
697 self.tcx
.lifetimes
.re_erased
700 fn fold_const(&mut self, ct
: &'tcx ty
::Const
<'tcx
>) -> &'tcx ty
::Const
<'tcx
> {
701 match self.infcx
.fully_resolve(&ct
) {
702 Ok(ct
) => self.infcx
.tcx
.erase_regions(&ct
),
704 debug
!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct
);
705 self.report_const_error(ct
);
706 self.replaced_with_error
= true;
707 self.tcx().const_error(ct
.ty
)
713 ///////////////////////////////////////////////////////////////////////////
714 // During type check, we store promises with the result of trait
715 // lookup rather than the actual results (because the results are not
716 // necessarily available immediately). These routines unwind the
717 // promises. It is expected that we will have already reported any
718 // errors that may be encountered, so if the promises store an error,
719 // a dummy result is returned.