1 // Copyright 2012 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 /*!
12 *
13 * # Lattice Variables
14 *
15 * This file contains generic code for operating on inference variables
16 * that are characterized by an upper- and lower-bound. The logic and
17 * reasoning is explained in detail in the large comment in `infer.rs`.
18 *
19 * The code in here is defined quite generically so that it can be
20 * applied both to type variables, which represent types being inferred,
21 * and fn variables, which represent function types being inferred.
22 * It may eventually be applied to ther types as well, who knows.
23 * In some cases, the functions are also generic with respect to the
24 * operation on the lattice (GLB vs LUB).
25 *
26 * Although all the functions are generic, we generally write the
27 * comments in a way that is specific to type variables and the LUB
28 * operation. It's just easier that way.
29 *
30 * In general all of the functions are defined parametrically
31 * over a `LatticeValue`, which is a value defined with respect to
32 * a lattice.
33 */
34
35
36 use middle::ty::{RegionVid, TyVar, Vid};
37 use middle::ty;
38 use middle::typeck::infer::{then, ToUres};
39 use middle::typeck::infer::*;
40 use middle::typeck::infer::combine::*;
41 use middle::typeck::infer::glb::Glb;
42 use middle::typeck::infer::lub::Lub;
43 use middle::typeck::infer::unify::*;
44 use middle::typeck::infer::sub::Sub;
45 use middle::typeck::infer::to_str::InferStr;
46 use util::common::indenter;
47
48 use collections::HashMap;
49
50 trait LatticeValue {
51 fn sub(cf: CombineFields, a: &Self, b: &Self) -> ures;
52 fn lub(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
53 fn glb(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
54 }
55
56 pub type LatticeOp<'a, T> =
57 |cf: CombineFields, a: &T, b: &T|: 'a -> cres<T>;
58
59 impl LatticeValue for ty::t {
60 fn sub(cf: CombineFields, a: &ty::t, b: &ty::t) -> ures {
61 Sub(cf).tys(*a, *b).to_ures()
62 }
63
64 fn lub(cf: CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
65 Lub(cf).tys(*a, *b)
66 }
67
68 fn glb(cf: CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
69 Glb(cf).tys(*a, *b)
70 }
71 }
72
73 pub trait CombineFieldsLatticeMethods {
74 fn var_sub_var<T:Clone + InferStr + LatticeValue,
75 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(&self,
76 a_id: V,
77 b_id: V)
78 -> ures;
79 /// make variable a subtype of T
80 fn var_sub_t<T:Clone + InferStr + LatticeValue,
81 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
82 &self,
83 a_id: V,
84 b: T)
85 -> ures;
86 fn t_sub_var<T:Clone + InferStr + LatticeValue,
87 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
88 &self,
89 a: T,
90 b_id: V)
91 -> ures;
92 fn merge_bnd<T:Clone + InferStr + LatticeValue>(
93 &self,
94 a: &Bound<T>,
95 b: &Bound<T>,
96 lattice_op: LatticeOp<T>)
97 -> cres<Bound<T>>;
98 fn set_var_to_merged_bounds<T:Clone + InferStr + LatticeValue,
99 V:Clone+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
100 &self,
101 v_id: V,
102 a: &Bounds<T>,
103 b: &Bounds<T>,
104 rank: uint)
105 -> ures;
106 fn bnds<T:Clone + InferStr + LatticeValue>(
107 &self,
108 a: &Bound<T>,
109 b: &Bound<T>)
110 -> ures;
111 }
112
113 impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
114 fn var_sub_var<T:Clone + InferStr + LatticeValue,
115 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
116 &self,
117 a_id: V,
118 b_id: V)
119 -> ures {
120 /*!
121 *
122 * Make one variable a subtype of another variable. This is a
123 * subtle and tricky process, as described in detail at the
124 * top of infer.rs*/
125
126 // Need to make sub_id a subtype of sup_id.
127 let node_a = self.infcx.get(a_id);
128 let node_b = self.infcx.get(b_id);
129 let a_id = node_a.root.clone();
130 let b_id = node_b.root.clone();
131 let a_bounds = node_a.possible_types.clone();
132 let b_bounds = node_b.possible_types.clone();
133
134 debug!("vars({}={} <: {}={})",
135 a_id.to_str(), a_bounds.inf_str(self.infcx),
136 b_id.to_str(), b_bounds.inf_str(self.infcx));
137
138 if a_id == b_id { return uok(); }
139
140 // If both A's UB and B's LB have already been bound to types,
141 // see if we can make those types subtypes.
142 match (&a_bounds.ub, &b_bounds.lb) {
143 (&Some(ref a_ub), &Some(ref b_lb)) => {
144 let r = self.infcx.try(
145 || LatticeValue::sub(self.clone(), a_ub, b_lb));
146 match r {
147 Ok(()) => {
148 return Ok(());
149 }
150 Err(_) => { /*fallthrough */ }
151 }
152 }
153 _ => { /*fallthrough*/ }
154 }
155
156 // Otherwise, we need to merge A and B so as to guarantee that
157 // A remains a subtype of B. Actually, there are other options,
158 // but that's the route we choose to take.
159
160 let (new_root, new_rank) = self.infcx.unify(&node_a, &node_b);
161 self.set_var_to_merged_bounds(new_root,
162 &a_bounds, &b_bounds,
163 new_rank)
164 }
165
166 /// make variable a subtype of T
167 fn var_sub_t<T:Clone + InferStr + LatticeValue,
168 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
169 &self,
170 a_id: V,
171 b: T)
172 -> ures {
173 /*!
174 *
175 * Make a variable (`a_id`) a subtype of the concrete type `b` */
176
177 let node_a = self.infcx.get(a_id);
178 let a_id = node_a.root.clone();
179 let a_bounds = &node_a.possible_types;
180 let b_bounds = &Bounds { lb: None, ub: Some(b.clone()) };
181
182 debug!("var_sub_t({}={} <: {})",
183 a_id.to_str(),
184 a_bounds.inf_str(self.infcx),
185 b.inf_str(self.infcx));
186
187 self.set_var_to_merged_bounds(
188 a_id, a_bounds, b_bounds, node_a.rank)
189 }
190
191 fn t_sub_var<T:Clone + InferStr + LatticeValue,
192 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
193 &self,
194 a: T,
195 b_id: V)
196 -> ures {
197 /*!
198 *
199 * Make a concrete type (`a`) a subtype of the variable `b_id` */
200
201 let a_bounds = &Bounds { lb: Some(a.clone()), ub: None };
202 let node_b = self.infcx.get(b_id);
203 let b_id = node_b.root.clone();
204 let b_bounds = &node_b.possible_types;
205
206 debug!("t_sub_var({} <: {}={})",
207 a.inf_str(self.infcx),
208 b_id.to_str(),
209 b_bounds.inf_str(self.infcx));
210
211 self.set_var_to_merged_bounds(
212 b_id, a_bounds, b_bounds, node_b.rank)
213 }
214
215 fn merge_bnd<T:Clone + InferStr + LatticeValue>(
216 &self,
217 a: &Bound<T>,
218 b: &Bound<T>,
219 lattice_op: LatticeOp<T>)
220 -> cres<Bound<T>> {
221 /*!
222 *
223 * Combines two bounds into a more general bound. */
224
225 debug!("merge_bnd({},{})",
226 a.inf_str(self.infcx),
227 b.inf_str(self.infcx));
228 let _r = indenter();
229
230 match (a, b) {
231 (&None, &None) => Ok(None),
232 (&Some(_), &None) => Ok((*a).clone()),
233 (&None, &Some(_)) => Ok((*b).clone()),
234 (&Some(ref v_a), &Some(ref v_b)) => {
235 lattice_op(self.clone(), v_a, v_b).and_then(|v| Ok(Some(v)))
236 }
237 }
238 }
239
240 fn set_var_to_merged_bounds<T:Clone + InferStr + LatticeValue,
241 V:Clone+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
242 &self,
243 v_id: V,
244 a: &Bounds<T>,
245 b: &Bounds<T>,
246 rank: uint)
247 -> ures {
248 /*!
249 *
250 * Updates the bounds for the variable `v_id` to be the intersection
251 * of `a` and `b`. That is, the new bounds for `v_id` will be
252 * a bounds c such that:
253 * c.ub <: a.ub
254 * c.ub <: b.ub
255 * a.lb <: c.lb
256 * b.lb <: c.lb
257 * If this cannot be achieved, the result is failure. */
258
259 // Think of the two diamonds, we want to find the
260 // intersection. There are basically four possibilities (you
261 // can swap A/B in these pictures):
262 //
263 // A A
264 // / \ / \
265 // / B \ / B \
266 // / / \ \ / / \ \
267 // * * * * * / * *
268 // \ \ / / \ / /
269 // \ B / / \ / /
270 // \ / * \ /
271 // A \ / A
272 // B
273
274 debug!("merge({},{},{})",
275 v_id.to_str(),
276 a.inf_str(self.infcx),
277 b.inf_str(self.infcx));
278 let _indent = indenter();
279
280 // First, relate the lower/upper bounds of A and B.
281 // Note that these relations *must* hold for us
282 // to be able to merge A and B at all, and relating
283 // them explicitly gives the type inferencer more
284 // information and helps to produce tighter bounds
285 // when necessary.
286 let () = if_ok!(self.bnds(&a.lb, &b.ub));
287 let () = if_ok!(self.bnds(&b.lb, &a.ub));
288 let ub = if_ok!(self.merge_bnd(&a.ub, &b.ub, LatticeValue::glb));
289 let lb = if_ok!(self.merge_bnd(&a.lb, &b.lb, LatticeValue::lub));
290 let bounds = Bounds { lb: lb, ub: ub };
291 debug!("merge({}): bounds={}",
292 v_id.to_str(),
293 bounds.inf_str(self.infcx));
294
295 // the new bounds must themselves
296 // be relatable:
297 let () = if_ok!(self.bnds(&bounds.lb, &bounds.ub));
298 self.infcx.set(v_id, Root(bounds, rank));
299 uok()
300 }
301
302 fn bnds<T:Clone + InferStr + LatticeValue>(&self,
303 a: &Bound<T>,
304 b: &Bound<T>)
305 -> ures {
306 debug!("bnds({} <: {})", a.inf_str(self.infcx),
307 b.inf_str(self.infcx));
308 let _r = indenter();
309
310 match (a, b) {
311 (&None, &None) |
312 (&Some(_), &None) |
313 (&None, &Some(_)) => {
314 uok()
315 }
316 (&Some(ref t_a), &Some(ref t_b)) => {
317 LatticeValue::sub(self.clone(), t_a, t_b)
318 }
319 }
320 }
321 }
322
323 // ______________________________________________________________________
324 // Lattice operations on variables
325 //
326 // This is common code used by both LUB and GLB to compute the LUB/GLB
327 // for pairs of variables or for variables and values.
328
329 pub trait LatticeDir {
330 fn combine_fields<'a>(&'a self) -> CombineFields<'a>;
331 fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T>;
332 fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T>;
333 }
334
335 pub trait TyLatticeDir {
336 fn ty_bot(&self, t: ty::t) -> cres<ty::t>;
337 }
338
339 impl<'f> LatticeDir for Lub<'f> {
340 fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
341 fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.ub.clone() }
342 fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
343 Bounds { ub: Some(t), ..(*b).clone() }
344 }
345 }
346
347 impl<'f> TyLatticeDir for Lub<'f> {
348 fn ty_bot(&self, t: ty::t) -> cres<ty::t> {
349 Ok(t)
350 }
351 }
352
353 impl<'f> LatticeDir for Glb<'f> {
354 fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
355 fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.lb.clone() }
356 fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
357 Bounds { lb: Some(t), ..(*b).clone() }
358 }
359 }
360
361 impl<'f> TyLatticeDir for Glb<'f> {
362 fn ty_bot(&self, _t: ty::t) -> cres<ty::t> {
363 Ok(ty::mk_bot())
364 }
365 }
366
367 pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
368 a: ty::t,
369 b: ty::t)
370 -> cres<ty::t> {
371 debug!("{}.lattice_tys({}, {})", this.tag(),
372 a.inf_str(this.infcx()),
373 b.inf_str(this.infcx()));
374
375 if a == b {
376 return Ok(a);
377 }
378
379 let tcx = this.infcx().tcx;
380
381 match (&ty::get(a).sty, &ty::get(b).sty) {
382 (&ty::ty_bot, _) => { return this.ty_bot(b); }
383 (_, &ty::ty_bot) => { return this.ty_bot(a); }
384
385 (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
386 let r = if_ok!(lattice_vars(this, a_id, b_id,
387 |x, y| this.tys(*x, *y)));
388 return match r {
389 VarResult(v) => Ok(ty::mk_var(tcx, v)),
390 ValueResult(t) => Ok(t)
391 };
392 }
393
394 (&ty::ty_infer(TyVar(a_id)), _) => {
395 return lattice_var_and_t(this, a_id, &b,
396 |x, y| this.tys(*x, *y));
397 }
398
399 (_, &ty::ty_infer(TyVar(b_id))) => {
400 return lattice_var_and_t(this, b_id, &a,
401 |x, y| this.tys(*x, *y));
402 }
403
404 _ => {
405 return super_tys(this, a, b);
406 }
407 }
408 }
409
410 pub type LatticeDirOp<'a, T> = |a: &T, b: &T|: 'a -> cres<T>;
411
412 #[deriving(Clone)]
413 pub enum LatticeVarResult<V,T> {
414 VarResult(V),
415 ValueResult(T)
416 }
417
418 /**
419 * Computes the LUB or GLB of two bounded variables. These could be any
420 * sort of variables, but in the comments on this function I'll assume
421 * we are doing an LUB on two type variables.
422 *
423 * This computation can be done in one of two ways:
424 *
425 * - If both variables have an upper bound, we may just compute the
426 * LUB of those bounds and return that, in which case we are
427 * returning a type. This is indicated with a `ValueResult` return.
428 *
429 * - If the variables do not both have an upper bound, we will unify
430 * the variables and return the unified variable, in which case the
431 * result is a variable. This is indicated with a `VarResult`
432 * return. */
433 pub fn lattice_vars<L:LatticeDir + Combine,
434 T:Clone + InferStr + LatticeValue,
435 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
436 this: &L, // defines whether we want LUB or GLB
437 a_vid: V, // first variable
438 b_vid: V, // second variable
439 lattice_dir_op: LatticeDirOp<T>) // LUB or GLB operation on types
440 -> cres<LatticeVarResult<V,T>> {
441 let nde_a = this.infcx().get(a_vid);
442 let nde_b = this.infcx().get(b_vid);
443 let a_vid = nde_a.root.clone();
444 let b_vid = nde_b.root.clone();
445 let a_bounds = &nde_a.possible_types;
446 let b_bounds = &nde_b.possible_types;
447
448 debug!("{}.lattice_vars({}={} <: {}={})",
449 this.tag(),
450 a_vid.to_str(), a_bounds.inf_str(this.infcx()),
451 b_vid.to_str(), b_bounds.inf_str(this.infcx()));
452
453 // Same variable: the easy case.
454 if a_vid == b_vid {
455 return Ok(VarResult(a_vid));
456 }
457
458 // If both A and B have an UB type, then we can just compute the
459 // LUB of those types:
460 let (a_bnd, b_bnd) = (this.bnd(a_bounds), this.bnd(b_bounds));
461 match (a_bnd, b_bnd) {
462 (Some(ref a_ty), Some(ref b_ty)) => {
463 match this.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) {
464 Ok(t) => return Ok(ValueResult(t)),
465 Err(_) => { /*fallthrough */ }
466 }
467 }
468 _ => {/*fallthrough*/}
469 }
470
471 // Otherwise, we need to merge A and B into one variable. We can
472 // then use either variable as an upper bound:
473 let cf = this.combine_fields();
474 cf.var_sub_var(a_vid.clone(), b_vid.clone()).then(|| {
475 Ok(VarResult(a_vid.clone()))
476 })
477 }
478
479 pub fn lattice_var_and_t<L:LatticeDir + Combine,
480 T:Clone + InferStr + LatticeValue,
481 V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
482 this: &L,
483 a_id: V,
484 b: &T,
485 lattice_dir_op: LatticeDirOp<T>)
486 -> cres<T> {
487 let nde_a = this.infcx().get(a_id);
488 let a_id = nde_a.root.clone();
489 let a_bounds = &nde_a.possible_types;
490
491 // The comments in this function are written for LUB, but they
492 // apply equally well to GLB if you inverse upper/lower/sub/super/etc.
493
494 debug!("{}.lattice_var_and_t({}={} <: {})",
495 this.tag(),
496 a_id.to_str(),
497 a_bounds.inf_str(this.infcx()),
498 b.inf_str(this.infcx()));
499
500 match this.bnd(a_bounds) {
501 Some(ref a_bnd) => {
502 // If a has an upper bound, return the LUB(a.ub, b)
503 debug!("bnd=Some({})", a_bnd.inf_str(this.infcx()));
504 lattice_dir_op(a_bnd, b)
505 }
506 None => {
507 // If a does not have an upper bound, make b the upper bound of a
508 // and then return b.
509 debug!("bnd=None");
510 let a_bounds = this.with_bnd(a_bounds, (*b).clone());
511 this.combine_fields().bnds(&a_bounds.lb, &a_bounds.ub).then(|| {
512 this.infcx().set(a_id.clone(),
513 Root(a_bounds.clone(), nde_a.rank));
514 Ok((*b).clone())
515 })
516 }
517 }
518 }
519
520 // ___________________________________________________________________________
521 // Random utility functions used by LUB/GLB when computing LUB/GLB of
522 // fn types
523
524 pub fn var_ids<T:Combine>(this: &T,
525 map: &HashMap<ty::BoundRegion, ty::Region>)
526 -> Vec<RegionVid> {
527 map.iter().map(|(_, r)| match *r {
528 ty::ReInfer(ty::ReVar(r)) => { r }
529 r => {
530 this.infcx().tcx.sess.span_bug(
531 this.trace().origin.span(),
532 format!("found non-region-vid: {:?}", r));
533 }
534 }).collect()
535 }
536
537 pub fn is_var_in_set(new_vars: &[RegionVid], r: ty::Region) -> bool {
538 match r {
539 ty::ReInfer(ty::ReVar(ref v)) => new_vars.iter().any(|x| x == v),
540 _ => false
541 }
542 }
librustc/middle/typeck/infer/lattice.rs:49:1-49:1 -trait- definition:
trait LatticeValue {
fn sub(cf: CombineFields, a: &Self, b: &Self) -> ures;
fn lub(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
references:- 2379: /// make variable a subtype of T
80: fn var_sub_t<T:Clone + InferStr + LatticeValue,
81: V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
--
105: -> ures;
106: fn bnds<T:Clone + InferStr + LatticeValue>(
107: &self,
--
240: fn set_var_to_merged_bounds<T:Clone + InferStr + LatticeValue,
241: V:Clone+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
--
433: pub fn lattice_vars<L:LatticeDir + Combine,
434: T:Clone + InferStr + LatticeValue,
435: V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
--
479: pub fn lattice_var_and_t<L:LatticeDir + Combine,
480: T:Clone + InferStr + LatticeValue,
481: V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
librustc/middle/typeck/infer/lattice.rs:366:1-366:1 -fn- definition:
pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
a: ty::t,
b: ty::t)
references:- 2librustc/middle/typeck/infer/glb.rs:
118: fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
119: super_lattice_tys(self, a, b)
120: }
librustc/middle/typeck/infer/lub.rs:
193: fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
194: super_lattice_tys(self, a, b)
195: }
librustc/middle/typeck/infer/lattice.rs:478:1-478:1 -fn- definition:
pub fn lattice_var_and_t<L:LatticeDir + Combine,
T:Clone + InferStr + LatticeValue,
V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
references:- 2394: (&ty::ty_infer(TyVar(a_id)), _) => {
395: return lattice_var_and_t(this, a_id, &b,
396: |x, y| this.tys(*x, *y));
--
399: (_, &ty::ty_infer(TyVar(b_id))) => {
400: return lattice_var_and_t(this, b_id, &a,
401: |x, y| this.tys(*x, *y));
librustc/middle/typeck/infer/lattice.rs:55:1-55:1 -NK_AS_STR_TODO- definition:
pub type LatticeOp<'a, T> =
|cf: CombineFields, a: &T, b: &T|: 'a -> cres<T>;
impl LatticeValue for ty::t {
references:- 2218: b: &Bound<T>,
219: lattice_op: LatticeOp<T>)
220: -> cres<Bound<T>> {
librustc/middle/typeck/infer/lattice.rs:523:1-523:1 -fn- definition:
pub fn var_ids<T:Combine>(this: &T,
map: &HashMap<ty::BoundRegion, ty::Region>)
-> Vec<RegionVid> {
references:- 2librustc/middle/typeck/infer/glb.rs:
143: self.trace(), b);
144: let b_vars = var_ids(self, &b_map);
librustc/middle/typeck/infer/lattice.rs:328:1-328:1 -trait- definition:
pub trait LatticeDir {
fn combine_fields<'a>(&'a self) -> CombineFields<'a>;
fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T>;
references:- 5339: impl<'f> LatticeDir for Lub<'f> {
340: fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
--
432: * return. */
433: pub fn lattice_vars<L:LatticeDir + Combine,
434: T:Clone + InferStr + LatticeValue,
--
479: pub fn lattice_var_and_t<L:LatticeDir + Combine,
480: T:Clone + InferStr + LatticeValue,
librustc/middle/typeck/infer/lattice.rs:536:1-536:1 -fn- definition:
pub fn is_var_in_set(new_vars: &[RegionVid], r: ty::Region) -> bool {
match r {
ty::ReInfer(ty::ReVar(ref v)) => new_vars.iter().any(|x| x == v),
references:- 6librustc/middle/typeck/infer/lub.rs:
152: // Regions that pre-dated the LUB computation stay as they are.
153: if !is_var_in_set(new_vars, r0) {
154: assert!(!r0.is_bound());
--
163: // stay as they are.
164: if !tainted.iter().all(|r| is_var_in_set(new_vars, *r)) {
165: debug!("generalize_region(r0={:?}): \
librustc/middle/typeck/infer/glb.rs:
194: }
195: } else if is_var_in_set(b_vars, *r) {
196: if b_r.is_some() {
--
200: }
201: } else if !is_var_in_set(new_vars, *r) {
202: only_new_vars = false;
librustc/middle/typeck/infer/lattice.rs:334:1-334:1 -trait- definition:
pub trait TyLatticeDir {
fn ty_bot(&self, t: ty::t) -> cres<ty::t>;
}
references:- 3347: impl<'f> TyLatticeDir for Lub<'f> {
348: fn ty_bot(&self, t: ty::t) -> cres<ty::t> {
--
367: pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
368: a: ty::t,
librustc/middle/typeck/infer/lattice.rs:412:19-412:19 -enum- definition:
pub enum LatticeVarResult<V,T> {
VarResult(V),
ValueResult(T)
references:- 3413: pub enum LatticeVarResult<V,T> {
--
439: lattice_dir_op: LatticeDirOp<T>) // LUB or GLB operation on types
440: -> cres<LatticeVarResult<V,T>> {
441: let nde_a = this.infcx().get(a_vid);
librustc/middle/typeck/infer/lattice.rs:409:1-409:1 -NK_AS_STR_TODO- definition:
pub type LatticeDirOp<'a, T> = |a: &T, b: &T|: 'a -> cres<T>;
pub enum LatticeVarResult<V,T> {
VarResult(V),
references:- 2438: b_vid: V, // second variable
439: lattice_dir_op: LatticeDirOp<T>) // LUB or GLB operation on types
440: -> cres<LatticeVarResult<V,T>> {
--
484: b: &T,
485: lattice_dir_op: LatticeDirOp<T>)
486: -> cres<T> {