]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/wf.rs
Auto merge of #28146 - eefriedman:deque_extras, r=alexcrichton
[rust.git] / src / librustc_typeck / check / wf.rs
1 // Copyright 2014 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 use astconv::AstConv;
12 use check::{FnCtxt, Inherited, blank_fn_ctxt, regionck, wfcheck};
13 use constrained_type_params::{identify_constrained_type_params, Parameter};
14 use CrateCtxt;
15 use middle::def_id::DefId;
16 use middle::region;
17 use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
18 use middle::traits;
19 use middle::ty::{self, Ty};
20 use middle::ty_fold::{TypeFolder, TypeFoldable, super_fold_ty};
21
22 use std::cell::RefCell;
23 use std::collections::HashSet;
24 use syntax::ast;
25 use syntax::codemap::{DUMMY_SP, Span};
26 use syntax::parse::token::{special_idents};
27 use syntax::visit;
28 use syntax::visit::{FnKind, Visitor};
29
30 pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> {
31     ccx: &'ccx CrateCtxt<'ccx, 'tcx>,
32     cache: HashSet<Ty<'tcx>>
33 }
34
35 impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
36     pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'tcx>) -> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
37         CheckTypeWellFormedVisitor { ccx: ccx, cache: HashSet::new() }
38     }
39
40     fn tcx(&self) -> &ty::ctxt<'tcx> {
41         self.ccx.tcx
42     }
43
44     /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
45     /// well-formed, meaning that they do not require any constraints not declared in the struct
46     /// definition itself. For example, this definition would be illegal:
47     ///
48     ///     struct Ref<'a, T> { x: &'a T }
49     ///
50     /// because the type did not declare that `T:'a`.
51     ///
52     /// We do this check as a pre-pass before checking fn bodies because if these constraints are
53     /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
54     /// the types first.
55     fn check_item_well_formed(&mut self, item: &ast::Item) {
56         let ccx = self.ccx;
57         debug!("check_item_well_formed(it.id={}, it.ident={})",
58                item.id,
59                ccx.tcx.item_path_str(DefId::local(item.id)));
60
61         match item.node {
62             /// Right now we check that every default trait implementation
63             /// has an implementation of itself. Basically, a case like:
64             ///
65             /// `impl Trait for T {}`
66             ///
67             /// has a requirement of `T: Trait` which was required for default
68             /// method implementations. Although this could be improved now that
69             /// there's a better infrastructure in place for this, it's being left
70             /// for a follow-up work.
71             ///
72             /// Since there's such a requirement, we need to check *just* positive
73             /// implementations, otherwise things like:
74             ///
75             /// impl !Send for T {}
76             ///
77             /// won't be allowed unless there's an *explicit* implementation of `Send`
78             /// for `T`
79             ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
80                 self.check_impl(item);
81             }
82             ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
83                 let trait_ref = ccx.tcx.impl_trait_ref(DefId::local(item.id)).unwrap();
84                 ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
85                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
86                     Some(ty::BoundSend) | Some(ty::BoundSync) => {}
87                     Some(_) | None => {
88                         if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
89                             wfcheck::error_192(ccx, item.span);
90                         }
91                     }
92                 }
93             }
94             ast::ItemFn(..) => {
95                 self.check_item_type(item);
96             }
97             ast::ItemStatic(..) => {
98                 self.check_item_type(item);
99             }
100             ast::ItemConst(..) => {
101                 self.check_item_type(item);
102             }
103             ast::ItemStruct(ref struct_def, ref ast_generics) => {
104                 self.check_type_defn(item, |fcx| {
105                     vec![struct_variant(fcx, &**struct_def)]
106                 });
107
108                 self.check_variances_for_type_defn(item, ast_generics);
109             }
110             ast::ItemEnum(ref enum_def, ref ast_generics) => {
111                 self.check_type_defn(item, |fcx| {
112                     enum_variants(fcx, enum_def)
113                 });
114
115                 self.check_variances_for_type_defn(item, ast_generics);
116             }
117             ast::ItemTrait(_, _, _, ref items) => {
118                 let trait_predicates =
119                     ccx.tcx.lookup_predicates(DefId::local(item.id));
120                 reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
121                 if ccx.tcx.trait_has_default_impl(DefId::local(item.id)) {
122                     if !items.is_empty() {
123                         wfcheck::error_380(ccx, item.span);
124                     }
125                 }
126             }
127             _ => {}
128         }
129     }
130
131     fn with_fcx<F>(&mut self, item: &ast::Item, mut f: F) where
132         F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, &FnCtxt<'fcx, 'tcx>),
133     {
134         let ccx = self.ccx;
135         let item_def_id = DefId::local(item.id);
136         let type_scheme = ccx.tcx.lookup_item_type(item_def_id);
137         let type_predicates = ccx.tcx.lookup_predicates(item_def_id);
138         reject_non_type_param_bounds(ccx.tcx, item.span, &type_predicates);
139         let param_env = ccx.tcx.construct_parameter_environment(item.span,
140                                                                 &type_scheme.generics,
141                                                                 &type_predicates,
142                                                                 item.id);
143         let tables = RefCell::new(ty::Tables::empty());
144         let inh = Inherited::new(ccx.tcx, &tables, param_env);
145         let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id);
146         f(self, &fcx);
147         fcx.select_all_obligations_or_error();
148         regionck::regionck_item(&fcx, item.id, item.span, &[]);
149     }
150
151     /// In a type definition, we check that to ensure that the types of the fields are well-formed.
152     fn check_type_defn<F>(&mut self, item: &ast::Item, mut lookup_fields: F) where
153         F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
154     {
155         self.with_fcx(item, |this, fcx| {
156             let variants = lookup_fields(fcx);
157             let mut bounds_checker = BoundsChecker::new(fcx,
158                                                         item.id,
159                                                         Some(&mut this.cache));
160             debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope);
161
162             for variant in &variants {
163                 for field in &variant.fields {
164                     // Regions are checked below.
165                     bounds_checker.check_traits_in_ty(field.ty, field.span);
166                 }
167
168                 // For DST, all intermediate types must be sized.
169                 if let Some((_, fields)) = variant.fields.split_last() {
170                     for field in fields {
171                         fcx.register_builtin_bound(
172                             field.ty,
173                             ty::BoundSized,
174                             traits::ObligationCause::new(field.span,
175                                                          fcx.body_id,
176                                                          traits::FieldSized));
177                     }
178                 }
179             }
180
181             for field in variants.iter().flat_map(|v| v.fields.iter()) {
182                 fcx.register_old_wf_obligation(field.ty, field.span, traits::MiscObligation);
183             }
184         });
185     }
186
187     fn check_item_type(&mut self,
188                        item: &ast::Item)
189     {
190         self.with_fcx(item, |this, fcx| {
191             let mut bounds_checker = BoundsChecker::new(fcx,
192                                                         item.id,
193                                                         Some(&mut this.cache));
194             debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope);
195
196             let type_scheme = fcx.tcx().lookup_item_type(DefId::local(item.id));
197             let item_ty = fcx.instantiate_type_scheme(item.span,
198                                                       &fcx.inh
199                                                           .infcx
200                                                           .parameter_environment
201                                                           .free_substs,
202                                                       &type_scheme.ty);
203
204             bounds_checker.check_traits_in_ty(item_ty, item.span);
205         });
206     }
207
208     fn check_impl(&mut self,
209                   item: &ast::Item)
210     {
211         self.with_fcx(item, |this, fcx| {
212             let mut bounds_checker = BoundsChecker::new(fcx,
213                                                         item.id,
214                                                         Some(&mut this.cache));
215             debug!("check_impl at bounds_checker.scope: {:?}", bounds_checker.scope);
216
217             // Find the impl self type as seen from the "inside" --
218             // that is, with all type parameters converted from bound
219             // to free.
220             let self_ty = fcx.tcx().node_id_to_type(item.id);
221             let self_ty = fcx.instantiate_type_scheme(item.span,
222                                                       &fcx.inh
223                                                           .infcx
224                                                           .parameter_environment
225                                                           .free_substs,
226                                                       &self_ty);
227
228             bounds_checker.check_traits_in_ty(self_ty, item.span);
229
230             // Similarly, obtain an "inside" reference to the trait
231             // that the impl implements.
232             let trait_ref = match fcx.tcx().impl_trait_ref(DefId::local(item.id)) {
233                 None => { return; }
234                 Some(t) => { t }
235             };
236
237             let trait_ref = fcx.instantiate_type_scheme(item.span,
238                                                         &fcx.inh
239                                                             .infcx
240                                                             .parameter_environment
241                                                             .free_substs,
242                                                         &trait_ref);
243
244             // We are stricter on the trait-ref in an impl than the
245             // self-type.  In particular, we enforce region
246             // relationships. The reason for this is that (at least
247             // presently) "applying" an impl does not require that the
248             // application site check the well-formedness constraints on the
249             // trait reference. Instead, this is done at the impl site.
250             // Arguably this is wrong and we should treat the trait-reference
251             // the same way as we treat the self-type.
252             bounds_checker.check_trait_ref(&trait_ref, item.span);
253
254             let cause =
255                 traits::ObligationCause::new(
256                     item.span,
257                     fcx.body_id,
258                     traits::ItemObligation(trait_ref.def_id));
259
260             // Find the supertrait bounds. This will add `int:Bar`.
261             let poly_trait_ref = ty::Binder(trait_ref);
262             let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id());
263             let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref);
264             let predicates = {
265                 let selcx = &mut traits::SelectionContext::new(fcx.infcx());
266                 traits::normalize(selcx, cause.clone(), &predicates)
267             };
268             for predicate in predicates.value.predicates {
269                 fcx.register_predicate(traits::Obligation::new(cause.clone(), predicate));
270             }
271             for obligation in predicates.obligations {
272                 fcx.register_predicate(obligation);
273             }
274         });
275     }
276
277     fn check_variances_for_type_defn(&self,
278                                      item: &ast::Item,
279                                      ast_generics: &ast::Generics)
280     {
281         let item_def_id = DefId::local(item.id);
282         let ty_predicates = self.tcx().lookup_predicates(item_def_id);
283         let variances = self.tcx().item_variances(item_def_id);
284
285         let mut constrained_parameters: HashSet<_> =
286             variances.types
287                      .iter_enumerated()
288                      .filter(|&(_, _, &variance)| variance != ty::Bivariant)
289                      .map(|(space, index, _)| self.param_ty(ast_generics, space, index))
290                      .map(|p| Parameter::Type(p))
291                      .collect();
292
293         identify_constrained_type_params(self.tcx(),
294                                          ty_predicates.predicates.as_slice(),
295                                          None,
296                                          &mut constrained_parameters);
297
298         for (space, index, _) in variances.types.iter_enumerated() {
299             let param_ty = self.param_ty(ast_generics, space, index);
300             if constrained_parameters.contains(&Parameter::Type(param_ty)) {
301                 continue;
302             }
303             let span = self.ty_param_span(ast_generics, item, space, index);
304             self.report_bivariance(span, param_ty.name);
305         }
306
307         for (space, index, &variance) in variances.regions.iter_enumerated() {
308             if variance != ty::Bivariant {
309                 continue;
310             }
311
312             assert_eq!(space, TypeSpace);
313             let span = ast_generics.lifetimes[index].lifetime.span;
314             let name = ast_generics.lifetimes[index].lifetime.name;
315             self.report_bivariance(span, name);
316         }
317     }
318
319     fn param_ty(&self,
320                 ast_generics: &ast::Generics,
321                 space: ParamSpace,
322                 index: usize)
323                 -> ty::ParamTy
324     {
325         let name = match space {
326             TypeSpace => ast_generics.ty_params[index].ident.name,
327             SelfSpace => special_idents::type_self.name,
328             FnSpace => self.tcx().sess.bug("Fn space occupied?"),
329         };
330
331         ty::ParamTy { space: space, idx: index as u32, name: name }
332     }
333
334     fn ty_param_span(&self,
335                      ast_generics: &ast::Generics,
336                      item: &ast::Item,
337                      space: ParamSpace,
338                      index: usize)
339                      -> Span
340     {
341         match space {
342             TypeSpace => ast_generics.ty_params[index].span,
343             SelfSpace => item.span,
344             FnSpace => self.tcx().sess.span_bug(item.span, "Fn space occupied?"),
345         }
346     }
347
348     fn report_bivariance(&self,
349                          span: Span,
350                          param_name: ast::Name)
351     {
352         wfcheck::error_392(self.tcx(), span, param_name);
353
354         let suggested_marker_id = self.tcx().lang_items.phantom_data();
355         match suggested_marker_id {
356             Some(def_id) => {
357                 self.tcx().sess.fileline_help(
358                     span,
359                     &format!("consider removing `{}` or using a marker such as `{}`",
360                              param_name,
361                              self.tcx().item_path_str(def_id)));
362             }
363             None => {
364                 // no lang items, no help!
365             }
366         }
367     }
368 }
369
370 // Reject any predicates that do not involve a type parameter.
371 fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
372                                       span: Span,
373                                       predicates: &ty::GenericPredicates<'tcx>) {
374     for predicate in &predicates.predicates {
375         match predicate {
376             &ty::Predicate::Trait(ty::Binder(ref tr)) => {
377                 let found_param = tr.input_types().iter()
378                                     .flat_map(|ty| ty.walk())
379                                     .any(is_ty_param);
380                 if !found_param { report_bound_error(tcx, span, tr.self_ty() )}
381             }
382             &ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(ty, _))) => {
383                 let found_param = ty.walk().any(|t| is_ty_param(t));
384                 if !found_param { report_bound_error(tcx, span, ty) }
385             }
386             _ => {}
387         };
388     }
389
390     fn report_bound_error<'t>(tcx: &ty::ctxt<'t>,
391                           span: Span,
392                           bounded_ty: ty::Ty<'t>) {
393         span_err!(tcx.sess, span, E0193,
394             "cannot bound type `{}`, where clause \
395                 bounds may only be attached to types involving \
396                 type parameters",
397                 bounded_ty)
398     }
399
400     fn is_ty_param(ty: ty::Ty) -> bool {
401         match &ty.sty {
402             &ty::TyParam(_) => true,
403             _ => false
404         }
405     }
406 }
407
408 fn reject_shadowing_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>,
409                                           span: Span,
410                                           generics: &ty::Generics<'tcx>) {
411     let impl_params = generics.types.get_slice(subst::TypeSpace).iter()
412         .map(|tp| tp.name).collect::<HashSet<_>>();
413
414     for method_param in generics.types.get_slice(subst::FnSpace) {
415         if impl_params.contains(&method_param.name) {
416             wfcheck::error_194(tcx, span, method_param.name);
417         }
418     }
419 }
420
421 impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
422     fn visit_item(&mut self, i: &ast::Item) {
423         self.check_item_well_formed(i);
424         visit::walk_item(self, i);
425     }
426
427     fn visit_fn(&mut self,
428                 fk: FnKind<'v>, fd: &'v ast::FnDecl,
429                 b: &'v ast::Block, span: Span, id: ast::NodeId) {
430         match fk {
431             FnKind::Closure | FnKind::ItemFn(..) => {}
432             FnKind::Method(..) => {
433                 match self.tcx().impl_or_trait_item(DefId::local(id)) {
434                     ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
435                         reject_shadowing_type_parameters(self.tcx(), span, &ty_method.generics)
436                     }
437                     _ => {}
438                 }
439             }
440         }
441         visit::walk_fn(self, fk, fd, b, span)
442     }
443
444     fn visit_trait_item(&mut self, trait_item: &'v ast::TraitItem) {
445         if let ast::MethodTraitItem(_, None) = trait_item.node {
446             match self.tcx().impl_or_trait_item(DefId::local(trait_item.id)) {
447                 ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
448                     reject_non_type_param_bounds(
449                         self.tcx(),
450                         trait_item.span,
451                         &ty_method.predicates);
452                     reject_shadowing_type_parameters(
453                         self.tcx(),
454                         trait_item.span,
455                         &ty_method.generics);
456                 }
457                 _ => {}
458             }
459         }
460
461         visit::walk_trait_item(self, trait_item)
462     }
463 }
464
465 pub struct BoundsChecker<'cx,'tcx:'cx> {
466     fcx: &'cx FnCtxt<'cx,'tcx>,
467     span: Span,
468
469     scope: region::CodeExtent,
470
471     binding_count: usize,
472     cache: Option<&'cx mut HashSet<Ty<'tcx>>>,
473 }
474
475 impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
476     pub fn new(fcx: &'cx FnCtxt<'cx,'tcx>,
477                scope: ast::NodeId,
478                cache: Option<&'cx mut HashSet<Ty<'tcx>>>)
479                -> BoundsChecker<'cx,'tcx> {
480         let scope = fcx.tcx().region_maps.item_extent(scope);
481         BoundsChecker { fcx: fcx, span: DUMMY_SP, scope: scope,
482                         cache: cache, binding_count: 0 }
483     }
484
485     /// Given a trait ref like `A : Trait<B>`, where `Trait` is defined as (say):
486     ///
487     ///     trait Trait<B:OtherTrait> : Copy { ... }
488     ///
489     /// This routine will check that `B : OtherTrait` and `A : Trait<B>`. It will also recursively
490     /// check that the types `A` and `B` are well-formed.
491     ///
492     /// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated
493     /// to the point where impl `A : Trait<B>` is implemented).
494     pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, span: Span) {
495         let trait_predicates = self.fcx.tcx().lookup_predicates(trait_ref.def_id);
496
497         let bounds = self.fcx.instantiate_bounds(span,
498                                                  trait_ref.substs,
499                                                  &trait_predicates);
500
501         self.fcx.add_obligations_for_parameters(
502             traits::ObligationCause::new(
503                 span,
504                 self.fcx.body_id,
505                 traits::ItemObligation(trait_ref.def_id)),
506             &bounds);
507
508         for &ty in &trait_ref.substs.types {
509             self.check_traits_in_ty(ty, span);
510         }
511     }
512
513     fn check_traits_in_ty(&mut self, ty: Ty<'tcx>, span: Span) {
514         self.span = span;
515         // When checking types outside of a type def'n, we ignore
516         // region obligations. See discussion below in fold_ty().
517         self.binding_count += 1;
518         ty.fold_with(self);
519         self.binding_count -= 1;
520     }
521 }
522
523 impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
524     fn tcx(&self) -> &ty::ctxt<'tcx> {
525         self.fcx.tcx()
526     }
527
528     fn fold_binder<T>(&mut self, binder: &ty::Binder<T>) -> ty::Binder<T>
529         where T : TypeFoldable<'tcx>
530     {
531         self.binding_count += 1;
532         let value = self.fcx.tcx().liberate_late_bound_regions(
533             self.scope,
534             binder);
535         debug!("BoundsChecker::fold_binder: late-bound regions replaced: {:?} at scope: {:?}",
536                value, self.scope);
537         let value = value.fold_with(self);
538         self.binding_count -= 1;
539         ty::Binder(value)
540     }
541
542     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
543         debug!("BoundsChecker t={:?}",
544                t);
545
546         match self.cache {
547             Some(ref mut cache) => {
548                 if !cache.insert(t) {
549                     // Already checked this type! Don't check again.
550                     debug!("cached");
551                     return t;
552                 }
553             }
554             None => { }
555         }
556
557         match t.sty{
558             ty::TyStruct(def, substs) |
559             ty::TyEnum(def, substs) => {
560                 let type_predicates = def.predicates(self.fcx.tcx());
561                 let bounds = self.fcx.instantiate_bounds(self.span, substs,
562                                                          &type_predicates);
563
564                 if self.binding_count == 0 {
565                     self.fcx.add_obligations_for_parameters(
566                         traits::ObligationCause::new(self.span,
567                                                      self.fcx.body_id,
568                                                      traits::ItemObligation(def.did)),
569                         &bounds);
570                 } else {
571                     // There are two circumstances in which we ignore
572                     // region obligations.
573                     //
574                     // The first is when we are inside of a closure
575                     // type. This is because in that case the region
576                     // obligations for the parameter types are things
577                     // that the closure body gets to assume and the
578                     // caller must prove at the time of call. In other
579                     // words, if there is a type like `<'a, 'b> | &'a
580                     // &'b int |`, it is well-formed, and caller will
581                     // have to show that `'b : 'a` at the time of
582                     // call.
583                     //
584                     // The second is when we are checking for
585                     // well-formedness outside of a type def'n or fn
586                     // body. This is for a similar reason: in general,
587                     // we only do WF checking for regions in the
588                     // result of expressions and type definitions, so
589                     // to as allow for implicit where clauses.
590                     //
591                     // (I believe we should do the same for traits, but
592                     // that will require an RFC. -nmatsakis)
593                     let bounds = filter_to_trait_obligations(bounds);
594                     self.fcx.add_obligations_for_parameters(
595                         traits::ObligationCause::new(self.span,
596                                                      self.fcx.body_id,
597                                                      traits::ItemObligation(def.did)),
598                         &bounds);
599                 }
600
601                 self.fold_substs(substs);
602             }
603             _ => {
604                 super_fold_ty(self, t);
605             }
606         }
607
608         t // we're not folding to produce a new type, so just return `t` here
609     }
610 }
611
612 ///////////////////////////////////////////////////////////////////////////
613 // ADT
614
615 struct AdtVariant<'tcx> {
616     fields: Vec<AdtField<'tcx>>,
617 }
618
619 struct AdtField<'tcx> {
620     ty: Ty<'tcx>,
621     span: Span,
622 }
623
624 fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
625                             struct_def: &ast::StructDef)
626                             -> AdtVariant<'tcx> {
627     let fields =
628         struct_def.fields
629         .iter()
630         .map(|field| {
631             let field_ty = fcx.tcx().node_id_to_type(field.node.id);
632             let field_ty = fcx.instantiate_type_scheme(field.span,
633                                                        &fcx.inh
634                                                            .infcx
635                                                            .parameter_environment
636                                                            .free_substs,
637                                                        &field_ty);
638             AdtField { ty: field_ty, span: field.span }
639         })
640         .collect();
641     AdtVariant { fields: fields }
642 }
643
644 fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
645                            enum_def: &ast::EnumDef)
646                            -> Vec<AdtVariant<'tcx>> {
647     enum_def.variants.iter()
648         .map(|variant| {
649             match variant.node.kind {
650                 ast::TupleVariantKind(ref args) if !args.is_empty() => {
651                     let ctor_ty = fcx.tcx().node_id_to_type(variant.node.id);
652
653                     // the regions in the argument types come from the
654                     // enum def'n, and hence will all be early bound
655                     let arg_tys = fcx.tcx().no_late_bound_regions(&ctor_ty.fn_args()).unwrap();
656                     AdtVariant {
657                         fields: args.iter().enumerate().map(|(index, arg)| {
658                             let arg_ty = arg_tys[index];
659                             let arg_ty =
660                                 fcx.instantiate_type_scheme(variant.span,
661                                                             &fcx.inh
662                                                                 .infcx
663                                                                 .parameter_environment
664                                                                 .free_substs,
665                                                             &arg_ty);
666                             AdtField {
667                                 ty: arg_ty,
668                                 span: arg.ty.span
669                             }
670                         }).collect()
671                     }
672                 }
673                 ast::TupleVariantKind(_) => {
674                     AdtVariant {
675                         fields: Vec::new()
676                     }
677                 }
678                 ast::StructVariantKind(ref struct_def) => {
679                     struct_variant(fcx, &**struct_def)
680                 }
681             }
682         })
683         .collect()
684 }
685
686 fn filter_to_trait_obligations<'tcx>(bounds: ty::InstantiatedPredicates<'tcx>)
687                                      -> ty::InstantiatedPredicates<'tcx>
688 {
689     let mut result = ty::InstantiatedPredicates::empty();
690     for (space, _, predicate) in bounds.predicates.iter_enumerated() {
691         match *predicate {
692             ty::Predicate::Trait(..) |
693             ty::Predicate::Projection(..) => {
694                 result.predicates.push(space, predicate.clone())
695             }
696             ty::Predicate::WellFormed(..) |
697             ty::Predicate::ObjectSafe(..) |
698             ty::Predicate::Equate(..) |
699             ty::Predicate::TypeOutlives(..) |
700             ty::Predicate::RegionOutlives(..) => {
701             }
702         }
703     }
704     result
705 }