1 // Copyright 2012-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.
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.
15 The collect phase of type check has the job of visiting all items,
16 determining their type, and writing that type into the `tcx.tcache`
17 table. Despite its name, this table does not really operate as a
18 *cache*, at least not for the types of items defined within the
19 current crate: we assume that after the collect phase, the types of
20 all local items will be present in the table.
22 Unlike most of the types that are present in Rust, the types computed
23 for each item are in fact type schemes. This means that they are
24 generic types that may have type parameters. TypeSchemes are
25 represented by an instance of `ty::TypeScheme`. This combines the
26 core type along with a list of the bounds for each parameter. Type
27 parameters themselves are represented as `ty_param()` instances.
29 The phasing of type conversion is somewhat complicated. There is no
30 clear set of phases we can enforce (e.g., converting traits first,
31 then types, or something like that) because the user can introduce
32 arbitrary interdependencies. So instead we generally convert things
33 lazilly and on demand, and include logic that checks for cycles.
34 Demand is driven by calls to `AstConv::get_item_type_scheme` or
35 `AstConv::lookup_trait_def`.
37 Currently, we "convert" types and traits in three phases (note that
38 conversion only affects the types of items / enum variants / methods;
39 it does not e.g. compute the types of individual expressions):
45 Conversion itself is done by simply walking each of the items in turn
46 and invoking an appropriate function (e.g., `trait_def_of_item` or
47 `convert_item`). However, it is possible that while converting an
48 item, we may need to compute the *type scheme* or *trait definition*
51 There are some shortcomings in this design:
53 - Before walking the set of supertraits for a given trait, you must
54 call `ensure_super_predicates` on that trait def-id. Otherwise,
55 `lookup_super_predicates` will result in ICEs.
56 - Because the type scheme includes defaults, cycles through type
57 parameter defaults are illegal even if those defaults are never
58 employed. This is not necessarily a bug.
59 - The phasing of trait definitions before type definitions does not
60 seem to be necessary, sufficient, or particularly helpful, given that
61 processing a trait definition can trigger processing a type def and
62 vice versa. However, if I remove it, I get ICEs, so some more work is
63 needed in that area. -nmatsakis
67 use astconv
::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region}
;
69 use constrained_type_params
as ctp
;
70 use middle
::lang_items
::SizedTraitLangItem
;
71 use middle
::free_region
::FreeRegionMap
;
73 use middle
::resolve_lifetime
;
74 use middle
::subst
::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}
;
75 use middle
::ty
::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}
;
76 use middle
::ty
::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme}
;
77 use middle
::ty_fold
::{self, TypeFolder, TypeFoldable}
;
80 use util
::common
::{ErrorReported, memoized}
;
81 use util
::nodemap
::{FnvHashMap, FnvHashSet}
;
83 use util
::ppaux
::{Repr,UserString}
;
86 use std
::cell
::{Cell, RefCell}
;
87 use std
::collections
::HashSet
;
93 use syntax
::ast_util
::local_def
;
94 use syntax
::codemap
::Span
;
95 use syntax
::parse
::token
::special_idents
;
96 use syntax
::parse
::token
;
100 ///////////////////////////////////////////////////////////////////////////
103 pub fn collect_item_types(tcx
: &ty
::ctxt
) {
104 let ccx
= &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) }
;
106 let mut visitor
= CollectTraitDefVisitor{ ccx: ccx }
;
107 visit
::walk_crate(&mut visitor
, ccx
.tcx
.map
.krate());
109 let mut visitor
= CollectItemTypesVisitor{ ccx: ccx }
;
110 visit
::walk_crate(&mut visitor
, ccx
.tcx
.map
.krate());
113 ///////////////////////////////////////////////////////////////////////////
115 struct CrateCtxt
<'a
,'tcx
:'a
> {
116 tcx
: &'a ty
::ctxt
<'tcx
>,
118 // This stack is used to identify cycles in the user's source.
119 // Note that these cycles can cross multiple items.
120 stack
: RefCell
<Vec
<AstConvRequest
>>,
123 /// Context specific to some particular item. This is what implements
124 /// AstConv. It has information about the predicates that are defined
125 /// on the trait. Unfortunately, this predicate information is
126 /// available in various different forms at various points in the
127 /// process. So we can't just store a pointer to e.g. the AST or the
128 /// parsed ty form, we have to be more flexible. To this end, the
129 /// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object
130 /// that it uses to satisfy `get_type_parameter_bounds` requests.
131 /// This object might draw the information from the AST
132 /// (`ast::Generics`) or it might draw from a `ty::GenericPredicates`
133 /// or both (a tuple).
134 struct ItemCtxt
<'a
,'tcx
:'a
> {
135 ccx
: &'a CrateCtxt
<'a
,'tcx
>,
136 param_bounds
: &'
a (GetTypeParameterBounds
<'tcx
>+'a
),
139 #[derive(Copy, Clone, PartialEq, Eq)]
140 enum AstConvRequest
{
141 GetItemTypeScheme(ast
::DefId
),
142 GetTraitDef(ast
::DefId
),
143 EnsureSuperPredicates(ast
::DefId
),
144 GetTypeParameterBounds(ast
::NodeId
),
147 ///////////////////////////////////////////////////////////////////////////
148 // First phase: just collect *trait definitions* -- basically, the set
149 // of type parameters and supertraits. This is information we need to
150 // know later when parsing field defs.
152 struct CollectTraitDefVisitor
<'a
, 'tcx
: 'a
> {
153 ccx
: &'a CrateCtxt
<'a
, 'tcx
>
156 impl<'a
, 'tcx
, 'v
> visit
::Visitor
<'v
> for CollectTraitDefVisitor
<'a
, 'tcx
> {
157 fn visit_item(&mut self, i
: &ast
::Item
) {
159 ast
::ItemTrait(..) => {
160 // computing the trait def also fills in the table
161 let _
= trait_def_of_item(self.ccx
, i
);
166 visit
::walk_item(self, i
);
170 ///////////////////////////////////////////////////////////////////////////
171 // Second phase: collection proper.
173 struct CollectItemTypesVisitor
<'a
, 'tcx
: 'a
> {
174 ccx
: &'a CrateCtxt
<'a
, 'tcx
>
177 impl<'a
, 'tcx
, 'v
> visit
::Visitor
<'v
> for CollectItemTypesVisitor
<'a
, 'tcx
> {
178 fn visit_item(&mut self, i
: &ast
::Item
) {
179 convert_item(self.ccx
, i
);
180 visit
::walk_item(self, i
);
182 fn visit_foreign_item(&mut self, i
: &ast
::ForeignItem
) {
183 convert_foreign_item(self.ccx
, i
);
184 visit
::walk_foreign_item(self, i
);
188 ///////////////////////////////////////////////////////////////////////////
189 // Utility types and common code for the above passes.
191 impl<'a
,'tcx
> CrateCtxt
<'a
,'tcx
> {
192 fn icx(&'a
self, param_bounds
: &'a GetTypeParameterBounds
<'tcx
>) -> ItemCtxt
<'a
,'tcx
> {
193 ItemCtxt { ccx: self, param_bounds: param_bounds }
196 fn method_ty(&self, method_id
: ast
::NodeId
) -> Rc
<ty
::Method
<'tcx
>> {
197 let def_id
= local_def(method_id
);
198 match *self.tcx
.impl_or_trait_items
.borrow().get(&def_id
).unwrap() {
199 ty
::MethodTraitItem(ref mty
) => mty
.clone(),
201 self.tcx
.sess
.bug(&format
!("method with id {} has the wrong type", method_id
));
206 fn cycle_check
<F
,R
>(&self,
208 request
: AstConvRequest
,
210 -> Result
<R
,ErrorReported
>
211 where F
: FnOnce() -> Result
<R
,ErrorReported
>
214 let mut stack
= self.stack
.borrow_mut();
215 match stack
.iter().enumerate().rev().find(|&(_
, r
)| *r
== request
) {
218 let cycle
= &stack
[i
..];
219 self.report_cycle(span
, cycle
);
220 return Err(ErrorReported
);
228 self.stack
.borrow_mut().pop();
232 fn report_cycle(&self,
234 cycle
: &[AstConvRequest
])
236 assert
!(!cycle
.is_empty());
241 &format
!("unsupported cyclic reference between types/traits detected"));
244 AstConvRequest
::GetItemTypeScheme(def_id
) |
245 AstConvRequest
::GetTraitDef(def_id
) => {
247 &format
!("the cycle begins when processing `{}`...",
248 ty
::item_path_str(tcx
, def_id
)));
250 AstConvRequest
::EnsureSuperPredicates(def_id
) => {
252 &format
!("the cycle begins when computing the supertraits of `{}`...",
253 ty
::item_path_str(tcx
, def_id
)));
255 AstConvRequest
::GetTypeParameterBounds(id
) => {
256 let def
= tcx
.type_parameter_def(id
);
258 &format
!("the cycle begins when computing the bounds \
259 for type parameter `{}`...",
260 def
.name
.user_string(tcx
)));
264 for request
in cycle
[1..].iter() {
266 AstConvRequest
::GetItemTypeScheme(def_id
) |
267 AstConvRequest
::GetTraitDef(def_id
) => {
269 &format
!("...which then requires processing `{}`...",
270 ty
::item_path_str(tcx
, def_id
)));
272 AstConvRequest
::EnsureSuperPredicates(def_id
) => {
274 &format
!("...which then requires computing the supertraits of `{}`...",
275 ty
::item_path_str(tcx
, def_id
)));
277 AstConvRequest
::GetTypeParameterBounds(id
) => {
278 let def
= tcx
.type_parameter_def(id
);
280 &format
!("...which then requires computing the bounds \
281 for type parameter `{}`...",
282 def
.name
.user_string(tcx
)));
288 AstConvRequest
::GetItemTypeScheme(def_id
) |
289 AstConvRequest
::GetTraitDef(def_id
) => {
291 &format
!("...which then again requires processing `{}`, completing the cycle.",
292 ty
::item_path_str(tcx
, def_id
)));
294 AstConvRequest
::EnsureSuperPredicates(def_id
) => {
296 &format
!("...which then again requires computing the supertraits of `{}`, \
297 completing the cycle.",
298 ty
::item_path_str(tcx
, def_id
)));
300 AstConvRequest
::GetTypeParameterBounds(id
) => {
301 let def
= tcx
.type_parameter_def(id
);
303 &format
!("...which then again requires computing the bounds \
304 for type parameter `{}`, completing the cycle.",
305 def
.name
.user_string(tcx
)));
310 /// Loads the trait def for a given trait, returning ErrorReported if a cycle arises.
311 fn get_trait_def(&self, trait_id
: ast
::DefId
)
312 -> &'tcx ty
::TraitDef
<'tcx
>
316 if trait_id
.krate
!= ast
::LOCAL_CRATE
{
317 return ty
::lookup_trait_def(tcx
, trait_id
)
320 let item
= match tcx
.map
.get(trait_id
.node
) {
321 ast_map
::NodeItem(item
) => item
,
322 _
=> tcx
.sess
.bug(&format
!("get_trait_def({}): not an item", trait_id
.repr(tcx
)))
325 trait_def_of_item(self, &*item
)
328 /// Ensure that the (transitive) super predicates for
329 /// `trait_def_id` are available. This will report a cycle error
330 /// if a trait `X` (transitively) extends itself in some form.
331 fn ensure_super_predicates(&self, span
: Span
, trait_def_id
: ast
::DefId
)
332 -> Result
<(), ErrorReported
>
334 self.cycle_check(span
, AstConvRequest
::EnsureSuperPredicates(trait_def_id
), || {
335 let def_ids
= ensure_super_predicates_step(self, trait_def_id
);
337 for def_id
in def_ids
{
338 try
!(self.ensure_super_predicates(span
, def_id
));
346 impl<'a
,'tcx
> ItemCtxt
<'a
,'tcx
> {
347 fn to_ty
<RS
:RegionScope
>(&self, rs
: &RS
, ast_ty
: &ast
::Ty
) -> Ty
<'tcx
> {
348 ast_ty_to_ty(self, rs
, ast_ty
)
352 impl<'a
, 'tcx
> AstConv
<'tcx
> for ItemCtxt
<'a
, 'tcx
> {
353 fn tcx(&self) -> &ty
::ctxt
<'tcx
> { self.ccx.tcx }
355 fn get_item_type_scheme(&self, span
: Span
, id
: ast
::DefId
)
356 -> Result
<ty
::TypeScheme
<'tcx
>, ErrorReported
>
358 self.ccx
.cycle_check(span
, AstConvRequest
::GetItemTypeScheme(id
), || {
359 Ok(type_scheme_of_def_id(self.ccx
, id
))
363 fn get_trait_def(&self, span
: Span
, id
: ast
::DefId
)
364 -> Result
<&'tcx ty
::TraitDef
<'tcx
>, ErrorReported
>
366 self.ccx
.cycle_check(span
, AstConvRequest
::GetTraitDef(id
), || {
367 Ok(self.ccx
.get_trait_def(id
))
371 fn ensure_super_predicates(&self,
373 trait_def_id
: ast
::DefId
)
374 -> Result
<(), ErrorReported
>
376 debug
!("ensure_super_predicates(trait_def_id={})",
377 trait_def_id
.repr(self.tcx()));
379 self.ccx
.ensure_super_predicates(span
, trait_def_id
)
383 fn get_type_parameter_bounds(&self,
385 node_id
: ast
::NodeId
)
386 -> Result
<Vec
<ty
::PolyTraitRef
<'tcx
>>, ErrorReported
>
388 self.ccx
.cycle_check(span
, AstConvRequest
::GetTypeParameterBounds(node_id
), || {
389 let v
= self.param_bounds
.get_type_parameter_bounds(self, span
, node_id
)
391 .filter_map(|p
| p
.to_opt_poly_trait_ref())
397 fn trait_defines_associated_type_named(&self,
398 trait_def_id
: ast
::DefId
,
399 assoc_name
: ast
::Name
)
402 if trait_def_id
.krate
== ast
::LOCAL_CRATE
{
403 trait_defines_associated_type_named(self.ccx
, trait_def_id
.node
, assoc_name
)
405 let trait_def
= ty
::lookup_trait_def(self.tcx(), trait_def_id
);
406 trait_def
.associated_type_names
.contains(&assoc_name
)
410 fn ty_infer(&self, span
: Span
) -> Ty
<'tcx
> {
411 span_err
!(self.tcx().sess
, span
, E0121
,
412 "the type placeholder `_` is not allowed within types on item signatures");
416 fn projected_ty(&self,
418 trait_ref
: ty
::TraitRef
<'tcx
>,
419 item_name
: ast
::Name
)
422 ty
::mk_projection(self.tcx(), trait_ref
, item_name
)
426 /// Interface used to find the bounds on a type parameter from within
427 /// an `ItemCtxt`. This allows us to use multiple kinds of sources.
428 trait GetTypeParameterBounds
<'tcx
> {
429 fn get_type_parameter_bounds(&self,
430 astconv
: &AstConv
<'tcx
>,
432 node_id
: ast
::NodeId
)
433 -> Vec
<ty
::Predicate
<'tcx
>>;
436 /// Find bounds from both elements of the tuple.
437 impl<'a
,'b
,'tcx
,A
,B
> GetTypeParameterBounds
<'tcx
> for (&'a A
,&'b B
)
438 where A
: GetTypeParameterBounds
<'tcx
>, B
: GetTypeParameterBounds
<'tcx
>
440 fn get_type_parameter_bounds(&self,
441 astconv
: &AstConv
<'tcx
>,
443 node_id
: ast
::NodeId
)
444 -> Vec
<ty
::Predicate
<'tcx
>>
446 let mut v
= self.0.get_type_parameter_bounds(astconv
, span
, node_id
);
447 v
.extend(self.1.get_type_parameter_bounds(astconv
, span
, node_id
).into_iter());
452 /// Empty set of bounds.
453 impl<'tcx
> GetTypeParameterBounds
<'tcx
> for () {
454 fn get_type_parameter_bounds(&self,
455 _astconv
: &AstConv
<'tcx
>,
457 _node_id
: ast
::NodeId
)
458 -> Vec
<ty
::Predicate
<'tcx
>>
464 /// Find bounds from the parsed and converted predicates. This is
465 /// used when converting methods, because by that time the predicates
466 /// from the trait/impl have been fully converted.
467 impl<'tcx
> GetTypeParameterBounds
<'tcx
> for ty
::GenericPredicates
<'tcx
> {
468 fn get_type_parameter_bounds(&self,
469 astconv
: &AstConv
<'tcx
>,
471 node_id
: ast
::NodeId
)
472 -> Vec
<ty
::Predicate
<'tcx
>>
474 let def
= astconv
.tcx().type_parameter_def(node_id
);
478 .filter(|predicate
| {
480 ty
::Predicate
::Trait(ref data
) => {
481 data
.skip_binder().self_ty().is_param(def
.space
, def
.index
)
483 ty
::Predicate
::TypeOutlives(ref data
) => {
484 data
.skip_binder().0.is_param
(def
.space
, def
.index
)
486 ty
::Predicate
::Equate(..) |
487 ty
::Predicate
::RegionOutlives(..) |
488 ty
::Predicate
::Projection(..) => {
498 /// Find bounds from ast::Generics. This requires scanning through the
499 /// AST. We do this to avoid having to convert *all* the bounds, which
500 /// would create artificial cycles. Instead we can only convert the
501 /// bounds for those a type parameter `X` if `X::Foo` is used.
502 impl<'tcx
> GetTypeParameterBounds
<'tcx
> for ast
::Generics
{
503 fn get_type_parameter_bounds(&self,
504 astconv
: &AstConv
<'tcx
>,
506 node_id
: ast
::NodeId
)
507 -> Vec
<ty
::Predicate
<'tcx
>>
509 // In the AST, bounds can derive from two places. Either
510 // written inline like `<T:Foo>` or in a where clause like
513 let def
= astconv
.tcx().type_parameter_def(node_id
);
514 let ty
= ty
::mk_param_from_def(astconv
.tcx(), &def
);
519 .filter(|p
| p
.id
== node_id
)
520 .flat_map(|p
| p
.bounds
.iter())
521 .flat_map(|b
| predicates_from_bound(astconv
, ty
, b
).into_iter());
523 let from_where_clauses
=
527 .filter_map(|wp
| match *wp
{
528 ast
::WherePredicate
::BoundPredicate(ref bp
) => Some(bp
),
531 .filter(|bp
| is_param(astconv
.tcx(), &bp
.bounded_ty
, node_id
))
532 .flat_map(|bp
| bp
.bounds
.iter())
533 .flat_map(|b
| predicates_from_bound(astconv
, ty
, b
).into_iter());
535 from_ty_params
.chain(from_where_clauses
).collect()
539 /// Tests whether this is the AST for a reference to the type
540 /// parameter with id `param_id`. We use this so as to avoid running
541 /// `ast_ty_to_ty`, because we want to avoid triggering an all-out
542 /// conversion of the type to avoid inducing unnecessary cycles.
543 fn is_param
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>,
545 param_id
: ast
::NodeId
)
548 if let ast
::TyPath(None
, _
) = ast_ty
.node
{
549 let path_res
= *tcx
.def_map
.borrow().get(&ast_ty
.id
).unwrap();
550 match path_res
.base_def
{
551 def
::DefSelfTy(Some(def_id
), None
) => {
552 path_res
.depth
== 0 && def_id
.node
== param_id
554 def
::DefTyParam(_
, _
, def_id
, _
) => {
555 path_res
.depth
== 0 && def_id
== local_def(param_id
)
566 fn get_enum_variant_types
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
567 enum_scheme
: ty
::TypeScheme
<'tcx
>,
568 enum_predicates
: ty
::GenericPredicates
<'tcx
>,
569 variants
: &[P
<ast
::Variant
>]) {
571 let icx
= ccx
.icx(&enum_predicates
);
573 // Create a set of parameter types shared among all the variants.
574 for variant
in variants
{
575 let variant_def_id
= local_def(variant
.node
.id
);
577 // Nullary enum constructors get turned into constants; n-ary enum
578 // constructors get turned into functions.
579 let result_ty
= match variant
.node
.kind
{
580 ast
::TupleVariantKind(ref args
) if !args
.is_empty() => {
581 let rs
= ExplicitRscope
;
582 let input_tys
: Vec
<_
> = args
.iter().map(|va
| icx
.to_ty(&rs
, &*va
.ty
)).collect();
583 ty
::mk_ctor_fn(tcx
, variant_def_id
, &input_tys
, enum_scheme
.ty
)
586 ast
::TupleVariantKind(_
) => {
590 ast
::StructVariantKind(ref struct_def
) => {
591 convert_struct(ccx
, &**struct_def
, enum_scheme
.clone(),
592 enum_predicates
.clone(), variant
.node
.id
);
597 let variant_scheme
= TypeScheme
{
598 generics
: enum_scheme
.generics
.clone(),
602 tcx
.tcache
.borrow_mut().insert(variant_def_id
, variant_scheme
.clone());
603 tcx
.predicates
.borrow_mut().insert(variant_def_id
, enum_predicates
.clone());
604 write_ty_to_tcx(tcx
, variant
.node
.id
, result_ty
);
608 fn convert_method
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
609 container
: ImplOrTraitItemContainer
,
610 sig
: &ast
::MethodSig
,
613 vis
: ast
::Visibility
,
614 untransformed_rcvr_ty
: Ty
<'tcx
>,
615 rcvr_ty_generics
: &ty
::Generics
<'tcx
>,
616 rcvr_ty_predicates
: &ty
::GenericPredicates
<'tcx
>) {
617 let ty_generics
= ty_generics_for_fn(ccx
, &sig
.generics
, rcvr_ty_generics
);
619 let ty_generic_predicates
=
620 ty_generic_predicates_for_fn(ccx
, &sig
.generics
, rcvr_ty_predicates
);
622 let (fty
, explicit_self_category
) =
623 astconv
::ty_of_method(&ccx
.icx(&(rcvr_ty_predicates
, &sig
.generics
)),
624 sig
, untransformed_rcvr_ty
);
626 let def_id
= local_def(id
);
627 let ty_method
= ty
::Method
::new(ident
.name
,
629 ty_generic_predicates
,
631 explicit_self_category
,
637 let fty
= ty
::mk_bare_fn(ccx
.tcx
, Some(def_id
),
638 ccx
.tcx
.mk_bare_fn(ty_method
.fty
.clone()));
639 debug
!("method {} (id {}) has type {}",
640 ident
.repr(ccx
.tcx
), id
, fty
.repr(ccx
.tcx
));
641 ccx
.tcx
.tcache
.borrow_mut().insert(def_id
,TypeScheme
{
642 generics
: ty_method
.generics
.clone(),
645 ccx
.tcx
.predicates
.borrow_mut().insert(def_id
, ty_method
.predicates
.clone());
647 write_ty_to_tcx(ccx
.tcx
, id
, fty
);
649 debug
!("writing method type: def_id={:?} mty={}",
650 def_id
, ty_method
.repr(ccx
.tcx
));
652 ccx
.tcx
.impl_or_trait_items
.borrow_mut().insert(def_id
,
653 ty
::MethodTraitItem(Rc
::new(ty_method
)));
656 fn convert_field
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
657 struct_generics
: &ty
::Generics
<'tcx
>,
658 struct_predicates
: &ty
::GenericPredicates
<'tcx
>,
659 v
: &ast
::StructField
,
663 let tt
= ccx
.icx(struct_predicates
).to_ty(&ExplicitRscope
, &*v
.node
.ty
);
664 write_ty_to_tcx(ccx
.tcx
, v
.node
.id
, tt
);
666 /* add the field to the tcache */
667 ccx
.tcx
.tcache
.borrow_mut().insert(local_def(v
.node
.id
),
669 generics
: struct_generics
.clone(),
672 ccx
.tcx
.predicates
.borrow_mut().insert(local_def(v
.node
.id
),
673 struct_predicates
.clone());
676 ast
::NamedField(ident
, visibility
) => {
679 id
: local_def(v
.node
.id
),
684 ast
::UnnamedField(visibility
) => {
686 name
: special_idents
::unnamed_field
.name
,
687 id
: local_def(v
.node
.id
),
695 fn convert_associated_const
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
696 container
: ImplOrTraitItemContainer
,
699 vis
: ast
::Visibility
,
701 default: Option
<&ast
::Expr
>)
703 ccx
.tcx
.predicates
.borrow_mut().insert(local_def(id
),
704 ty
::GenericPredicates
::empty());
706 write_ty_to_tcx(ccx
.tcx
, id
, ty
);
707 let default_id
= default.map(|expr
| local_def(expr
.id
));
709 let associated_const
= Rc
::new(ty
::AssociatedConst
{
712 def_id
: local_def(id
),
713 container
: container
,
717 ccx
.tcx
.impl_or_trait_items
.borrow_mut()
718 .insert(local_def(id
), ty
::ConstTraitItem(associated_const
));
721 fn as_refsociated_type
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
722 container
: ImplOrTraitItemContainer
,
725 vis
: ast
::Visibility
)
727 let associated_type
= Rc
::new(ty
::AssociatedType
{
730 def_id
: local_def(id
),
733 ccx
.tcx
.impl_or_trait_items
.borrow_mut()
734 .insert(local_def(id
), ty
::TypeTraitItem(associated_type
));
737 fn convert_methods
<'a
,'tcx
,'i
,I
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
738 container
: ImplOrTraitItemContainer
,
740 untransformed_rcvr_ty
: Ty
<'tcx
>,
741 rcvr_ty_generics
: &ty
::Generics
<'tcx
>,
742 rcvr_ty_predicates
: &ty
::GenericPredicates
<'tcx
>)
743 where I
: Iterator
<Item
=(&'i ast
::MethodSig
, ast
::NodeId
, ast
::Ident
, ast
::Visibility
, Span
)>
745 debug
!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={}, rcvr_ty_predicates={})",
746 untransformed_rcvr_ty
.repr(ccx
.tcx
),
747 rcvr_ty_generics
.repr(ccx
.tcx
),
748 rcvr_ty_predicates
.repr(ccx
.tcx
));
751 let mut seen_methods
= FnvHashSet();
752 for (sig
, id
, ident
, vis
, span
) in methods
{
753 if !seen_methods
.insert(ident
.name
) {
754 span_err
!(tcx
.sess
, span
, E0201
, "duplicate method");
763 untransformed_rcvr_ty
,
769 fn ensure_no_ty_param_bounds(ccx
: &CrateCtxt
,
771 generics
: &ast
::Generics
,
772 thing
: &'
static str) {
773 let mut warn
= false;
775 for ty_param
in &*generics
.ty_params
{
776 for bound
in &*ty_param
.bounds
{
778 ast
::TraitTyParamBound(..) => {
781 ast
::RegionTyParamBound(..) => { }
787 // According to accepted RFC #XXX, we should
788 // eventually accept these, but it will not be
789 // part of this PR. Still, convert to warning to
790 // make bootstrapping easier.
791 span_warn
!(ccx
.tcx
.sess
, span
, E0122
,
792 "trait bounds are not (yet) enforced \
798 fn convert_item(ccx
: &CrateCtxt
, it
: &ast
::Item
) {
800 debug
!("convert: item {} with id {}", token
::get_ident(it
.ident
), it
.id
);
802 // These don't define types.
803 ast
::ItemExternCrate(_
) | ast
::ItemUse(_
) |
804 ast
::ItemForeignMod(_
) | ast
::ItemMod(_
) | ast
::ItemMac(_
) => {
806 ast
::ItemEnum(ref enum_definition
, _
) => {
807 let (scheme
, predicates
) = convert_typed_item(ccx
, it
);
808 write_ty_to_tcx(tcx
, it
.id
, scheme
.ty
);
809 get_enum_variant_types(ccx
,
812 &enum_definition
.variants
);
814 ast
::ItemDefaultImpl(_
, ref ast_trait_ref
) => {
816 astconv
::instantiate_mono_trait_ref(&ccx
.icx(&()),
821 ty
::record_trait_has_default_impl(tcx
, trait_ref
.def_id
);
823 tcx
.impl_trait_refs
.borrow_mut().insert(it
.id
, trait_ref
);
830 // Create generics from the generics specified in the impl head.
832 debug
!("convert: ast_generics={:?}", generics
);
833 let ty_generics
= ty_generics_for_type_or_impl(ccx
, generics
);
834 let ty_predicates
= ty_generic_predicates_for_type_or_impl(ccx
, generics
);
836 debug
!("convert: impl_bounds={:?}", ty_predicates
);
838 let selfty
= ccx
.icx(&ty_predicates
).to_ty(&ExplicitRscope
, &**selfty
);
839 write_ty_to_tcx(tcx
, it
.id
, selfty
);
841 tcx
.tcache
.borrow_mut().insert(local_def(it
.id
),
842 TypeScheme
{ generics
: ty_generics
.clone(),
844 tcx
.predicates
.borrow_mut().insert(local_def(it
.id
),
845 ty_predicates
.clone());
847 // If there is a trait reference, treat the methods as always public.
848 // This is to work around some incorrect behavior in privacy checking:
849 // when the method belongs to a trait, it should acquire the privacy
850 // from the trait, not the impl. Forcing the visibility to be public
851 // makes things sorta work.
852 let parent_visibility
= if opt_trait_ref
.is_some() {
858 // Convert all the associated consts.
859 for impl_item
in impl_items
{
860 if let ast
::ConstImplItem(ref ty
, ref expr
) = impl_item
.node
{
861 let ty
= ccx
.icx(&ty_predicates
)
862 .to_ty(&ExplicitRscope
, &*ty
);
863 tcx
.tcache
.borrow_mut().insert(local_def(impl_item
.id
),
865 generics
: ty_generics
.clone(),
868 convert_associated_const(ccx
, ImplContainer(local_def(it
.id
)),
869 impl_item
.ident
, impl_item
.id
,
870 impl_item
.vis
.inherit_from(parent_visibility
),
875 // Convert all the associated types.
876 for impl_item
in impl_items
{
877 if let ast
::TypeImplItem(ref ty
) = impl_item
.node
{
878 if opt_trait_ref
.is_none() {
879 span_err
!(tcx
.sess
, impl_item
.span
, E0202
,
880 "associated items are not allowed in inherent impls");
883 as_refsociated_type(ccx
, ImplContainer(local_def(it
.id
)),
884 impl_item
.ident
, impl_item
.id
, impl_item
.vis
);
886 let typ
= ccx
.icx(&ty_predicates
).to_ty(&ExplicitRscope
, ty
);
887 tcx
.tcache
.borrow_mut().insert(local_def(impl_item
.id
),
889 generics
: ty
::Generics
::empty(),
892 tcx
.predicates
.borrow_mut().insert(local_def(impl_item
.id
),
893 ty
::GenericPredicates
::empty());
894 write_ty_to_tcx(tcx
, impl_item
.id
, typ
);
898 let methods
= impl_items
.iter().filter_map(|ii
| {
899 if let ast
::MethodImplItem(ref sig
, _
) = ii
.node
{
900 // if the method specifies a visibility, use that, otherwise
901 // inherit the visibility from the impl (so `foo` in `pub impl
902 // { fn foo(); }` is public, but private in `impl { fn
904 let method_vis
= ii
.vis
.inherit_from(parent_visibility
);
905 Some((sig
, ii
.id
, ii
.ident
, method_vis
, ii
.span
))
911 ImplContainer(local_def(it
.id
)),
917 for impl_item
in impl_items
{
918 if let ast
::MethodImplItem(ref sig
, ref body
) = impl_item
.node
{
919 let body_id
= body
.id
;
920 check_method_self_type(ccx
,
921 &BindingRscope
::new(),
922 ccx
.method_ty(impl_item
.id
),
929 if let Some(ref ast_trait_ref
) = *opt_trait_ref
{
931 astconv
::instantiate_mono_trait_ref(&ccx
.icx(&ty_predicates
),
936 tcx
.impl_trait_refs
.borrow_mut().insert(it
.id
, trait_ref
);
939 enforce_impl_params_are_constrained(tcx
,
944 ast
::ItemTrait(_
, _
, _
, ref trait_items
) => {
945 let trait_def
= trait_def_of_item(ccx
, it
);
946 let _
: Result
<(), ErrorReported
> = // any error is already reported, can ignore
947 ccx
.ensure_super_predicates(it
.span
, local_def(it
.id
));
948 convert_trait_predicates(ccx
, it
);
949 let trait_predicates
= ty
::lookup_predicates(tcx
, local_def(it
.id
));
951 debug
!("convert: trait_bounds={:?}", trait_predicates
);
953 // Convert all the associated types.
954 for trait_item
in trait_items
{
955 match trait_item
.node
{
956 ast
::ConstTraitItem(ref ty
, ref default) => {
957 let ty
= ccx
.icx(&trait_predicates
)
958 .to_ty(&ExplicitRscope
, ty
);
959 tcx
.tcache
.borrow_mut().insert(local_def(trait_item
.id
),
961 generics
: trait_def
.generics
.clone(),
964 convert_associated_const(ccx
, TraitContainer(local_def(it
.id
)),
965 trait_item
.ident
, trait_item
.id
,
966 ast
::Public
, ty
, default.as_ref().map(|d
| &**d
));
972 // Convert all the associated types.
973 for trait_item
in trait_items
{
974 match trait_item
.node
{
975 ast
::TypeTraitItem(..) => {
976 as_refsociated_type(ccx
, TraitContainer(local_def(it
.id
)),
977 trait_item
.ident
, trait_item
.id
, ast
::Public
);
983 let methods
= trait_items
.iter().filter_map(|ti
| {
984 let sig
= match ti
.node
{
985 ast
::MethodTraitItem(ref sig
, _
) => sig
,
988 Some((sig
, ti
.id
, ti
.ident
, ast
::Inherited
, ti
.span
))
991 // Run convert_methods on the trait methods.
993 TraitContainer(local_def(it
.id
)),
995 ty
::mk_self_type(tcx
),
999 // Add an entry mapping
1000 let trait_item_def_ids
= Rc
::new(trait_items
.iter().map(|trait_item
| {
1001 let def_id
= local_def(trait_item
.id
);
1002 match trait_item
.node
{
1003 ast
::ConstTraitItem(..) => {
1004 ty
::ConstTraitItemId(def_id
)
1006 ast
::MethodTraitItem(..) => {
1007 ty
::MethodTraitItemId(def_id
)
1009 ast
::TypeTraitItem(..) => {
1010 ty
::TypeTraitItemId(def_id
)
1014 tcx
.trait_item_def_ids
.borrow_mut().insert(local_def(it
.id
), trait_item_def_ids
);
1016 // This must be done after `collect_trait_methods` so that
1017 // we have a method type stored for every method.
1018 for trait_item
in trait_items
{
1019 let sig
= match trait_item
.node
{
1020 ast
::MethodTraitItem(ref sig
, _
) => sig
,
1023 check_method_self_type(ccx
,
1024 &BindingRscope
::new(),
1025 ccx
.method_ty(trait_item
.id
),
1026 ty
::mk_self_type(tcx
),
1031 ast
::ItemStruct(ref struct_def
, _
) => {
1032 // Write the class type.
1033 let (scheme
, predicates
) = convert_typed_item(ccx
, it
);
1034 write_ty_to_tcx(tcx
, it
.id
, scheme
.ty
);
1035 convert_struct(ccx
, &**struct_def
, scheme
, predicates
, it
.id
);
1037 ast
::ItemTy(_
, ref generics
) => {
1038 ensure_no_ty_param_bounds(ccx
, it
.span
, generics
, "type");
1039 let (scheme
, _
) = convert_typed_item(ccx
, it
);
1040 write_ty_to_tcx(tcx
, it
.id
, scheme
.ty
);
1043 // This call populates the type cache with the converted type
1044 // of the item in passing. All we have to do here is to write
1045 // it into the node type table.
1046 let (scheme
, _
) = convert_typed_item(ccx
, it
);
1047 write_ty_to_tcx(tcx
, it
.id
, scheme
.ty
);
1052 fn convert_struct
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
1053 struct_def
: &ast
::StructDef
,
1054 scheme
: ty
::TypeScheme
<'tcx
>,
1055 predicates
: ty
::GenericPredicates
<'tcx
>,
1059 // Write the type of each of the members and check for duplicate fields.
1060 let mut seen_fields
: FnvHashMap
<ast
::Name
, Span
> = FnvHashMap();
1061 let field_tys
= struct_def
.fields
.iter().map(|f
| {
1062 let result
= convert_field(ccx
, &scheme
.generics
, &predicates
, f
, local_def(id
));
1064 if result
.name
!= special_idents
::unnamed_field
.name
{
1065 let dup
= match seen_fields
.get(&result
.name
) {
1066 Some(prev_span
) => {
1067 span_err
!(tcx
.sess
, f
.span
, E0124
,
1068 "field `{}` is already declared",
1069 token
::get_name(result
.name
));
1070 span_note
!(tcx
.sess
, *prev_span
, "previously declared here");
1075 // FIXME(#6393) this whole dup thing is just to satisfy
1076 // the borrow checker :-(
1078 seen_fields
.insert(result
.name
, f
.span
);
1085 tcx
.struct_fields
.borrow_mut().insert(local_def(id
), Rc
::new(field_tys
));
1087 let substs
= mk_item_substs(ccx
, &scheme
.generics
);
1088 let selfty
= ty
::mk_struct(tcx
, local_def(id
), tcx
.mk_substs(substs
));
1090 // If this struct is enum-like or tuple-like, create the type of its
1092 match struct_def
.ctor_id
{
1095 if struct_def
.fields
.is_empty() {
1097 write_ty_to_tcx(tcx
, ctor_id
, selfty
);
1099 tcx
.tcache
.borrow_mut().insert(local_def(ctor_id
), scheme
);
1100 tcx
.predicates
.borrow_mut().insert(local_def(ctor_id
), predicates
);
1101 } else if struct_def
.fields
[0].node
.kind
.is_unnamed() {
1103 let inputs
: Vec
<_
> =
1106 .map(|field
| tcx
.tcache
.borrow().get(&local_def(field
.node
.id
))
1110 let ctor_fn_ty
= ty
::mk_ctor_fn(tcx
,
1114 write_ty_to_tcx(tcx
, ctor_id
, ctor_fn_ty
);
1115 tcx
.tcache
.borrow_mut().insert(local_def(ctor_id
),
1117 generics
: scheme
.generics
,
1120 tcx
.predicates
.borrow_mut().insert(local_def(ctor_id
), predicates
);
1126 /// Ensures that the super-predicates of the trait with def-id
1127 /// trait_def_id are converted and stored. This does NOT ensure that
1128 /// the transitive super-predicates are converted; that is the job of
1129 /// the `ensure_super_predicates()` method in the `AstConv` impl
1130 /// above. Returns a list of trait def-ids that must be ensured as
1131 /// well to guarantee that the transitive superpredicates are
1133 fn ensure_super_predicates_step(ccx
: &CrateCtxt
,
1134 trait_def_id
: ast
::DefId
)
1139 debug
!("ensure_super_predicates_step(trait_def_id={})", trait_def_id
.repr(tcx
));
1141 if trait_def_id
.krate
!= ast
::LOCAL_CRATE
{
1142 // If this trait comes from an external crate, then all of the
1143 // supertraits it may depend on also must come from external
1144 // crates, and hence all of them already have their
1145 // super-predicates "converted" (and available from crate
1146 // meta-data), so there is no need to transitively test them.
1150 let superpredicates
= tcx
.super_predicates
.borrow().get(&trait_def_id
).cloned();
1151 let superpredicates
= superpredicates
.unwrap_or_else(|| {
1152 let trait_node_id
= trait_def_id
.node
;
1154 let item
= match ccx
.tcx
.map
.get(trait_node_id
) {
1155 ast_map
::NodeItem(item
) => item
,
1156 _
=> ccx
.tcx
.sess
.bug(&format
!("trait_node_id {} is not an item", trait_node_id
))
1159 let (generics
, bounds
) = match item
.node
{
1160 ast
::ItemTrait(_
, ref generics
, ref supertraits
, _
) => (generics
, supertraits
),
1161 _
=> tcx
.sess
.span_bug(item
.span
,
1162 "ensure_super_predicates_step invoked on non-trait"),
1165 // In-scope when converting the superbounds for `Trait` are
1166 // that `Self:Trait` as well as any bounds that appear on the
1168 let trait_def
= trait_def_of_item(ccx
, item
);
1169 let self_predicate
= ty
::GenericPredicates
{
1170 predicates
: VecPerParamSpace
::new(vec
![],
1171 vec
![trait_def
.trait_ref
.as_predicate()],
1174 let scope
= &(generics
, &self_predicate
);
1176 // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
1177 let self_param_ty
= ty
::mk_self_type(tcx
);
1178 let superbounds1
= compute_bounds(&ccx
.icx(scope
), self_param_ty
, bounds
,
1179 SizedByDefault
::No
, item
.span
);
1180 let superbounds1
= ty
::predicates(tcx
, self_param_ty
, &superbounds1
);
1182 // Convert any explicit superbounds in the where clause,
1183 // e.g. `trait Foo where Self : Bar`:
1184 let superbounds2
= generics
.get_type_parameter_bounds(&ccx
.icx(scope
), item
.span
, item
.id
);
1186 // Combine the two lists to form the complete set of superbounds:
1187 let superbounds
= superbounds1
.into_iter().chain(superbounds2
.into_iter()).collect();
1188 let superpredicates
= ty
::GenericPredicates
{
1189 predicates
: VecPerParamSpace
::new(superbounds
, vec
![], vec
![])
1191 debug
!("superpredicates for trait {} = {}",
1192 local_def(item
.id
).repr(ccx
.tcx
),
1193 superpredicates
.repr(ccx
.tcx
));
1195 tcx
.super_predicates
.borrow_mut().insert(trait_def_id
, superpredicates
.clone());
1200 let def_ids
: Vec
<_
> = superpredicates
.predicates
1202 .filter_map(|p
| p
.to_opt_poly_trait_ref())
1203 .map(|tr
| tr
.def_id())
1206 debug
!("ensure_super_predicates_step: def_ids={}", def_ids
.repr(tcx
));
1211 fn trait_def_of_item
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
1213 -> &'tcx ty
::TraitDef
<'tcx
>
1215 let def_id
= local_def(it
.id
);
1218 if let Some(def
) = tcx
.trait_defs
.borrow().get(&def_id
) {
1222 let (unsafety
, generics
, items
) = match it
.node
{
1223 ast
::ItemTrait(unsafety
, ref generics
, _
, ref items
) => (unsafety
, generics
, items
),
1224 _
=> tcx
.sess
.span_bug(it
.span
, "trait_def_of_item invoked on non-trait"),
1227 let paren_sugar
= ty
::has_attr(tcx
, def_id
, "rustc_paren_sugar");
1228 if paren_sugar
&& !ccx
.tcx
.sess
.features
.borrow().unboxed_closures
{
1229 ccx
.tcx
.sess
.span_err(
1231 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
1232 which traits can use parenthetical notation");
1233 fileline_help
!(ccx
.tcx
.sess
, it
.span
,
1234 "add `#![feature(unboxed_closures)]` to \
1235 the crate attributes to use it");
1238 let substs
= ccx
.tcx
.mk_substs(mk_trait_substs(ccx
, generics
));
1240 let ty_generics
= ty_generics_for_trait(ccx
, it
.id
, substs
, generics
);
1242 let associated_type_names
: Vec
<_
> = items
.iter().filter_map(|trait_item
| {
1243 match trait_item
.node
{
1244 ast
::TypeTraitItem(..) => Some(trait_item
.ident
.name
),
1249 let trait_ref
= ty
::TraitRef
{
1254 let trait_def
= ty
::TraitDef
{
1255 paren_sugar
: paren_sugar
,
1257 generics
: ty_generics
,
1258 trait_ref
: trait_ref
,
1259 associated_type_names
: associated_type_names
,
1260 nonblanket_impls
: RefCell
::new(FnvHashMap()),
1261 blanket_impls
: RefCell
::new(vec
![]),
1262 flags
: Cell
::new(ty
::TraitFlags
::NO_TRAIT_FLAGS
)
1265 return tcx
.intern_trait_def(trait_def
);
1267 fn mk_trait_substs
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
1268 generics
: &ast
::Generics
)
1273 // Creates a no-op substitution for the trait's type parameters.
1278 .map(|(i
, def
)| ty
::ReEarlyBound(ty
::EarlyBoundRegion
{
1279 param_id
: def
.lifetime
.id
,
1282 name
: def
.lifetime
.name
1286 // Start with the generics in the type parameters...
1291 .map(|(i
, def
)| ty
::mk_param(tcx
, TypeSpace
,
1292 i
as u32, def
.ident
.name
))
1295 // ...and also create the `Self` parameter.
1296 let self_ty
= ty
::mk_self_type(tcx
);
1298 Substs
::new_trait(types
, regions
, self_ty
)
1302 fn trait_defines_associated_type_named(ccx
: &CrateCtxt
,
1303 trait_node_id
: ast
::NodeId
,
1304 assoc_name
: ast
::Name
)
1307 let item
= match ccx
.tcx
.map
.get(trait_node_id
) {
1308 ast_map
::NodeItem(item
) => item
,
1309 _
=> ccx
.tcx
.sess
.bug(&format
!("trait_node_id {} is not an item", trait_node_id
))
1312 let trait_items
= match item
.node
{
1313 ast
::ItemTrait(_
, _
, _
, ref trait_items
) => trait_items
,
1314 _
=> ccx
.tcx
.sess
.bug(&format
!("trait_node_id {} is not a trait", trait_node_id
))
1317 trait_items
.iter().any(|trait_item
| {
1318 match trait_item
.node
{
1319 ast
::TypeTraitItem(..) => trait_item
.ident
.name
== assoc_name
,
1325 fn convert_trait_predicates
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>, it
: &ast
::Item
) {
1327 let trait_def
= trait_def_of_item(ccx
, it
);
1329 let def_id
= local_def(it
.id
);
1331 let (generics
, items
) = match it
.node
{
1332 ast
::ItemTrait(_
, ref generics
, _
, ref items
) => (generics
, items
),
1336 &format
!("trait_def_of_item invoked on {:?}", s
));
1340 let super_predicates
= ty
::lookup_super_predicates(ccx
.tcx
, def_id
);
1342 // `ty_generic_predicates` below will consider the bounds on the type
1343 // parameters (including `Self`) and the explicit where-clauses,
1344 // but to get the full set of predicates on a trait we need to add
1345 // in the supertrait bounds and anything declared on the
1346 // associated types.
1347 let mut base_predicates
= super_predicates
;
1349 // Add in a predicate that `Self:Trait` (where `Trait` is the
1350 // current trait). This is needed for builtin bounds.
1351 let self_predicate
= trait_def
.trait_ref
.to_poly_trait_ref().as_predicate();
1352 base_predicates
.predicates
.push(SelfSpace
, self_predicate
);
1354 // add in the explicit where-clauses
1355 let mut trait_predicates
=
1356 ty_generic_predicates(ccx
, TypeSpace
, generics
, &base_predicates
);
1358 let assoc_predicates
= predicates_for_associated_types(ccx
,
1361 trait_def
.trait_ref
,
1363 trait_predicates
.predicates
.extend(TypeSpace
, assoc_predicates
.into_iter());
1365 let prev_predicates
= tcx
.predicates
.borrow_mut().insert(def_id
, trait_predicates
);
1366 assert
!(prev_predicates
.is_none());
1370 fn predicates_for_associated_types
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
1371 ast_generics
: &ast
::Generics
,
1372 trait_predicates
: &ty
::GenericPredicates
<'tcx
>,
1373 self_trait_ref
: ty
::TraitRef
<'tcx
>,
1374 trait_items
: &[P
<ast
::TraitItem
>])
1375 -> Vec
<ty
::Predicate
<'tcx
>>
1377 trait_items
.iter().flat_map(|trait_item
| {
1378 let bounds
= match trait_item
.node
{
1379 ast
::TypeTraitItem(ref bounds
, _
) => bounds
,
1381 return vec
!().into_iter();
1385 let assoc_ty
= ty
::mk_projection(ccx
.tcx
,
1387 trait_item
.ident
.name
);
1389 let bounds
= compute_bounds(&ccx
.icx(&(ast_generics
, trait_predicates
)),
1392 SizedByDefault
::Yes
,
1395 ty
::predicates(ccx
.tcx
, assoc_ty
, &bounds
).into_iter()
1400 fn type_scheme_of_def_id
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1402 -> ty
::TypeScheme
<'tcx
>
1404 if def_id
.krate
!= ast
::LOCAL_CRATE
{
1405 return ty
::lookup_item_type(ccx
.tcx
, def_id
);
1408 match ccx
.tcx
.map
.find(def_id
.node
) {
1409 Some(ast_map
::NodeItem(item
)) => {
1410 type_scheme_of_item(ccx
, &*item
)
1412 Some(ast_map
::NodeForeignItem(foreign_item
)) => {
1413 let abi
= ccx
.tcx
.map
.get_foreign_abi(def_id
.node
);
1414 type_scheme_of_foreign_item(ccx
, &*foreign_item
, abi
)
1417 ccx
.tcx
.sess
.bug(&format
!("unexpected sort of node \
1418 in get_item_type_scheme(): {:?}",
1424 fn type_scheme_of_item
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1426 -> ty
::TypeScheme
<'tcx
>
1428 memoized(&ccx
.tcx
.tcache
,
1430 |_
| compute_type_scheme_of_item(ccx
, it
))
1433 fn compute_type_scheme_of_item
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1435 -> ty
::TypeScheme
<'tcx
>
1439 ast
::ItemStatic(ref t
, _
, _
) | ast
::ItemConst(ref t
, _
) => {
1440 let ty
= ccx
.icx(&()).to_ty(&ExplicitRscope
, &**t
);
1441 ty
::TypeScheme { ty: ty, generics: ty::Generics::empty() }
1443 ast
::ItemFn(ref decl
, unsafety
, abi
, ref generics
, _
) => {
1444 let ty_generics
= ty_generics_for_fn(ccx
, generics
, &ty
::Generics
::empty());
1445 let tofd
= astconv
::ty_of_bare_fn(&ccx
.icx(generics
), unsafety
, abi
, &**decl
);
1446 let ty
= ty
::mk_bare_fn(tcx
, Some(local_def(it
.id
)), tcx
.mk_bare_fn(tofd
));
1447 ty
::TypeScheme { ty: ty, generics: ty_generics }
1449 ast
::ItemTy(ref t
, ref generics
) => {
1450 let ty_generics
= ty_generics_for_type_or_impl(ccx
, generics
);
1451 let ty
= ccx
.icx(generics
).to_ty(&ExplicitRscope
, &**t
);
1452 ty
::TypeScheme { ty: ty, generics: ty_generics }
1454 ast
::ItemEnum(_
, ref generics
) => {
1455 // Create a new generic polytype.
1456 let ty_generics
= ty_generics_for_type_or_impl(ccx
, generics
);
1457 let substs
= mk_item_substs(ccx
, &ty_generics
);
1458 let t
= ty
::mk_enum(tcx
, local_def(it
.id
), tcx
.mk_substs(substs
));
1459 ty
::TypeScheme { ty: t, generics: ty_generics }
1461 ast
::ItemStruct(_
, ref generics
) => {
1462 let ty_generics
= ty_generics_for_type_or_impl(ccx
, generics
);
1463 let substs
= mk_item_substs(ccx
, &ty_generics
);
1464 let t
= ty
::mk_struct(tcx
, local_def(it
.id
), tcx
.mk_substs(substs
));
1465 ty
::TypeScheme { ty: t, generics: ty_generics }
1467 ast
::ItemDefaultImpl(..) |
1468 ast
::ItemTrait(..) |
1471 ast
::ItemForeignMod(..) |
1472 ast
::ItemExternCrate(..) |
1474 ast
::ItemMac(..) => {
1477 &format
!("compute_type_scheme_of_item: unexpected item type: {:?}",
1483 fn convert_typed_item
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
1485 -> (ty
::TypeScheme
<'tcx
>, ty
::GenericPredicates
<'tcx
>)
1489 let tag
= type_scheme_of_item(ccx
, it
);
1490 let scheme
= TypeScheme { generics: tag.generics, ty: tag.ty }
;
1491 let predicates
= match it
.node
{
1492 ast
::ItemStatic(..) | ast
::ItemConst(..) => {
1493 ty
::GenericPredicates
::empty()
1495 ast
::ItemFn(_
, _
, _
, ref ast_generics
, _
) => {
1496 ty_generic_predicates_for_fn(ccx
, ast_generics
, &ty
::GenericPredicates
::empty())
1498 ast
::ItemTy(_
, ref generics
) => {
1499 ty_generic_predicates_for_type_or_impl(ccx
, generics
)
1501 ast
::ItemEnum(_
, ref generics
) => {
1502 ty_generic_predicates_for_type_or_impl(ccx
, generics
)
1504 ast
::ItemStruct(_
, ref generics
) => {
1505 ty_generic_predicates_for_type_or_impl(ccx
, generics
)
1507 ast
::ItemDefaultImpl(..) |
1508 ast
::ItemTrait(..) |
1509 ast
::ItemExternCrate(..) |
1513 ast
::ItemForeignMod(..) |
1514 ast
::ItemMac(..) => {
1517 &format
!("compute_type_scheme_of_item: unexpected item type: {:?}",
1522 let prev_predicates
= tcx
.predicates
.borrow_mut().insert(local_def(it
.id
),
1523 predicates
.clone());
1524 assert
!(prev_predicates
.is_none());
1527 if ty
::has_attr(tcx
, local_def(it
.id
), "rustc_object_lifetime_default") {
1528 let object_lifetime_default_reprs
: String
=
1529 scheme
.generics
.types
.iter()
1530 .map(|t
| match t
.object_lifetime_default
{
1531 Some(ty
::ObjectLifetimeDefault
::Specific(r
)) =>
1536 .collect
::<Vec
<String
>>()
1539 tcx
.sess
.span_err(it
.span
, &object_lifetime_default_reprs
);
1542 return (scheme
, predicates
);
1545 fn type_scheme_of_foreign_item
<'a
, 'tcx
>(
1546 ccx
: &CrateCtxt
<'a
, 'tcx
>,
1547 it
: &ast
::ForeignItem
,
1549 -> ty
::TypeScheme
<'tcx
>
1551 memoized(&ccx
.tcx
.tcache
,
1553 |_
| compute_type_scheme_of_foreign_item(ccx
, it
, abi
))
1556 fn compute_type_scheme_of_foreign_item
<'a
, 'tcx
>(
1557 ccx
: &CrateCtxt
<'a
, 'tcx
>,
1558 it
: &ast
::ForeignItem
,
1560 -> ty
::TypeScheme
<'tcx
>
1563 ast
::ForeignItemFn(ref fn_decl
, ref generics
) => {
1564 compute_type_scheme_of_foreign_fn_decl(ccx
, fn_decl
, generics
, abi
)
1566 ast
::ForeignItemStatic(ref t
, _
) => {
1568 generics
: ty
::Generics
::empty(),
1569 ty
: ast_ty_to_ty(&ccx
.icx(&()), &ExplicitRscope
, t
)
1575 fn convert_foreign_item
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
1576 it
: &ast
::ForeignItem
)
1578 // For reasons I cannot fully articulate, I do so hate the AST
1579 // map, and I regard each time that I use it as a personal and
1580 // moral failing, but at the moment it seems like the only
1581 // convenient way to extract the ABI. - ndm
1583 let abi
= tcx
.map
.get_foreign_abi(it
.id
);
1585 let scheme
= type_scheme_of_foreign_item(ccx
, it
, abi
);
1586 write_ty_to_tcx(ccx
.tcx
, it
.id
, scheme
.ty
);
1588 let predicates
= match it
.node
{
1589 ast
::ForeignItemFn(_
, ref generics
) => {
1590 ty_generic_predicates_for_fn(ccx
, generics
, &ty
::GenericPredicates
::empty())
1592 ast
::ForeignItemStatic(..) => {
1593 ty
::GenericPredicates
::empty()
1597 let prev_predicates
= tcx
.predicates
.borrow_mut().insert(local_def(it
.id
), predicates
);
1598 assert
!(prev_predicates
.is_none());
1601 fn ty_generics_for_type_or_impl
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
1602 generics
: &ast
::Generics
)
1603 -> ty
::Generics
<'tcx
> {
1604 ty_generics(ccx
, TypeSpace
, generics
, &ty
::Generics
::empty())
1607 fn ty_generic_predicates_for_type_or_impl
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1608 generics
: &ast
::Generics
)
1609 -> ty
::GenericPredicates
<'tcx
>
1611 ty_generic_predicates(ccx
, TypeSpace
, generics
, &ty
::GenericPredicates
::empty())
1614 fn ty_generics_for_trait
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
1615 trait_id
: ast
::NodeId
,
1616 substs
: &'tcx Substs
<'tcx
>,
1617 ast_generics
: &ast
::Generics
)
1618 -> ty
::Generics
<'tcx
>
1620 debug
!("ty_generics_for_trait(trait_id={}, substs={})",
1621 local_def(trait_id
).repr(ccx
.tcx
), substs
.repr(ccx
.tcx
));
1623 let mut generics
= ty_generics_for_type_or_impl(ccx
, ast_generics
);
1625 // Add in the self type parameter.
1627 // Something of a hack: use the node id for the trait, also as
1628 // the node id for the Self type parameter.
1629 let param_id
= trait_id
;
1631 let def
= ty
::TypeParameterDef
{
1634 name
: special_idents
::type_self
.name
,
1635 def_id
: local_def(param_id
),
1637 object_lifetime_default
: None
,
1640 ccx
.tcx
.ty_param_defs
.borrow_mut().insert(param_id
, def
.clone());
1642 generics
.types
.push(SelfSpace
, def
);
1647 fn ty_generics_for_fn
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1648 generics
: &ast
::Generics
,
1649 base_generics
: &ty
::Generics
<'tcx
>)
1650 -> ty
::Generics
<'tcx
>
1652 ty_generics(ccx
, FnSpace
, generics
, base_generics
)
1655 fn ty_generic_predicates_for_fn
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1656 generics
: &ast
::Generics
,
1657 base_predicates
: &ty
::GenericPredicates
<'tcx
>)
1658 -> ty
::GenericPredicates
<'tcx
>
1660 ty_generic_predicates(ccx
, FnSpace
, generics
, base_predicates
)
1663 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1664 fn add_unsized_bound
<'tcx
>(astconv
: &AstConv
<'tcx
>,
1665 bounds
: &mut ty
::BuiltinBounds
,
1666 ast_bounds
: &[ast
::TyParamBound
],
1669 let tcx
= astconv
.tcx();
1671 // Try to find an unbound in bounds.
1672 let mut unbound
= None
;
1673 for ab
in ast_bounds
{
1674 if let &ast
::TraitTyParamBound(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = ab
{
1675 if unbound
.is_none() {
1676 assert
!(ptr
.bound_lifetimes
.is_empty());
1677 unbound
= Some(ptr
.trait_ref
.clone());
1679 span_err
!(tcx
.sess
, span
, E0203
,
1680 "type parameter has more than one relaxed default \
1681 bound, only one is supported");
1686 let kind_id
= tcx
.lang_items
.require(SizedTraitLangItem
);
1689 // FIXME(#8559) currently requires the unbound to be built-in.
1690 let trait_def_id
= ty
::trait_ref_to_def_id(tcx
, tpb
);
1692 Ok(kind_id
) if trait_def_id
!= kind_id
=> {
1693 tcx
.sess
.span_warn(span
,
1694 "default bound relaxed for a type parameter, but \
1695 this does nothing because the given bound is not \
1696 a default. Only `?Sized` is supported");
1697 ty
::try_add_builtin_trait(tcx
, kind_id
, bounds
);
1702 _
if kind_id
.is_ok() => {
1703 ty
::try_add_builtin_trait(tcx
, kind_id
.unwrap(), bounds
);
1705 // No lang item for Sized, so we can't add it as a bound.
1710 /// Returns the early-bound lifetimes declared in this generics
1711 /// listing. For anything other than fns/methods, this is just all
1712 /// the lifetimes that are declared. For fns or methods, we have to
1713 /// screen out those that do not appear in any where-clauses etc using
1714 /// `resolve_lifetime::early_bound_lifetimes`.
1715 fn early_bound_lifetimes_from_generics(space
: ParamSpace
,
1716 ast_generics
: &ast
::Generics
)
1717 -> Vec
<ast
::LifetimeDef
>
1720 SelfSpace
| TypeSpace
=> ast_generics
.lifetimes
.to_vec(),
1721 FnSpace
=> resolve_lifetime
::early_bound_lifetimes(ast_generics
),
1725 fn ty_generic_predicates
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1727 ast_generics
: &ast
::Generics
,
1728 base_predicates
: &ty
::GenericPredicates
<'tcx
>)
1729 -> ty
::GenericPredicates
<'tcx
>
1732 let mut result
= base_predicates
.clone();
1734 // Collect the predicates that were written inline by the user on each
1735 // type parameter (e.g., `<T:Foo>`).
1736 for (index
, param
) in ast_generics
.ty_params
.iter().enumerate() {
1737 let index
= index
as u32;
1738 let param_ty
= ty
::ParamTy
::new(space
, index
, param
.ident
.name
).to_ty(ccx
.tcx
);
1739 let bounds
= compute_bounds(&ccx
.icx(&(base_predicates
, ast_generics
)),
1742 SizedByDefault
::Yes
,
1744 let predicates
= ty
::predicates(ccx
.tcx
, param_ty
, &bounds
);
1745 result
.predicates
.extend(space
, predicates
.into_iter());
1748 // Collect the region predicates that were declared inline as
1749 // well. In the case of parameters declared on a fn or method, we
1750 // have to be careful to only iterate over early-bound regions.
1751 let early_lifetimes
= early_bound_lifetimes_from_generics(space
, ast_generics
);
1752 for (index
, param
) in early_lifetimes
.iter().enumerate() {
1753 let index
= index
as u32;
1755 ty
::ReEarlyBound(ty
::EarlyBoundRegion
{
1756 param_id
: param
.lifetime
.id
,
1759 name
: param
.lifetime
.name
1761 for bound
in ¶m
.bounds
{
1762 let bound_region
= ast_region_to_region(ccx
.tcx
, bound
);
1763 let outlives
= ty
::Binder(ty
::OutlivesPredicate(region
, bound_region
));
1764 result
.predicates
.push(space
, outlives
.as_predicate());
1768 // Add in the bounds that appear in the where-clause
1769 let where_clause
= &ast_generics
.where_clause
;
1770 for predicate
in &where_clause
.predicates
{
1772 &ast
::WherePredicate
::BoundPredicate(ref bound_pred
) => {
1773 let ty
= ast_ty_to_ty(&ccx
.icx(&(base_predicates
, ast_generics
)),
1775 &*bound_pred
.bounded_ty
);
1777 for bound
in &*bound_pred
.bounds
{
1779 &ast
::TyParamBound
::TraitTyParamBound(ref poly_trait_ref
, _
) => {
1780 let mut projections
= Vec
::new();
1783 conv_poly_trait_ref(&ccx
.icx(&(base_predicates
, ast_generics
)),
1788 result
.predicates
.push(space
, trait_ref
.as_predicate());
1790 for projection
in &projections
{
1791 result
.predicates
.push(space
, projection
.as_predicate());
1795 &ast
::TyParamBound
::RegionTyParamBound(ref lifetime
) => {
1796 let region
= ast_region_to_region(tcx
, lifetime
);
1797 let pred
= ty
::Binder(ty
::OutlivesPredicate(ty
, region
));
1798 result
.predicates
.push(space
, ty
::Predicate
::TypeOutlives(pred
))
1804 &ast
::WherePredicate
::RegionPredicate(ref region_pred
) => {
1805 let r1
= ast_region_to_region(tcx
, ®ion_pred
.lifetime
);
1806 for bound
in ®ion_pred
.bounds
{
1807 let r2
= ast_region_to_region(tcx
, bound
);
1808 let pred
= ty
::Binder(ty
::OutlivesPredicate(r1
, r2
));
1809 result
.predicates
.push(space
, ty
::Predicate
::RegionOutlives(pred
))
1813 &ast
::WherePredicate
::EqPredicate(ref eq_pred
) => {
1815 tcx
.sess
.span_bug(eq_pred
.span
,
1816 "Equality constraints are not yet \
1817 implemented (#20041)")
1825 fn ty_generics
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1827 ast_generics
: &ast
::Generics
,
1828 base_generics
: &ty
::Generics
<'tcx
>)
1829 -> ty
::Generics
<'tcx
>
1832 let mut result
= base_generics
.clone();
1834 let early_lifetimes
= early_bound_lifetimes_from_generics(space
, ast_generics
);
1835 for (i
, l
) in early_lifetimes
.iter().enumerate() {
1836 let bounds
= l
.bounds
.iter()
1837 .map(|l
| ast_region_to_region(tcx
, l
))
1839 let def
= ty
::RegionParameterDef
{ name
: l
.lifetime
.name
,
1842 def_id
: local_def(l
.lifetime
.id
),
1844 result
.regions
.push(space
, def
);
1847 assert
!(result
.types
.is_empty_in(space
));
1849 // Now create the real type parameters.
1850 for i
in 0..ast_generics
.ty_params
.len() {
1851 let def
= get_or_create_type_parameter_def(ccx
, ast_generics
, space
, i
as u32);
1852 debug
!("ty_generics: def for type param: {:?}, {:?}", def
, space
);
1853 result
.types
.push(space
, def
);
1859 fn get_or_create_type_parameter_def
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1860 ast_generics
: &ast
::Generics
,
1863 -> ty
::TypeParameterDef
<'tcx
>
1865 let param
= &ast_generics
.ty_params
[index
as usize];
1868 match tcx
.ty_param_defs
.borrow().get(¶m
.id
) {
1869 Some(d
) => { return d.clone(); }
1873 let default = match param
.default {
1876 let ty
= ast_ty_to_ty(&ccx
.icx(&()), &ExplicitRscope
, &**path
);
1877 let cur_idx
= index
;
1879 ty
::walk_ty(ty
, |t
| {
1881 ty
::ty_param(p
) => if p
.idx
> cur_idx
{
1882 span_err
!(tcx
.sess
, path
.span
, E0128
,
1883 "type parameters with a default cannot use \
1884 forward declared identifiers");
1894 let object_lifetime_default
=
1895 compute_object_lifetime_default(ccx
, param
.id
,
1896 ¶m
.bounds
, &ast_generics
.where_clause
);
1898 let def
= ty
::TypeParameterDef
{
1901 name
: param
.ident
.name
,
1902 def_id
: local_def(param
.id
),
1904 object_lifetime_default
: object_lifetime_default
,
1907 tcx
.ty_param_defs
.borrow_mut().insert(param
.id
, def
.clone());
1912 /// Scan the bounds and where-clauses on a parameter to extract bounds
1913 /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
1914 /// This runs as part of computing the minimal type scheme, so we
1915 /// intentionally avoid just asking astconv to convert all the where
1916 /// clauses into a `ty::Predicate`. This is because that could induce
1917 /// artificial cycles.
1918 fn compute_object_lifetime_default
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1919 param_id
: ast
::NodeId
,
1920 param_bounds
: &[ast
::TyParamBound
],
1921 where_clause
: &ast
::WhereClause
)
1922 -> Option
<ty
::ObjectLifetimeDefault
>
1924 let inline_bounds
= from_bounds(ccx
, param_bounds
);
1925 let where_bounds
= from_predicates(ccx
, param_id
, &where_clause
.predicates
);
1926 let all_bounds
: HashSet
<_
> = inline_bounds
.into_iter()
1927 .chain(where_bounds
.into_iter())
1929 return if all_bounds
.len() > 1 {
1930 Some(ty
::ObjectLifetimeDefault
::Ambiguous
)
1932 all_bounds
.into_iter()
1934 .map(ty
::ObjectLifetimeDefault
::Specific
)
1937 fn from_bounds
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1938 bounds
: &[ast
::TyParamBound
])
1942 .filter_map(|bound
| {
1944 ast
::TraitTyParamBound(..) =>
1946 ast
::RegionTyParamBound(ref lifetime
) =>
1947 Some(astconv
::ast_region_to_region(ccx
.tcx
, lifetime
)),
1953 fn from_predicates
<'a
,'tcx
>(ccx
: &CrateCtxt
<'a
,'tcx
>,
1954 param_id
: ast
::NodeId
,
1955 predicates
: &[ast
::WherePredicate
])
1959 .flat_map(|predicate
| {
1961 ast
::WherePredicate
::BoundPredicate(ref data
) => {
1962 if data
.bound_lifetimes
.is_empty() &&
1963 is_param(ccx
.tcx
, &data
.bounded_ty
, param_id
)
1965 from_bounds(ccx
, &data
.bounds
).into_iter()
1967 Vec
::new().into_iter()
1970 ast
::WherePredicate
::RegionPredicate(..) |
1971 ast
::WherePredicate
::EqPredicate(..) => {
1972 Vec
::new().into_iter()
1980 enum SizedByDefault { Yes, No, }
1982 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1983 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1984 /// built-in trait (formerly known as kind): Send.
1985 fn compute_bounds
<'tcx
>(astconv
: &AstConv
<'tcx
>,
1986 param_ty
: ty
::Ty
<'tcx
>,
1987 ast_bounds
: &[ast
::TyParamBound
],
1988 sized_by_default
: SizedByDefault
,
1990 -> ty
::ParamBounds
<'tcx
>
1992 let mut param_bounds
= conv_param_bounds(astconv
,
1997 if let SizedByDefault
::Yes
= sized_by_default
{
1998 add_unsized_bound(astconv
,
1999 &mut param_bounds
.builtin_bounds
,
2004 param_bounds
.trait_bounds
.sort_by(|a
,b
| a
.def_id().cmp(&b
.def_id()));
2009 /// Converts a specific TyParamBound from the AST into a set of
2010 /// predicates that apply to the self-type. A vector is returned
2011 /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
2012 /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
2013 /// and `<T as Bar>::X == i32`).
2014 fn predicates_from_bound
<'tcx
>(astconv
: &AstConv
<'tcx
>,
2016 bound
: &ast
::TyParamBound
)
2017 -> Vec
<ty
::Predicate
<'tcx
>>
2020 ast
::TraitTyParamBound(ref tr
, ast
::TraitBoundModifier
::None
) => {
2021 let mut projections
= Vec
::new();
2022 let pred
= conv_poly_trait_ref(astconv
, param_ty
, tr
, &mut projections
);
2023 projections
.into_iter()
2024 .map(|p
| p
.as_predicate())
2025 .chain(Some(pred
.as_predicate()).into_iter())
2028 ast
::RegionTyParamBound(ref lifetime
) => {
2029 let region
= ast_region_to_region(astconv
.tcx(), lifetime
);
2030 let pred
= ty
::Binder(ty
::OutlivesPredicate(param_ty
, region
));
2031 vec
![ty
::Predicate
::TypeOutlives(pred
)]
2033 ast
::TraitTyParamBound(_
, ast
::TraitBoundModifier
::Maybe
) => {
2039 fn conv_poly_trait_ref
<'tcx
>(astconv
: &AstConv
<'tcx
>,
2041 trait_ref
: &ast
::PolyTraitRef
,
2042 projections
: &mut Vec
<ty
::PolyProjectionPredicate
<'tcx
>>)
2043 -> ty
::PolyTraitRef
<'tcx
>
2045 astconv
::instantiate_poly_trait_ref(astconv
,
2052 fn conv_param_bounds
<'a
,'tcx
>(astconv
: &AstConv
<'tcx
>,
2054 param_ty
: ty
::Ty
<'tcx
>,
2055 ast_bounds
: &[ast
::TyParamBound
])
2056 -> ty
::ParamBounds
<'tcx
>
2058 let tcx
= astconv
.tcx();
2059 let astconv
::PartitionedBounds
{
2063 } = astconv
::partition_bounds(tcx
, span
, &ast_bounds
);
2065 let mut projection_bounds
= Vec
::new();
2067 let trait_bounds
: Vec
<ty
::PolyTraitRef
> =
2069 .map(|bound
| conv_poly_trait_ref(astconv
,
2072 &mut projection_bounds
))
2075 let region_bounds
: Vec
<ty
::Region
> =
2076 region_bounds
.into_iter()
2077 .map(|r
| ast_region_to_region(tcx
, r
))
2081 region_bounds
: region_bounds
,
2082 builtin_bounds
: builtin_bounds
,
2083 trait_bounds
: trait_bounds
,
2084 projection_bounds
: projection_bounds
,
2088 fn compute_type_scheme_of_foreign_fn_decl
<'a
, 'tcx
>(
2089 ccx
: &CrateCtxt
<'a
, 'tcx
>,
2091 ast_generics
: &ast
::Generics
,
2093 -> ty
::TypeScheme
<'tcx
>
2095 for i
in decl
.inputs
.iter() {
2096 match (*i
).pat
.node
{
2097 ast
::PatIdent(_
, _
, _
) => (),
2098 ast
::PatWild(ast
::PatWildSingle
) => (),
2100 span_err
!(ccx
.tcx
.sess
, (*i
).pat
.span
, E0130
,
2101 "patterns aren't allowed in foreign function declarations");
2106 let ty_generics
= ty_generics_for_fn(ccx
, ast_generics
, &ty
::Generics
::empty());
2108 let rb
= BindingRscope
::new();
2109 let input_tys
= decl
.inputs
2111 .map(|a
| ty_of_arg(&ccx
.icx(ast_generics
), &rb
, a
, None
))
2114 let output
= match decl
.output
{
2115 ast
::Return(ref ty
) =>
2116 ty
::FnConverging(ast_ty_to_ty(&ccx
.icx(ast_generics
), &rb
, &**ty
)),
2117 ast
::DefaultReturn(..) =>
2118 ty
::FnConverging(ty
::mk_nil(ccx
.tcx
)),
2119 ast
::NoReturn(..) =>
2123 let t_fn
= ty
::mk_bare_fn(
2126 ccx
.tcx
.mk_bare_fn(ty
::BareFnTy
{
2128 unsafety
: ast
::Unsafety
::Unsafe
,
2129 sig
: ty
::Binder(ty
::FnSig
{inputs
: input_tys
,
2131 variadic
: decl
.variadic
}),
2135 generics
: ty_generics
,
2140 fn mk_item_substs
<'a
, 'tcx
>(ccx
: &CrateCtxt
<'a
, 'tcx
>,
2141 ty_generics
: &ty
::Generics
<'tcx
>)
2145 ty_generics
.types
.map(
2146 |def
| ty
::mk_param_from_def(ccx
.tcx
, def
));
2149 ty_generics
.regions
.map(
2150 |def
| def
.to_early_bound_region());
2152 Substs
::new(types
, regions
)
2155 /// Verifies that the explicit self type of a method matches the impl
2156 /// or trait. This is a bit weird but basically because right now we
2157 /// don't handle the general case, but instead map it to one of
2158 /// several pre-defined options using various heuristics, this method
2159 /// comes back to check after the fact that explicit type the user
2160 /// wrote actually matches what the pre-defined option said.
2161 fn check_method_self_type
<'a
, 'tcx
, RS
:RegionScope
>(
2162 ccx
: &CrateCtxt
<'a
, 'tcx
>,
2164 method_type
: Rc
<ty
::Method
<'tcx
>>,
2165 required_type
: Ty
<'tcx
>,
2166 explicit_self
: &ast
::ExplicitSelf
,
2167 body_id
: ast
::NodeId
)
2170 if let ast
::SelfExplicit(ref ast_type
, _
) = explicit_self
.node
{
2171 let typ
= ccx
.icx(&method_type
.predicates
).to_ty(rs
, &**ast_type
);
2172 let base_type
= match typ
.sty
{
2173 ty
::ty_ptr(tm
) | ty
::ty_rptr(_
, tm
) => tm
.ty
,
2174 ty
::ty_uniq(typ
) => typ
,
2178 let body_scope
= region
::DestructionScopeData
::new(body_id
);
2180 // "Required type" comes from the trait definition. It may
2181 // contain late-bound regions from the method, but not the
2182 // trait (since traits only have early-bound region
2184 assert
!(!base_type
.has_regions_escaping_depth(1));
2185 let required_type_free
=
2186 liberate_early_bound_regions(
2188 &ty
::liberate_late_bound_regions(
2189 tcx
, body_scope
, &ty
::Binder(required_type
)));
2191 // The "base type" comes from the impl. It too may have late-bound
2192 // regions from the method.
2193 assert
!(!base_type
.has_regions_escaping_depth(1));
2194 let base_type_free
=
2195 liberate_early_bound_regions(
2197 &ty
::liberate_late_bound_regions(
2198 tcx
, body_scope
, &ty
::Binder(base_type
)));
2200 debug
!("required_type={} required_type_free={} \
2201 base_type={} base_type_free={}",
2202 required_type
.repr(tcx
),
2203 required_type_free
.repr(tcx
),
2204 base_type
.repr(tcx
),
2205 base_type_free
.repr(tcx
));
2207 let infcx
= infer
::new_infer_ctxt(tcx
);
2208 drop(::require_same_types(tcx
,
2215 format
!("mismatched self type: expected `{}`",
2216 ppaux
::ty_to_string(tcx
, required_type
))
2219 // We could conceviably add more free-reion relations here,
2220 // but since this code is just concerned with checking that
2221 // the `&Self` types etc match up, it's not really necessary.
2222 // It would just allow people to be more approximate in some
2223 // cases. In any case, we can do it later as we feel the need;
2224 // I'd like this function to go away eventually.
2225 let free_regions
= FreeRegionMap
::new();
2227 infcx
.resolve_regions_and_report_errors(&free_regions
, body_id
);
2230 fn liberate_early_bound_regions
<'tcx
,T
>(
2231 tcx
: &ty
::ctxt
<'tcx
>,
2232 scope
: region
::DestructionScopeData
,
2235 where T
: TypeFoldable
<'tcx
> + Repr
<'tcx
>
2238 * Convert early-bound regions into free regions; normally this is done by
2239 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
2240 * method-self-type check is kind of hacky and done very early in the process,
2241 * before we really have a `ParameterEnvironment` to check.
2244 ty_fold
::fold_regions(tcx
, value
, |region
, _
| {
2246 ty
::ReEarlyBound(data
) => {
2247 let def_id
= local_def(data
.param_id
);
2248 ty
::ReFree(ty
::FreeRegion
{ scope
: scope
,
2249 bound_region
: ty
::BrNamed(def_id
, data
.name
) })
2257 /// Checks that all the type parameters on an impl
2258 fn enforce_impl_params_are_constrained
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>,
2259 ast_generics
: &ast
::Generics
,
2260 impl_def_id
: ast
::DefId
,
2261 impl_items
: &[P
<ast
::ImplItem
>])
2263 let impl_scheme
= ty
::lookup_item_type(tcx
, impl_def_id
);
2264 let impl_predicates
= ty
::lookup_predicates(tcx
, impl_def_id
);
2265 let impl_trait_ref
= ty
::impl_trait_ref(tcx
, impl_def_id
);
2267 // The trait reference is an input, so find all type parameters
2268 // reachable from there, to start (if this is an inherent impl,
2269 // then just examine the self type).
2270 let mut input_parameters
: HashSet
<_
> =
2271 ctp
::parameters_for_type(impl_scheme
.ty
).into_iter().collect();
2272 if let Some(ref trait_ref
) = impl_trait_ref
{
2273 input_parameters
.extend(ctp
::parameters_for_trait_ref(trait_ref
));
2276 ctp
::identify_constrained_type_params(tcx
,
2277 impl_predicates
.predicates
.as_slice(),
2279 &mut input_parameters
);
2281 for (index
, ty_param
) in ast_generics
.ty_params
.iter().enumerate() {
2282 let param_ty
= ty
::ParamTy
{ space
: TypeSpace
,
2284 name
: ty_param
.ident
.name
};
2285 if !input_parameters
.contains(&ctp
::Parameter
::Type(param_ty
)) {
2286 report_unused_parameter(tcx
, ty_param
.span
, "type", ¶m_ty
.user_string(tcx
));
2290 // Every lifetime used in an associated type must be constrained.
2292 let lifetimes_in_associated_types
: HashSet
<_
> =
2294 .filter_map(|item
| match item
.node
{
2295 ast
::TypeImplItem(..) => Some(ty
::node_id_to_type(tcx
, item
.id
)),
2296 ast
::ConstImplItem(..) | ast
::MethodImplItem(..) |
2297 ast
::MacImplItem(..) => None
,
2299 .flat_map(|ty
| ctp
::parameters_for_type(ty
).into_iter())
2300 .filter_map(|p
| match p
{
2301 ctp
::Parameter
::Type(_
) => None
,
2302 ctp
::Parameter
::Region(r
) => Some(r
),
2306 for (index
, lifetime_def
) in ast_generics
.lifetimes
.iter().enumerate() {
2307 let region
= ty
::EarlyBoundRegion
{ param_id
: lifetime_def
.lifetime
.id
,
2309 index
: index
as u32,
2310 name
: lifetime_def
.lifetime
.name
};
2312 lifetimes_in_associated_types
.contains(®ion
) && // (*)
2313 !input_parameters
.contains(&ctp
::Parameter
::Region(region
))
2315 report_unused_parameter(tcx
, lifetime_def
.lifetime
.span
,
2316 "lifetime", ®ion
.name
.user_string(tcx
));
2320 // (*) This is a horrible concession to reality. I think it'd be
2321 // better to just ban unconstrianed lifetimes outright, but in
2322 // practice people do non-hygenic macros like:
2325 // macro_rules! __impl_slice_eq1 {
2326 // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
2327 // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
2334 // In a concession to backwards compatbility, we continue to
2335 // permit those, so long as the lifetimes aren't used in
2336 // associated types. I believe this is sound, because lifetimes
2337 // used elsewhere are not projected back out.
2340 fn report_unused_parameter(tcx
: &ty
::ctxt
,
2345 span_err
!(tcx
.sess
, span
, E0207
,
2346 "the {} parameter `{}` is not constrained by the \
2347 impl trait, self type, or predicates",