]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/variance.rs
bd244b431c20e02823b1fefeb7ce3f47d872893b
[rust.git] / src / librustc / middle / typeck / variance.rs
1 // Copyright 2013 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 This file infers the variance of type and lifetime parameters. The
14 algorithm is taken from Section 4 of the paper "Taming the Wildcards:
15 Combining Definition- and Use-Site Variance" published in PLDI'11 and
16 written by Altidor et al., and hereafter referred to as The Paper.
17
18 This inference is explicitly designed *not* to consider the uses of
19 types within code. To determine the variance of type parameters
20 defined on type `X`, we only consider the definition of the type `X`
21 and the definitions of any types it references.
22
23 We only infer variance for type parameters found on *types*: structs,
24 enums, and traits. We do not infer variance for type parameters found
25 on fns or impls. This is because those things are not type definitions
26 and variance doesn't really make sense in that context.
27
28 It is worth covering what variance means in each case. For structs and
29 enums, I think it is fairly straightforward. The variance of the type
30 or lifetime parameters defines whether `T<A>` is a subtype of `T<B>`
31 (resp. `T<'a>` and `T<'b>`) based on the relationship of `A` and `B`
32 (resp. `'a` and `'b`). (FIXME #3598 -- we do not currently make use of
33 the variances we compute for type parameters.)
34
35 ### Variance on traits
36
37 The meaning of variance for trait parameters is more subtle and worth
38 expanding upon. There are in fact two uses of the variance values we
39 compute.
40
41 #### Trait variance and object types
42
43 The first is for object types. Just as with structs and enums, we can
44 decide the subtyping relationship between two object types `&Trait<A>`
45 and `&Trait<B>` based on the relationship of `A` and `B`. Note that
46 for object types we ignore the `Self` type parameter -- it is unknown,
47 and the nature of dynamic dispatch ensures that we will always call a
48 function that is expected the appropriate `Self` type. However, we
49 must be careful with the other type parameters, or else we could end
50 up calling a function that is expecting one type but provided another.
51
52 To see what I mean, consider a trait like so:
53
54     trait ConvertTo<A> {
55         fn convertTo(&self) -> A;
56     }
57
58 Intuitively, If we had one object `O=&ConvertTo<Object>` and another
59 `S=&ConvertTo<String>`, then `S <: O` because `String <: Object`
60 (presuming Java-like "string" and "object" types, my go to examples
61 for subtyping). The actual algorithm would be to compare the
62 (explicit) type parameters pairwise respecting their variance: here,
63 the type parameter A is covariant (it appears only in a return
64 position), and hence we require that `String <: Object`.
65
66 You'll note though that we did not consider the binding for the
67 (implicit) `Self` type parameter: in fact, it is unknown, so that's
68 good. The reason we can ignore that parameter is precisely because we
69 don't need to know its value until a call occurs, and at that time (as
70 you said) the dynamic nature of virtual dispatch means the code we run
71 will be correct for whatever value `Self` happens to be bound to for
72 the particular object whose method we called. `Self` is thus different
73 from `A`, because the caller requires that `A` be known in order to
74 know the return type of the method `convertTo()`. (As an aside, we
75 have rules preventing methods where `Self` appears outside of the
76 receiver position from being called via an object.)
77
78 #### Trait variance and vtable resolution
79
80 But traits aren't only used with objects. They're also used when
81 deciding whether a given impl satisfies a given trait bound (or should
82 be -- FIXME #5781). To set the scene here, imagine I had a function:
83
84     fn convertAll<A,T:ConvertTo<A>>(v: &[T]) {
85         ...
86     }
87
88 Now imagine that I have an implementation of `ConvertTo` for `Object`:
89
90     impl ConvertTo<int> for Object { ... }
91
92 And I want to call `convertAll` on an array of strings. Suppose
93 further that for whatever reason I specifically supply the value of
94 `String` for the type parameter `T`:
95
96     let mut vector = ~["string", ...];
97     convertAll::<int, String>(v);
98
99 Is this legal? To put another way, can we apply the `impl` for
100 `Object` to the type `String`? The answer is yes, but to see why
101 we have to expand out what will happen:
102
103 - `convertAll` will create a pointer to one of the entries in the
104   vector, which will have type `&String`
105 - It will then call the impl of `convertTo()` that is intended
106   for use with objects. This has the type:
107
108       fn(self: &Object) -> int
109
110   It is ok to provide a value for `self` of type `&String` because
111   `&String <: &Object`.
112
113 OK, so intuitively we want this to be legal, so let's bring this back
114 to variance and see whether we are computing the correct result. We
115 must first figure out how to phrase the question "is an impl for
116 `Object,int` usable where an impl for `String,int` is expected?"
117
118 Maybe it's helpful to think of a dictionary-passing implementation of
119 type classes. In that case, `convertAll()` takes an implicit parameter
120 representing the impl. In short, we *have* an impl of type:
121
122     V_O = ConvertTo<int> for Object
123
124 and the function prototype expects an impl of type:
125
126     V_S = ConvertTo<int> for String
127
128 As with any argument, this is legal if the type of the value given
129 (`V_O`) is a subtype of the type expected (`V_S`). So is `V_O <: V_S`?
130 The answer will depend on the variance of the various parameters. In
131 this case, because the `Self` parameter is contravariant and `A` is
132 covariant, it means that:
133
134     V_O <: V_S iff
135         int <: int
136         String <: Object
137
138 These conditions are satisfied and so we are happy.
139
140 ### The algorithm
141
142 The basic idea is quite straightforward. We iterate over the types
143 defined and, for each use of a type parameter X, accumulate a
144 constraint indicating that the variance of X must be valid for the
145 variance of that use site. We then iteratively refine the variance of
146 X until all constraints are met. There is *always* a sol'n, because at
147 the limit we can declare all type parameters to be invariant and all
148 constraints will be satisfied.
149
150 As a simple example, consider:
151
152     enum Option<A> { Some(A), None }
153     enum OptionalFn<B> { Some(|B|), None }
154     enum OptionalMap<C> { Some(|C| -> C), None }
155
156 Here, we will generate the constraints:
157
158     1. V(A) <= +
159     2. V(B) <= -
160     3. V(C) <= +
161     4. V(C) <= -
162
163 These indicate that (1) the variance of A must be at most covariant;
164 (2) the variance of B must be at most contravariant; and (3, 4) the
165 variance of C must be at most covariant *and* contravariant. All of these
166 results are based on a variance lattice defined as follows:
167
168       *      Top (bivariant)
169    -     +
170       o      Bottom (invariant)
171
172 Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the
173 optimal solution. Note that there is always a naive solution which
174 just declares all variables to be invariant.
175
176 You may be wondering why fixed-point iteration is required. The reason
177 is that the variance of a use site may itself be a function of the
178 variance of other type parameters. In full generality, our constraints
179 take the form:
180
181     V(X) <= Term
182     Term := + | - | * | o | V(X) | Term x Term
183
184 Here the notation V(X) indicates the variance of a type/region
185 parameter `X` with respect to its defining class. `Term x Term`
186 represents the "variance transform" as defined in the paper:
187
188   If the variance of a type variable `X` in type expression `E` is `V2`
189   and the definition-site variance of the [corresponding] type parameter
190   of a class `C` is `V1`, then the variance of `X` in the type expression
191   `C<E>` is `V3 = V1.xform(V2)`.
192
193 */
194
195 use collections::HashMap;
196 use arena;
197 use arena::Arena;
198 use middle::ty;
199 use std::vec;
200 use std::fmt;
201 use syntax::ast;
202 use syntax::ast_util;
203 use syntax::opt_vec;
204 use syntax::visit;
205 use syntax::visit::Visitor;
206 use util::ppaux::Repr;
207
208 pub fn infer_variance(tcx: ty::ctxt,
209                       krate: &ast::Crate) {
210     let mut arena = arena::Arena::new();
211     let terms_cx = determine_parameters_to_be_inferred(tcx, &mut arena, krate);
212     let constraints_cx = add_constraints_from_crate(terms_cx, krate);
213     solve_constraints(constraints_cx);
214 }
215
216 /**************************************************************************
217  * Representing terms
218  *
219  * Terms are structured as a straightforward tree. Rather than rely on
220  * GC, we allocate terms out of a bounded arena (the lifetime of this
221  * arena is the lifetime 'a that is threaded around).
222  *
223  * We assign a unique index to each type/region parameter whose variance
224  * is to be inferred. We refer to such variables as "inferreds". An
225  * `InferredIndex` is a newtype'd int representing the index of such
226  * a variable.
227  */
228
229 type VarianceTermPtr<'a> = &'a VarianceTerm<'a>;
230
231 struct InferredIndex(uint);
232
233 enum VarianceTerm<'a> {
234     ConstantTerm(ty::Variance),
235     TransformTerm(VarianceTermPtr<'a>, VarianceTermPtr<'a>),
236     InferredTerm(InferredIndex),
237 }
238
239 impl<'a> fmt::Show for VarianceTerm<'a> {
240     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
241         match *self {
242             ConstantTerm(c1) => write!(f.buf, "{}", c1),
243             TransformTerm(v1, v2) => write!(f.buf, "({} \u00D7 {})", v1, v2),
244             InferredTerm(id) => write!(f.buf, "[{}]", { let InferredIndex(i) = id; i })
245         }
246     }
247 }
248
249 /**************************************************************************
250  * The first pass over the crate simply builds up the set of inferreds.
251  */
252
253 struct TermsContext<'a> {
254     tcx: ty::ctxt,
255     arena: &'a Arena,
256
257     empty_variances: @ty::ItemVariances,
258
259     // Maps from the node id of a type/generic parameter to the
260     // corresponding inferred index.
261     inferred_map: HashMap<ast::NodeId, InferredIndex>,
262
263     // Maps from an InferredIndex to the info for that variable.
264     inferred_infos: ~[InferredInfo<'a>],
265 }
266
267 enum ParamKind { TypeParam, RegionParam, SelfParam }
268
269 struct InferredInfo<'a> {
270     item_id: ast::NodeId,
271     kind: ParamKind,
272     index: uint,
273     param_id: ast::NodeId,
274     term: VarianceTermPtr<'a>,
275 }
276
277 fn determine_parameters_to_be_inferred<'a>(tcx: ty::ctxt,
278                                            arena: &'a mut Arena,
279                                            krate: &ast::Crate)
280                                            -> TermsContext<'a> {
281     let mut terms_cx = TermsContext {
282         tcx: tcx,
283         arena: arena,
284         inferred_map: HashMap::new(),
285         inferred_infos: ~[],
286
287         // cache and share the variance struct used for items with
288         // no type/region parameters
289         empty_variances: @ty::ItemVariances { self_param: None,
290                                               type_params: opt_vec::Empty,
291                                               region_params: opt_vec::Empty }
292     };
293
294     visit::walk_crate(&mut terms_cx, krate, ());
295
296     terms_cx
297 }
298
299 impl<'a> TermsContext<'a> {
300     fn add_inferred(&mut self,
301                     item_id: ast::NodeId,
302                     kind: ParamKind,
303                     index: uint,
304                     param_id: ast::NodeId) {
305         let inf_index = InferredIndex(self.inferred_infos.len());
306         let term = self.arena.alloc(|| InferredTerm(inf_index));
307         self.inferred_infos.push(InferredInfo { item_id: item_id,
308                                                 kind: kind,
309                                                 index: index,
310                                                 param_id: param_id,
311                                                 term: term });
312         let newly_added = self.inferred_map.insert(param_id, inf_index);
313         assert!(newly_added);
314
315         debug!("add_inferred(item_id={}, \
316                 kind={:?}, \
317                 index={}, \
318                 param_id={},
319                 inf_index={:?})",
320                 item_id, kind, index, param_id, inf_index);
321     }
322
323     fn num_inferred(&self) -> uint {
324         self.inferred_infos.len()
325     }
326 }
327
328 impl<'a> Visitor<()> for TermsContext<'a> {
329     fn visit_item(&mut self, item: &ast::Item, _: ()) {
330         debug!("add_inferreds for item {}", item.repr(self.tcx));
331
332         let inferreds_on_entry = self.num_inferred();
333
334         // NB: In the code below for writing the results back into the
335         // tcx, we rely on the fact that all inferreds for a particular
336         // item are assigned continuous indices.
337         match item.node {
338             ast::ItemTrait(..) => {
339                 self.add_inferred(item.id, SelfParam, 0, item.id);
340             }
341             _ => { }
342         }
343
344         match item.node {
345             ast::ItemEnum(_, ref generics) |
346             ast::ItemStruct(_, ref generics) |
347             ast::ItemTrait(ref generics, _, _) => {
348                 for (i, p) in generics.lifetimes.iter().enumerate() {
349                     self.add_inferred(item.id, RegionParam, i, p.id);
350                 }
351                 for (i, p) in generics.ty_params.iter().enumerate() {
352                     self.add_inferred(item.id, TypeParam, i, p.id);
353                 }
354
355                 // If this item has no type or lifetime parameters,
356                 // then there are no variances to infer, so just
357                 // insert an empty entry into the variance map.
358                 // Arguably we could just leave the map empty in this
359                 // case but it seems cleaner to be able to distinguish
360                 // "invalid item id" from "item id with no
361                 // parameters".
362                 if self.num_inferred() == inferreds_on_entry {
363                     let mut item_variance_map = self.tcx
364                                                     .item_variance_map
365                                                     .borrow_mut();
366                     let newly_added = item_variance_map.get().insert(
367                         ast_util::local_def(item.id),
368                         self.empty_variances);
369                     assert!(newly_added);
370                 }
371
372                 visit::walk_item(self, item, ());
373             }
374
375             ast::ItemImpl(..) |
376             ast::ItemStatic(..) |
377             ast::ItemFn(..) |
378             ast::ItemMod(..) |
379             ast::ItemForeignMod(..) |
380             ast::ItemTy(..) |
381             ast::ItemMac(..) => {
382                 visit::walk_item(self, item, ());
383             }
384         }
385     }
386 }
387
388 /**************************************************************************
389  * Constraint construction and representation
390  *
391  * The second pass over the AST determines the set of constraints.
392  * We walk the set of items and, for each member, generate new constraints.
393  */
394
395 struct ConstraintContext<'a> {
396     terms_cx: TermsContext<'a>,
397
398     // These are the def-id of the std::kinds::marker::InvariantType,
399     // std::kinds::marker::InvariantLifetime, and so on. The arrays
400     // are indexed by the `ParamKind` (type, lifetime, self). Note
401     // that there are no marker types for self, so the entries for
402     // self are always None.
403     invariant_lang_items: [Option<ast::DefId>, ..3],
404     covariant_lang_items: [Option<ast::DefId>, ..3],
405     contravariant_lang_items: [Option<ast::DefId>, ..3],
406
407     // These are pointers to common `ConstantTerm` instances
408     covariant: VarianceTermPtr<'a>,
409     contravariant: VarianceTermPtr<'a>,
410     invariant: VarianceTermPtr<'a>,
411     bivariant: VarianceTermPtr<'a>,
412
413     constraints: ~[Constraint<'a>],
414 }
415
416 /// Declares that the variable `decl_id` appears in a location with
417 /// variance `variance`.
418 struct Constraint<'a> {
419     inferred: InferredIndex,
420     variance: &'a VarianceTerm<'a>,
421 }
422
423 fn add_constraints_from_crate<'a>(terms_cx: TermsContext<'a>,
424                                   krate: &ast::Crate)
425                                   -> ConstraintContext<'a> {
426     let mut invariant_lang_items = [None, ..3];
427     let mut covariant_lang_items = [None, ..3];
428     let mut contravariant_lang_items = [None, ..3];
429
430     covariant_lang_items[TypeParam as uint] =
431         terms_cx.tcx.lang_items.covariant_type();
432     covariant_lang_items[RegionParam as uint] =
433         terms_cx.tcx.lang_items.covariant_lifetime();
434
435     contravariant_lang_items[TypeParam as uint] =
436         terms_cx.tcx.lang_items.contravariant_type();
437     contravariant_lang_items[RegionParam as uint] =
438         terms_cx.tcx.lang_items.contravariant_lifetime();
439
440     invariant_lang_items[TypeParam as uint] =
441         terms_cx.tcx.lang_items.invariant_type();
442     invariant_lang_items[RegionParam as uint] =
443         terms_cx.tcx.lang_items.invariant_lifetime();
444
445     let covariant = terms_cx.arena.alloc(|| ConstantTerm(ty::Covariant));
446     let contravariant = terms_cx.arena.alloc(|| ConstantTerm(ty::Contravariant));
447     let invariant = terms_cx.arena.alloc(|| ConstantTerm(ty::Invariant));
448     let bivariant = terms_cx.arena.alloc(|| ConstantTerm(ty::Bivariant));
449     let mut constraint_cx = ConstraintContext {
450         terms_cx: terms_cx,
451
452         invariant_lang_items: invariant_lang_items,
453         covariant_lang_items: covariant_lang_items,
454         contravariant_lang_items: contravariant_lang_items,
455
456         covariant: covariant,
457         contravariant: contravariant,
458         invariant: invariant,
459         bivariant: bivariant,
460         constraints: ~[],
461     };
462     visit::walk_crate(&mut constraint_cx, krate, ());
463     constraint_cx
464 }
465
466 impl<'a> Visitor<()> for ConstraintContext<'a> {
467     fn visit_item(&mut self, item: &ast::Item, _: ()) {
468         let did = ast_util::local_def(item.id);
469         let tcx = self.terms_cx.tcx;
470
471         match item.node {
472             ast::ItemEnum(ref enum_definition, _) => {
473                 // Hack: If we directly call `ty::enum_variants`, it
474                 // annoyingly takes it upon itself to run off and
475                 // evaluate the discriminants eagerly (*grumpy* that's
476                 // not the typical pattern). This results in double
477                 // error messages because typeck goes off and does
478                 // this at a later time. All we really care about is
479                 // the types of the variant arguments, so we just call
480                 // `ty::VariantInfo::from_ast_variant()` ourselves
481                 // here, mainly so as to mask the differences between
482                 // struct-like enums and so forth.
483                 for &ast_variant in enum_definition.variants.iter() {
484                     let variant =
485                         ty::VariantInfo::from_ast_variant(tcx,
486                                                           ast_variant,
487                                                           /*discrimant*/ 0);
488                     for &arg_ty in variant.args.iter() {
489                         self.add_constraints_from_ty(arg_ty, self.covariant);
490                     }
491                 }
492             }
493
494             ast::ItemStruct(..) => {
495                 let struct_fields = ty::lookup_struct_fields(tcx, did);
496                 for field_info in struct_fields.iter() {
497                     assert_eq!(field_info.id.krate, ast::LOCAL_CRATE);
498                     let field_ty = ty::node_id_to_type(tcx, field_info.id.node);
499                     self.add_constraints_from_ty(field_ty, self.covariant);
500                 }
501             }
502
503             ast::ItemTrait(..) => {
504                 let methods = ty::trait_methods(tcx, did);
505                 for method in methods.iter() {
506                     self.add_constraints_from_sig(
507                         &method.fty.sig, self.covariant);
508                 }
509             }
510
511             ast::ItemStatic(..) |
512             ast::ItemFn(..) |
513             ast::ItemMod(..) |
514             ast::ItemForeignMod(..) |
515             ast::ItemTy(..) |
516             ast::ItemImpl(..) |
517             ast::ItemMac(..) => {
518                 visit::walk_item(self, item, ());
519             }
520         }
521     }
522 }
523
524 impl<'a> ConstraintContext<'a> {
525     fn tcx(&self) -> ty::ctxt {
526         self.terms_cx.tcx
527     }
528
529     fn inferred_index(&self, param_id: ast::NodeId) -> InferredIndex {
530         match self.terms_cx.inferred_map.find(&param_id) {
531             Some(&index) => index,
532             None => {
533                 self.tcx().sess.bug(format!(
534                         "No inferred index entry for {}",
535                         self.tcx().map.node_to_str(param_id)));
536             }
537         }
538     }
539
540     fn declared_variance(&self,
541                          param_def_id: ast::DefId,
542                          item_def_id: ast::DefId,
543                          kind: ParamKind,
544                          index: uint)
545                          -> VarianceTermPtr<'a> {
546         /*!
547          * Returns a variance term representing the declared variance of
548          * the type/region parameter with the given id.
549          */
550
551         assert_eq!(param_def_id.krate, item_def_id.krate);
552
553         if self.invariant_lang_items[kind as uint] == Some(item_def_id) {
554             self.invariant
555         } else if self.covariant_lang_items[kind as uint] == Some(item_def_id) {
556             self.covariant
557         } else if self.contravariant_lang_items[kind as uint] == Some(item_def_id) {
558             self.contravariant
559         } else if param_def_id.krate == ast::LOCAL_CRATE {
560             // Parameter on an item defined within current crate:
561             // variance not yet inferred, so return a symbolic
562             // variance.
563             let InferredIndex(index) = self.inferred_index(param_def_id.node);
564             self.terms_cx.inferred_infos[index].term
565         } else {
566             // Parameter on an item defined within another crate:
567             // variance already inferred, just look it up.
568             let variances = ty::item_variances(self.tcx(), item_def_id);
569             let variance = match kind {
570                 SelfParam => variances.self_param.unwrap(),
571                 TypeParam => *variances.type_params.get(index),
572                 RegionParam => *variances.region_params.get(index),
573             };
574             self.constant_term(variance)
575         }
576     }
577
578     fn add_constraint(&mut self,
579                       InferredIndex(index): InferredIndex,
580                       variance: VarianceTermPtr<'a>) {
581         debug!("add_constraint(index={}, variance={})",
582                 index, variance.to_str());
583         self.constraints.push(Constraint { inferred: InferredIndex(index),
584                                            variance: variance });
585     }
586
587     fn contravariant(&mut self,
588                      variance: VarianceTermPtr<'a>)
589                      -> VarianceTermPtr<'a> {
590         self.xform(variance, self.contravariant)
591     }
592
593     fn invariant(&mut self,
594                  variance: VarianceTermPtr<'a>)
595                  -> VarianceTermPtr<'a> {
596         self.xform(variance, self.invariant)
597     }
598
599     fn constant_term(&self, v: ty::Variance) -> VarianceTermPtr<'a> {
600         match v {
601             ty::Covariant => self.covariant,
602             ty::Invariant => self.invariant,
603             ty::Contravariant => self.contravariant,
604             ty::Bivariant => self.bivariant,
605         }
606     }
607
608     fn xform(&mut self,
609              v1: VarianceTermPtr<'a>,
610              v2: VarianceTermPtr<'a>)
611              -> VarianceTermPtr<'a> {
612         match (*v1, *v2) {
613             (_, ConstantTerm(ty::Covariant)) => {
614                 // Applying a "covariant" transform is always a no-op
615                 v1
616             }
617
618             (ConstantTerm(c1), ConstantTerm(c2)) => {
619                 self.constant_term(c1.xform(c2))
620             }
621
622             _ => {
623                 self.terms_cx.arena.alloc(|| TransformTerm(v1, v2))
624             }
625         }
626     }
627
628     /// Adds constraints appropriate for an instance of `ty` appearing
629     /// in a context with ambient variance `variance`
630     fn add_constraints_from_ty(&mut self,
631                                ty: ty::t,
632                                variance: VarianceTermPtr<'a>) {
633         debug!("add_constraints_from_ty(ty={})", ty.repr(self.tcx()));
634
635         match ty::get(ty).sty {
636             ty::ty_nil | ty::ty_bot | ty::ty_bool |
637             ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) |
638             ty::ty_float(_) => {
639                 /* leaf type -- noop */
640             }
641
642             ty::ty_rptr(region, ref mt) => {
643                 let contra = self.contravariant(variance);
644                 self.add_constraints_from_region(region, contra);
645                 self.add_constraints_from_mt(mt, variance);
646             }
647
648             ty::ty_str(vstore) => {
649                 self.add_constraints_from_vstore(vstore, variance);
650             }
651
652             ty::ty_vec(ref mt, vstore) => {
653                 self.add_constraints_from_vstore(vstore, variance);
654                 self.add_constraints_from_mt(mt, variance);
655             }
656
657             ty::ty_uniq(typ) | ty::ty_box(typ) => {
658                 self.add_constraints_from_ty(typ, variance);
659             }
660
661             ty::ty_ptr(ref mt) => {
662                 self.add_constraints_from_mt(mt, variance);
663             }
664
665             ty::ty_tup(ref subtys) => {
666                 for &subty in subtys.iter() {
667                     self.add_constraints_from_ty(subty, variance);
668                 }
669             }
670
671             ty::ty_enum(def_id, ref substs) |
672             ty::ty_struct(def_id, ref substs) => {
673                 let item_type = ty::lookup_item_type(self.tcx(), def_id);
674                 self.add_constraints_from_substs(def_id, &item_type.generics,
675                                                  substs, variance);
676             }
677
678             ty::ty_trait(def_id, ref substs, _, _, _) => {
679                 let trait_def = ty::lookup_trait_def(self.tcx(), def_id);
680                 self.add_constraints_from_substs(def_id, &trait_def.generics,
681                                                  substs, variance);
682             }
683
684             ty::ty_param(ty::param_ty { def_id: ref def_id, .. }) => {
685                 assert_eq!(def_id.krate, ast::LOCAL_CRATE);
686                 match self.terms_cx.inferred_map.find(&def_id.node) {
687                     Some(&index) => {
688                         self.add_constraint(index, variance);
689                     }
690                     None => {
691                         // We do not infer variance for type parameters
692                         // declared on methods. They will not be present
693                         // in the inferred_map.
694                     }
695                 }
696             }
697
698             ty::ty_self(ref def_id) => {
699                 assert_eq!(def_id.krate, ast::LOCAL_CRATE);
700                 let index = self.inferred_index(def_id.node);
701                 self.add_constraint(index, variance);
702             }
703
704             ty::ty_bare_fn(ty::BareFnTy { sig: ref sig, .. }) => {
705                 self.add_constraints_from_sig(sig, variance);
706             }
707
708             ty::ty_closure(ty::ClosureTy { sig: ref sig, region, .. }) => {
709                 let contra = self.contravariant(variance);
710                 self.add_constraints_from_region(region, contra);
711                 self.add_constraints_from_sig(sig, variance);
712             }
713
714             ty::ty_infer(..) | ty::ty_err | ty::ty_unboxed_vec(..) => {
715                 self.tcx().sess.bug(
716                     format!("unexpected type encountered in \
717                             variance inference: {}",
718                             ty.repr(self.tcx())));
719             }
720         }
721     }
722
723     /// Adds constraints appropriate for a vector with vstore `vstore`
724     /// appearing in a context with ambient variance `variance`
725     fn add_constraints_from_vstore(&mut self,
726                                    vstore: ty::vstore,
727                                    variance: VarianceTermPtr<'a>) {
728         match vstore {
729             ty::vstore_slice(r) => {
730                 let contra = self.contravariant(variance);
731                 self.add_constraints_from_region(r, contra);
732             }
733
734             ty::vstore_fixed(_) | ty::vstore_uniq => {
735             }
736         }
737     }
738
739     /// Adds constraints appropriate for a nominal type (enum, struct,
740     /// object, etc) appearing in a context with ambient variance `variance`
741     fn add_constraints_from_substs(&mut self,
742                                    def_id: ast::DefId,
743                                    generics: &ty::Generics,
744                                    substs: &ty::substs,
745                                    variance: VarianceTermPtr<'a>) {
746         debug!("add_constraints_from_substs(def_id={:?})", def_id);
747
748         for (i, p) in generics.type_param_defs().iter().enumerate() {
749             let variance_decl =
750                 self.declared_variance(p.def_id, def_id, TypeParam, i);
751             let variance_i = self.xform(variance, variance_decl);
752             self.add_constraints_from_ty(substs.tps[i], variance_i);
753         }
754
755         match substs.regions {
756             ty::ErasedRegions => {}
757             ty::NonerasedRegions(ref rps) => {
758                 for (i, p) in generics.region_param_defs().iter().enumerate() {
759                     let variance_decl =
760                         self.declared_variance(p.def_id, def_id, RegionParam, i);
761                     let variance_i = self.xform(variance, variance_decl);
762                     self.add_constraints_from_region(*rps.get(i), variance_i);
763                 }
764             }
765         }
766     }
767
768     /// Adds constraints appropriate for a function with signature
769     /// `sig` appearing in a context with ambient variance `variance`
770     fn add_constraints_from_sig(&mut self,
771                                 sig: &ty::FnSig,
772                                 variance: VarianceTermPtr<'a>) {
773         let contra = self.contravariant(variance);
774         for &input in sig.inputs.iter() {
775             self.add_constraints_from_ty(input, contra);
776         }
777         self.add_constraints_from_ty(sig.output, variance);
778     }
779
780     /// Adds constraints appropriate for a region appearing in a
781     /// context with ambient variance `variance`
782     fn add_constraints_from_region(&mut self,
783                                    region: ty::Region,
784                                    variance: VarianceTermPtr<'a>) {
785         match region {
786             ty::ReEarlyBound(param_id, _, _) => {
787                 let index = self.inferred_index(param_id);
788                 self.add_constraint(index, variance);
789             }
790
791             ty::ReStatic => { }
792
793             ty::ReLateBound(..) => {
794                 // We do not infer variance for region parameters on
795                 // methods or in fn types.
796             }
797
798             ty::ReFree(..) | ty::ReScope(..) | ty::ReInfer(..) |
799             ty::ReEmpty => {
800                 // We don't expect to see anything but 'static or bound
801                 // regions when visiting member types or method types.
802                 self.tcx().sess.bug(format!("unexpected region encountered in \
803                                             variance inference: {}",
804                                             region.repr(self.tcx())));
805             }
806         }
807     }
808
809     /// Adds constraints appropriate for a mutability-type pair
810     /// appearing in a context with ambient variance `variance`
811     fn add_constraints_from_mt(&mut self,
812                                mt: &ty::mt,
813                                variance: VarianceTermPtr<'a>) {
814         match mt.mutbl {
815             ast::MutMutable => {
816                 let invar = self.invariant(variance);
817                 self.add_constraints_from_ty(mt.ty, invar);
818             }
819
820             ast::MutImmutable => {
821                 self.add_constraints_from_ty(mt.ty, variance);
822             }
823         }
824     }
825 }
826
827 /**************************************************************************
828  * Constraint solving
829  *
830  * The final phase iterates over the constraints, refining the variance
831  * for each inferred until a fixed point is reached. This will be the
832  * optimal solution to the constraints. The final variance for each
833  * inferred is then written into the `variance_map` in the tcx.
834  */
835
836 struct SolveContext<'a> {
837     terms_cx: TermsContext<'a>,
838     constraints: ~[Constraint<'a>],
839
840     // Maps from an InferredIndex to the inferred value for that variable.
841     solutions: ~[ty::Variance]
842 }
843
844 fn solve_constraints(constraints_cx: ConstraintContext) {
845     let ConstraintContext { terms_cx, constraints, .. } = constraints_cx;
846     let solutions = vec::from_elem(terms_cx.num_inferred(), ty::Bivariant);
847     let mut solutions_cx = SolveContext {
848         terms_cx: terms_cx,
849         constraints: constraints,
850         solutions: solutions
851     };
852     solutions_cx.solve();
853     solutions_cx.write();
854 }
855
856 impl<'a> SolveContext<'a> {
857     fn solve(&mut self) {
858         // Propagate constraints until a fixed point is reached.  Note
859         // that the maximum number of iterations is 2C where C is the
860         // number of constraints (each variable can change values at most
861         // twice). Since number of constraints is linear in size of the
862         // input, so is the inference process.
863         let mut changed = true;
864         while changed {
865             changed = false;
866
867             for constraint in self.constraints.iter() {
868                 let Constraint { inferred, variance: term } = *constraint;
869                 let InferredIndex(inferred) = inferred;
870                 let variance = self.evaluate(term);
871                 let old_value = self.solutions[inferred];
872                 let new_value = glb(variance, old_value);
873                 if old_value != new_value {
874                     debug!("Updating inferred {} (node {}) \
875                             from {:?} to {:?} due to {}",
876                             inferred,
877                             self.terms_cx.inferred_infos[inferred].param_id,
878                             old_value,
879                             new_value,
880                             term.to_str());
881
882                     self.solutions[inferred] = new_value;
883                     changed = true;
884                 }
885             }
886         }
887     }
888
889     fn write(&self) {
890         // Collect all the variances for a particular item and stick
891         // them into the variance map. We rely on the fact that we
892         // generate all the inferreds for a particular item
893         // consecutively (that is, we collect solutions for an item
894         // until we see a new item id, and we assume (1) the solutions
895         // are in the same order as the type parameters were declared
896         // and (2) all solutions or a given item appear before a new
897         // item id).
898
899         let tcx = self.terms_cx.tcx;
900         let solutions = &self.solutions;
901         let inferred_infos = &self.terms_cx.inferred_infos;
902         let mut index = 0;
903         let num_inferred = self.terms_cx.num_inferred();
904         while index < num_inferred {
905             let item_id = inferred_infos[index].item_id;
906             let mut item_variances = ty::ItemVariances {
907                 self_param: None,
908                 type_params: opt_vec::Empty,
909                 region_params: opt_vec::Empty
910             };
911             while index < num_inferred &&
912                   inferred_infos[index].item_id == item_id {
913                 let info = &inferred_infos[index];
914                 match info.kind {
915                     SelfParam => {
916                         assert!(item_variances.self_param.is_none());
917                         item_variances.self_param = Some(solutions[index]);
918                     }
919                     TypeParam => {
920                         item_variances.type_params.push(solutions[index]);
921                     }
922                     RegionParam => {
923                         item_variances.region_params.push(solutions[index]);
924                     }
925                 }
926                 index += 1;
927             }
928
929             debug!("item_id={} item_variances={}",
930                     item_id,
931                     item_variances.repr(tcx));
932
933             let item_def_id = ast_util::local_def(item_id);
934
935             // For unit testing: check for a special "rustc_variance"
936             // attribute and report an error with various results if found.
937             if ty::has_attr(tcx, item_def_id, "rustc_variance") {
938                 let found = item_variances.repr(tcx);
939                 tcx.sess.span_err(tcx.map.span(item_id), found);
940             }
941
942             let mut item_variance_map = tcx.item_variance_map.borrow_mut();
943             let newly_added = item_variance_map.get().insert(item_def_id,
944                                                              @item_variances);
945             assert!(newly_added);
946         }
947     }
948
949     fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance {
950         match *term {
951             ConstantTerm(v) => {
952                 v
953             }
954
955             TransformTerm(t1, t2) => {
956                 let v1 = self.evaluate(t1);
957                 let v2 = self.evaluate(t2);
958                 v1.xform(v2)
959             }
960
961             InferredTerm(InferredIndex(index)) => {
962                 self.solutions[index]
963             }
964         }
965     }
966 }
967
968 /**************************************************************************
969  * Miscellany transformations on variance
970  */
971
972 trait Xform {
973     fn xform(self, v: Self) -> Self;
974 }
975
976 impl Xform for ty::Variance {
977     fn xform(self, v: ty::Variance) -> ty::Variance {
978         // "Variance transformation", Figure 1 of The Paper
979         match (self, v) {
980             // Figure 1, column 1.
981             (ty::Covariant, ty::Covariant) => ty::Covariant,
982             (ty::Covariant, ty::Contravariant) => ty::Contravariant,
983             (ty::Covariant, ty::Invariant) => ty::Invariant,
984             (ty::Covariant, ty::Bivariant) => ty::Bivariant,
985
986             // Figure 1, column 2.
987             (ty::Contravariant, ty::Covariant) => ty::Contravariant,
988             (ty::Contravariant, ty::Contravariant) => ty::Covariant,
989             (ty::Contravariant, ty::Invariant) => ty::Invariant,
990             (ty::Contravariant, ty::Bivariant) => ty::Bivariant,
991
992             // Figure 1, column 3.
993             (ty::Invariant, _) => ty::Invariant,
994
995             // Figure 1, column 4.
996             (ty::Bivariant, _) => ty::Bivariant,
997         }
998     }
999 }
1000
1001 fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance {
1002     // Greatest lower bound of the variance lattice as
1003     // defined in The Paper:
1004     //
1005     //       *
1006     //    -     +
1007     //       o
1008     match (v1, v2) {
1009         (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
1010
1011         (ty::Covariant, ty::Contravariant) => ty::Invariant,
1012         (ty::Contravariant, ty::Covariant) => ty::Invariant,
1013
1014         (ty::Covariant, ty::Covariant) => ty::Covariant,
1015
1016         (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
1017
1018         (x, ty::Bivariant) | (ty::Bivariant, x) => x,
1019     }
1020 }