1 use super::{InferCtxt, FixupError, FixupResult}
;
2 use crate::ty
::{self, Ty, TyCtxt, TypeFoldable}
;
3 use crate::ty
::fold
::{TypeFolder, TypeVisitor}
;
5 ///////////////////////////////////////////////////////////////////////////
6 // OPPORTUNISTIC TYPE RESOLVER
8 /// The opportunistic type resolver can be used at any time. It simply replaces
9 /// type variables that have been unified with the things they have
10 /// been unified with (similar to `shallow_resolve`, but deep). This is
11 /// useful for printing messages etc but also required at various
12 /// points for correctness.
13 pub struct OpportunisticTypeResolver
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
14 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
17 impl<'a
, 'gcx
, 'tcx
> OpportunisticTypeResolver
<'a
, 'gcx
, 'tcx
> {
19 pub fn new(infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>) -> Self {
20 OpportunisticTypeResolver { infcx }
24 impl<'a
, 'gcx
, 'tcx
> TypeFolder
<'gcx
, 'tcx
> for OpportunisticTypeResolver
<'a
, 'gcx
, 'tcx
> {
25 fn tcx
<'b
>(&'b
self) -> TyCtxt
<'b
, 'gcx
, 'tcx
> {
29 fn fold_ty(&mut self, t
: Ty
<'tcx
>) -> Ty
<'tcx
> {
30 if !t
.has_infer_types() {
31 t
// micro-optimize -- if there is nothing in this type that this fold affects...
33 let t0
= self.infcx
.shallow_resolve(t
);
34 t0
.super_fold_with(self)
39 /// The opportunistic type and region resolver is similar to the
40 /// opportunistic type resolver, but also opportunistically resolves
41 /// regions. It is useful for canonicalization.
42 pub struct OpportunisticTypeAndRegionResolver
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
43 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
46 impl<'a
, 'gcx
, 'tcx
> OpportunisticTypeAndRegionResolver
<'a
, 'gcx
, 'tcx
> {
47 pub fn new(infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>) -> Self {
48 OpportunisticTypeAndRegionResolver { infcx }
52 impl<'a
, 'gcx
, 'tcx
> TypeFolder
<'gcx
, 'tcx
> for OpportunisticTypeAndRegionResolver
<'a
, 'gcx
, 'tcx
> {
53 fn tcx
<'b
>(&'b
self) -> TyCtxt
<'b
, 'gcx
, 'tcx
> {
57 fn fold_ty(&mut self, t
: Ty
<'tcx
>) -> Ty
<'tcx
> {
59 t
// micro-optimize -- if there is nothing in this type that this fold affects...
61 let t0
= self.infcx
.shallow_resolve(t
);
62 t0
.super_fold_with(self)
66 fn fold_region(&mut self, r
: ty
::Region
<'tcx
>) -> ty
::Region
<'tcx
> {
69 self.infcx
.borrow_region_constraints()
70 .opportunistic_resolve_var(self.tcx(), rid
),
77 ///////////////////////////////////////////////////////////////////////////
78 // UNRESOLVED TYPE FINDER
80 /// The unresolved type **finder** walks your type and searches for
81 /// type variables that don't yet have a value. They get pushed into a
82 /// vector. It does not construct the fully resolved type (which might
83 /// involve some hashing and so forth).
84 pub struct UnresolvedTypeFinder
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
85 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
88 impl<'a
, 'gcx
, 'tcx
> UnresolvedTypeFinder
<'a
, 'gcx
, 'tcx
> {
89 pub fn new(infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>) -> Self {
90 UnresolvedTypeFinder { infcx }
94 impl<'a
, 'gcx
, 'tcx
> TypeVisitor
<'tcx
> for UnresolvedTypeFinder
<'a
, 'gcx
, 'tcx
> {
95 fn visit_ty(&mut self, t
: Ty
<'tcx
>) -> bool
{
96 let t
= self.infcx
.shallow_resolve(t
);
97 if t
.has_infer_types() {
98 if let ty
::Infer(_
) = t
.sty
{
99 // Since we called `shallow_resolve` above, this must
100 // be an (as yet...) unresolved inference variable.
103 // Otherwise, visit its contents.
104 t
.super_visit_with(self)
107 // Micro-optimize: no inference types at all Can't have unresolved type
108 // variables, no need to visit the contents.
114 ///////////////////////////////////////////////////////////////////////////
115 // FULL TYPE RESOLUTION
117 /// Full type resolution replaces all type and region variables with
118 /// their concrete results. If any variable cannot be replaced (never unified, etc)
119 /// then an `Err` result is returned.
120 pub fn fully_resolve
<'a
, 'gcx
, 'tcx
, T
>(infcx
: &InferCtxt
<'a
, 'gcx
, 'tcx
>,
121 value
: &T
) -> FixupResult
<T
>
122 where T
: TypeFoldable
<'tcx
>
124 let mut full_resolver
= FullTypeResolver { infcx: infcx, err: None }
;
125 let result
= value
.fold_with(&mut full_resolver
);
126 match full_resolver
.err
{
132 // N.B. This type is not public because the protocol around checking the
133 // `err` field is not enforcable otherwise.
134 struct FullTypeResolver
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
135 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
136 err
: Option
<FixupError
>,
139 impl<'a
, 'gcx
, 'tcx
> TypeFolder
<'gcx
, 'tcx
> for FullTypeResolver
<'a
, 'gcx
, 'tcx
> {
140 fn tcx
<'b
>(&'b
self) -> TyCtxt
<'b
, 'gcx
, 'tcx
> {
144 fn fold_ty(&mut self, t
: Ty
<'tcx
>) -> Ty
<'tcx
> {
145 if !t
.needs_infer() && !ty
::keep_local(&t
) {
146 t
// micro-optimize -- if there is nothing in this type that this fold affects...
147 // ^ we need to have the `keep_local` check to un-default
150 let t
= self.infcx
.shallow_resolve(t
);
152 ty
::Infer(ty
::TyVar(vid
)) => {
153 self.err
= Some(FixupError
::UnresolvedTy(vid
));
156 ty
::Infer(ty
::IntVar(vid
)) => {
157 self.err
= Some(FixupError
::UnresolvedIntTy(vid
));
160 ty
::Infer(ty
::FloatVar(vid
)) => {
161 self.err
= Some(FixupError
::UnresolvedFloatTy(vid
));
165 bug
!("Unexpected type in full type resolver: {:?}", t
);
168 t
.super_fold_with(self)
174 fn fold_region(&mut self, r
: ty
::Region
<'tcx
>) -> ty
::Region
<'tcx
> {
176 ty
::ReVar(rid
) => self.infcx
.lexical_region_resolutions
179 .expect("region resolution not performed")