|
10 | 10 |
|
11 | 11 |
|
12 | 12 | use middle::ty::{BuiltinBounds};
|
13 |
| -use middle::ty::RegionVid; |
14 | 13 | use middle::ty;
|
15 | 14 | use middle::typeck::infer::combine::*;
|
16 | 15 | use middle::typeck::infer::lattice::*;
|
17 | 16 | use middle::typeck::infer::equate::Equate;
|
18 |
| -use middle::typeck::infer::fold_regions_in_sig; |
19 |
| -use middle::typeck::infer::LateBoundRegionConversionTime::FnType; |
| 17 | +use middle::typeck::infer::higher_ranked::HigherRankedRelations; |
20 | 18 | use middle::typeck::infer::lub::Lub;
|
21 |
| -use middle::typeck::infer::region_inference::RegionMark; |
22 | 19 | use middle::typeck::infer::sub::Sub;
|
23 | 20 | use middle::typeck::infer::{cres, InferCtxt};
|
24 | 21 | use middle::typeck::infer::{TypeTrace, Subtype};
|
25 | 22 | use syntax::ast::{Many, Once, MutImmutable, MutMutable};
|
26 |
| -use syntax::ast::{NormalFn, UnsafeFn, NodeId}; |
| 23 | +use syntax::ast::{NormalFn, UnsafeFn}; |
27 | 24 | use syntax::ast::{Onceness, FnStyle};
|
28 |
| -use util::common::{indenter}; |
29 |
| -use util::nodemap::FnvHashMap; |
30 | 25 | use util::ppaux::mt_to_string;
|
31 | 26 | use util::ppaux::Repr;
|
32 | 27 |
|
@@ -128,139 +123,6 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> {
|
128 | 123 | }
|
129 | 124 |
|
130 | 125 | fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
|
131 |
| - // Note: this is a subtle algorithm. For a full explanation, |
132 |
| - // please see the large comment in `region_inference.rs`. |
133 |
| - |
134 |
| - debug!("{}.fn_sigs({}, {})", |
135 |
| - self.tag(), a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx)); |
136 |
| - let _indenter = indenter(); |
137 |
| - |
138 |
| - // Make a mark so we can examine "all bindings that were |
139 |
| - // created as part of this type comparison". |
140 |
| - let mark = self.fields.infcx.region_vars.mark(); |
141 |
| - |
142 |
| - // Instantiate each bound region with a fresh region variable. |
143 |
| - let (a_with_fresh, a_map) = |
144 |
| - self.fields.infcx.replace_late_bound_regions_with_fresh_var( |
145 |
| - a.binder_id, self.trace().span(), FnType, a); |
146 |
| - let a_vars = var_ids(self, &a_map); |
147 |
| - let (b_with_fresh, b_map) = |
148 |
| - self.fields.infcx.replace_late_bound_regions_with_fresh_var( |
149 |
| - b.binder_id, self.trace().span(), FnType, b); |
150 |
| - let b_vars = var_ids(self, &b_map); |
151 |
| - |
152 |
| - // Collect constraints. |
153 |
| - let sig0 = try!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh)); |
154 |
| - debug!("sig0 = {}", sig0.repr(self.fields.infcx.tcx)); |
155 |
| - |
156 |
| - // Generalize the regions appearing in fn_ty0 if possible |
157 |
| - let new_vars = |
158 |
| - self.fields.infcx.region_vars.vars_created_since_mark(mark); |
159 |
| - let sig1 = |
160 |
| - fold_regions_in_sig( |
161 |
| - self.fields.infcx.tcx, |
162 |
| - &sig0, |
163 |
| - |r| { |
164 |
| - generalize_region(self, |
165 |
| - mark, |
166 |
| - new_vars.as_slice(), |
167 |
| - sig0.binder_id, |
168 |
| - &a_map, |
169 |
| - a_vars.as_slice(), |
170 |
| - b_vars.as_slice(), |
171 |
| - r) |
172 |
| - }); |
173 |
| - debug!("sig1 = {}", sig1.repr(self.fields.infcx.tcx)); |
174 |
| - return Ok(sig1); |
175 |
| - |
176 |
| - fn generalize_region(this: &Glb, |
177 |
| - mark: RegionMark, |
178 |
| - new_vars: &[RegionVid], |
179 |
| - new_binder_id: NodeId, |
180 |
| - a_map: &FnvHashMap<ty::BoundRegion, ty::Region>, |
181 |
| - a_vars: &[RegionVid], |
182 |
| - b_vars: &[RegionVid], |
183 |
| - r0: ty::Region) -> ty::Region { |
184 |
| - if !is_var_in_set(new_vars, r0) { |
185 |
| - assert!(!r0.is_bound()); |
186 |
| - return r0; |
187 |
| - } |
188 |
| - |
189 |
| - let tainted = this.fields.infcx.region_vars.tainted(mark, r0); |
190 |
| - |
191 |
| - let mut a_r = None; |
192 |
| - let mut b_r = None; |
193 |
| - let mut only_new_vars = true; |
194 |
| - for r in tainted.iter() { |
195 |
| - if is_var_in_set(a_vars, *r) { |
196 |
| - if a_r.is_some() { |
197 |
| - return fresh_bound_variable(this, new_binder_id); |
198 |
| - } else { |
199 |
| - a_r = Some(*r); |
200 |
| - } |
201 |
| - } else if is_var_in_set(b_vars, *r) { |
202 |
| - if b_r.is_some() { |
203 |
| - return fresh_bound_variable(this, new_binder_id); |
204 |
| - } else { |
205 |
| - b_r = Some(*r); |
206 |
| - } |
207 |
| - } else if !is_var_in_set(new_vars, *r) { |
208 |
| - only_new_vars = false; |
209 |
| - } |
210 |
| - } |
211 |
| - |
212 |
| - // NB---I do not believe this algorithm computes |
213 |
| - // (necessarily) the GLB. As written it can |
214 |
| - // spuriously fail. In particular, if there is a case |
215 |
| - // like: |fn(&a)| and fn(fn(&b)), where a and b are |
216 |
| - // free, it will return fn(&c) where c = GLB(a,b). If |
217 |
| - // however this GLB is not defined, then the result is |
218 |
| - // an error, even though something like |
219 |
| - // "fn<X>(fn(&X))" where X is bound would be a |
220 |
| - // subtype of both of those. |
221 |
| - // |
222 |
| - // The problem is that if we were to return a bound |
223 |
| - // variable, we'd be computing a lower-bound, but not |
224 |
| - // necessarily the *greatest* lower-bound. |
225 |
| - // |
226 |
| - // Unfortunately, this problem is non-trivial to solve, |
227 |
| - // because we do not know at the time of computing the GLB |
228 |
| - // whether a GLB(a,b) exists or not, because we haven't |
229 |
| - // run region inference (or indeed, even fully computed |
230 |
| - // the region hierarchy!). The current algorithm seems to |
231 |
| - // works ok in practice. |
232 |
| - |
233 |
| - if a_r.is_some() && b_r.is_some() && only_new_vars { |
234 |
| - // Related to exactly one bound variable from each fn: |
235 |
| - return rev_lookup(this, a_map, new_binder_id, a_r.unwrap()); |
236 |
| - } else if a_r.is_none() && b_r.is_none() { |
237 |
| - // Not related to bound variables from either fn: |
238 |
| - assert!(!r0.is_bound()); |
239 |
| - return r0; |
240 |
| - } else { |
241 |
| - // Other: |
242 |
| - return fresh_bound_variable(this, new_binder_id); |
243 |
| - } |
244 |
| - } |
245 |
| - |
246 |
| - fn rev_lookup(this: &Glb, |
247 |
| - a_map: &FnvHashMap<ty::BoundRegion, ty::Region>, |
248 |
| - new_binder_id: NodeId, |
249 |
| - r: ty::Region) -> ty::Region |
250 |
| - { |
251 |
| - for (a_br, a_r) in a_map.iter() { |
252 |
| - if *a_r == r { |
253 |
| - return ty::ReLateBound(new_binder_id, *a_br); |
254 |
| - } |
255 |
| - } |
256 |
| - this.fields.infcx.tcx.sess.span_bug( |
257 |
| - this.fields.trace.origin.span(), |
258 |
| - format!("could not find original bound region for {}", |
259 |
| - r).as_slice()) |
260 |
| - } |
261 |
| - |
262 |
| - fn fresh_bound_variable(this: &Glb, binder_id: NodeId) -> ty::Region { |
263 |
| - this.fields.infcx.region_vars.new_bound(binder_id) |
264 |
| - } |
| 126 | + self.higher_ranked_glb(a, b) |
265 | 127 | }
|
266 | 128 | }
|
0 commit comments