]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/collect.rs
Imported Upstream version 1.1.0+dfsg1
[rustc.git] / src / librustc_typeck / collect.rs
CommitLineData
1a4d82fc
JJ
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.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11/*
12
13# Collect phase
14
15The collect phase of type check has the job of visiting all items,
16determining their type, and writing that type into the `tcx.tcache`
17table. Despite its name, this table does not really operate as a
18*cache*, at least not for the types of items defined within the
19current crate: we assume that after the collect phase, the types of
20all local items will be present in the table.
21
22Unlike most of the types that are present in Rust, the types computed
85aaf69f
SL
23for each item are in fact type schemes. This means that they are
24generic types that may have type parameters. TypeSchemes are
25represented by an instance of `ty::TypeScheme`. This combines the
26core type along with a list of the bounds for each parameter. Type
27parameters themselves are represented as `ty_param()` instances.
28
c34b1796
AL
29The phasing of type conversion is somewhat complicated. There is no
30clear set of phases we can enforce (e.g., converting traits first,
31then types, or something like that) because the user can introduce
32arbitrary interdependencies. So instead we generally convert things
33lazilly and on demand, and include logic that checks for cycles.
34Demand is driven by calls to `AstConv::get_item_type_scheme` or
35`AstConv::lookup_trait_def`.
36
37Currently, we "convert" types and traits in three phases (note that
38conversion only affects the types of items / enum variants / methods;
39it does not e.g. compute the types of individual expressions):
85aaf69f
SL
40
410. Intrinsics
421. Trait definitions
432. Type definitions
44
45Conversion itself is done by simply walking each of the items in turn
46and invoking an appropriate function (e.g., `trait_def_of_item` or
47`convert_item`). However, it is possible that while converting an
48item, we may need to compute the *type scheme* or *trait definition*
c34b1796 49for other items.
85aaf69f
SL
50
51There are some shortcomings in this design:
52
c34b1796
AL
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.
85aaf69f
SL
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
1a4d82fc
JJ
64
65*/
85aaf69f 66
1a4d82fc 67use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
85aaf69f 68use middle::def;
9346a6ac 69use constrained_type_params as ctp;
1a4d82fc 70use middle::lang_items::SizedTraitLangItem;
bd371182 71use middle::free_region::FreeRegionMap;
1a4d82fc
JJ
72use middle::region;
73use middle::resolve_lifetime;
c34b1796 74use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
1a4d82fc 75use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
c34b1796 76use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
1a4d82fc
JJ
77use middle::ty_fold::{self, TypeFolder, TypeFoldable};
78use middle::infer;
1a4d82fc 79use rscope::*;
c34b1796 80use util::common::{ErrorReported, memoized};
1a4d82fc
JJ
81use util::nodemap::{FnvHashMap, FnvHashSet};
82use util::ppaux;
83use util::ppaux::{Repr,UserString};
84use write_ty_to_tcx;
85
d9579d0f 86use std::cell::{Cell, RefCell};
1a4d82fc
JJ
87use std::collections::HashSet;
88use std::rc::Rc;
89
90use syntax::abi;
91use syntax::ast;
92use syntax::ast_map;
c34b1796 93use syntax::ast_util::local_def;
1a4d82fc 94use syntax::codemap::Span;
c34b1796 95use syntax::parse::token::special_idents;
1a4d82fc
JJ
96use syntax::parse::token;
97use syntax::ptr::P;
98use syntax::visit;
99
100///////////////////////////////////////////////////////////////////////////
101// Main entry point
102
103pub fn collect_item_types(tcx: &ty::ctxt) {
c34b1796 104 let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
1a4d82fc
JJ
105
106 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
107 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
108
109 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
110 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
111}
112
113///////////////////////////////////////////////////////////////////////////
114
c34b1796 115struct CrateCtxt<'a,'tcx:'a> {
1a4d82fc 116 tcx: &'a ty::ctxt<'tcx>,
c34b1796
AL
117
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>>,
1a4d82fc
JJ
121}
122
c34b1796
AL
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).
134struct ItemCtxt<'a,'tcx:'a> {
135 ccx: &'a CrateCtxt<'a,'tcx>,
136 param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
137}
1a4d82fc 138
c34b1796
AL
139#[derive(Copy, Clone, PartialEq, Eq)]
140enum AstConvRequest {
141 GetItemTypeScheme(ast::DefId),
142 GetTraitDef(ast::DefId),
143 EnsureSuperPredicates(ast::DefId),
144 GetTypeParameterBounds(ast::NodeId),
1a4d82fc
JJ
145}
146
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.
151
152struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
c34b1796 153 ccx: &'a CrateCtxt<'a, 'tcx>
1a4d82fc
JJ
154}
155
156impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
157 fn visit_item(&mut self, i: &ast::Item) {
158 match i.node {
159 ast::ItemTrait(..) => {
160 // computing the trait def also fills in the table
161 let _ = trait_def_of_item(self.ccx, i);
162 }
163 _ => { }
164 }
165
166 visit::walk_item(self, i);
167 }
168}
169
170///////////////////////////////////////////////////////////////////////////
171// Second phase: collection proper.
172
173struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
c34b1796 174 ccx: &'a CrateCtxt<'a, 'tcx>
1a4d82fc
JJ
175}
176
177impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
178 fn visit_item(&mut self, i: &ast::Item) {
85aaf69f 179 convert_item(self.ccx, i);
1a4d82fc
JJ
180 visit::walk_item(self, i);
181 }
182 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
85aaf69f 183 convert_foreign_item(self.ccx, i);
1a4d82fc
JJ
184 visit::walk_foreign_item(self, i);
185 }
186}
187
188///////////////////////////////////////////////////////////////////////////
189// Utility types and common code for the above passes.
190
c34b1796
AL
191impl<'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 }
194 }
1a4d82fc 195
c34b1796
AL
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(),
d9579d0f 200 _ => {
c34b1796
AL
201 self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
202 }
203 }
1a4d82fc 204 }
1a4d82fc 205
c34b1796
AL
206 fn cycle_check<F,R>(&self,
207 span: Span,
208 request: AstConvRequest,
209 code: F)
210 -> Result<R,ErrorReported>
211 where F: FnOnce() -> Result<R,ErrorReported>
212 {
213 {
214 let mut stack = self.stack.borrow_mut();
215 match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) {
216 None => { }
217 Some((i, _)) => {
218 let cycle = &stack[i..];
219 self.report_cycle(span, cycle);
220 return Err(ErrorReported);
221 }
222 }
223 stack.push(request);
224 }
1a4d82fc 225
c34b1796
AL
226 let result = code();
227
228 self.stack.borrow_mut().pop();
229 result
230 }
231
232 fn report_cycle(&self,
233 span: Span,
234 cycle: &[AstConvRequest])
235 {
236 assert!(!cycle.is_empty());
237 let tcx = self.tcx;
238
239 tcx.sess.span_err(
240 span,
241 &format!("unsupported cyclic reference between types/traits detected"));
242
243 match cycle[0] {
244 AstConvRequest::GetItemTypeScheme(def_id) |
245 AstConvRequest::GetTraitDef(def_id) => {
246 tcx.sess.note(
247 &format!("the cycle begins when processing `{}`...",
248 ty::item_path_str(tcx, def_id)));
249 }
250 AstConvRequest::EnsureSuperPredicates(def_id) => {
251 tcx.sess.note(
252 &format!("the cycle begins when computing the supertraits of `{}`...",
253 ty::item_path_str(tcx, def_id)));
254 }
255 AstConvRequest::GetTypeParameterBounds(id) => {
256 let def = tcx.type_parameter_def(id);
257 tcx.sess.note(
258 &format!("the cycle begins when computing the bounds \
259 for type parameter `{}`...",
260 def.name.user_string(tcx)));
261 }
262 }
263
264 for request in cycle[1..].iter() {
265 match *request {
266 AstConvRequest::GetItemTypeScheme(def_id) |
267 AstConvRequest::GetTraitDef(def_id) => {
268 tcx.sess.note(
269 &format!("...which then requires processing `{}`...",
270 ty::item_path_str(tcx, def_id)));
271 }
272 AstConvRequest::EnsureSuperPredicates(def_id) => {
273 tcx.sess.note(
274 &format!("...which then requires computing the supertraits of `{}`...",
275 ty::item_path_str(tcx, def_id)));
276 }
277 AstConvRequest::GetTypeParameterBounds(id) => {
278 let def = tcx.type_parameter_def(id);
279 tcx.sess.note(
280 &format!("...which then requires computing the bounds \
281 for type parameter `{}`...",
282 def.name.user_string(tcx)));
283 }
284 }
1a4d82fc
JJ
285 }
286
c34b1796
AL
287 match cycle[0] {
288 AstConvRequest::GetItemTypeScheme(def_id) |
289 AstConvRequest::GetTraitDef(def_id) => {
290 tcx.sess.note(
291 &format!("...which then again requires processing `{}`, completing the cycle.",
292 ty::item_path_str(tcx, def_id)));
1a4d82fc 293 }
c34b1796
AL
294 AstConvRequest::EnsureSuperPredicates(def_id) => {
295 tcx.sess.note(
296 &format!("...which then again requires computing the supertraits of `{}`, \
297 completing the cycle.",
298 ty::item_path_str(tcx, def_id)));
1a4d82fc 299 }
c34b1796
AL
300 AstConvRequest::GetTypeParameterBounds(id) => {
301 let def = tcx.type_parameter_def(id);
302 tcx.sess.note(
303 &format!("...which then again requires computing the bounds \
304 for type parameter `{}`, completing the cycle.",
305 def.name.user_string(tcx)));
1a4d82fc
JJ
306 }
307 }
308 }
309
c34b1796
AL
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)
d9579d0f 312 -> &'tcx ty::TraitDef<'tcx>
c34b1796
AL
313 {
314 let tcx = self.tcx;
315
316 if trait_id.krate != ast::LOCAL_CRATE {
317 return ty::lookup_trait_def(tcx, trait_id)
318 }
319
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)))
323 };
324
325 trait_def_of_item(self, &*item)
326 }
327
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>
333 {
334 self.cycle_check(span, AstConvRequest::EnsureSuperPredicates(trait_def_id), || {
335 let def_ids = ensure_super_predicates_step(self, trait_def_id);
336
337 for def_id in def_ids {
338 try!(self.ensure_super_predicates(span, def_id));
339 }
340
341 Ok(())
342 })
343 }
344}
345
346impl<'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)
349 }
350}
351
352impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
353 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
354
355 fn get_item_type_scheme(&self, span: Span, id: ast::DefId)
356 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
357 {
358 self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || {
359 Ok(type_scheme_of_def_id(self.ccx, id))
360 })
361 }
362
363 fn get_trait_def(&self, span: Span, id: ast::DefId)
d9579d0f 364 -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
c34b1796
AL
365 {
366 self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || {
367 Ok(self.ccx.get_trait_def(id))
368 })
369 }
370
371 fn ensure_super_predicates(&self,
372 span: Span,
373 trait_def_id: ast::DefId)
374 -> Result<(), ErrorReported>
375 {
376 debug!("ensure_super_predicates(trait_def_id={})",
377 trait_def_id.repr(self.tcx()));
378
379 self.ccx.ensure_super_predicates(span, trait_def_id)
380 }
381
382
383 fn get_type_parameter_bounds(&self,
384 span: Span,
385 node_id: ast::NodeId)
386 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
387 {
388 self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || {
389 let v = self.param_bounds.get_type_parameter_bounds(self, span, node_id)
390 .into_iter()
391 .filter_map(|p| p.to_opt_poly_trait_ref())
392 .collect();
393 Ok(v)
394 })
395 }
396
397 fn trait_defines_associated_type_named(&self,
398 trait_def_id: ast::DefId,
399 assoc_name: ast::Name)
400 -> bool
401 {
402 if trait_def_id.krate == ast::LOCAL_CRATE {
403 trait_defines_associated_type_named(self.ccx, trait_def_id.node, assoc_name)
404 } else {
405 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
406 trait_def.associated_type_names.contains(&assoc_name)
407 }
1a4d82fc
JJ
408 }
409
410 fn ty_infer(&self, span: Span) -> Ty<'tcx> {
85aaf69f 411 span_err!(self.tcx().sess, span, E0121,
1a4d82fc
JJ
412 "the type placeholder `_` is not allowed within types on item signatures");
413 self.tcx().types.err
414 }
415
416 fn projected_ty(&self,
417 _span: Span,
d9579d0f 418 trait_ref: ty::TraitRef<'tcx>,
1a4d82fc
JJ
419 item_name: ast::Name)
420 -> Ty<'tcx>
421 {
85aaf69f 422 ty::mk_projection(self.tcx(), trait_ref, item_name)
1a4d82fc
JJ
423 }
424}
425
c34b1796
AL
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.
428trait GetTypeParameterBounds<'tcx> {
429 fn get_type_parameter_bounds(&self,
430 astconv: &AstConv<'tcx>,
431 span: Span,
432 node_id: ast::NodeId)
433 -> Vec<ty::Predicate<'tcx>>;
434}
435
436/// Find bounds from both elements of the tuple.
437impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
438 where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx>
439{
440 fn get_type_parameter_bounds(&self,
441 astconv: &AstConv<'tcx>,
442 span: Span,
443 node_id: ast::NodeId)
444 -> Vec<ty::Predicate<'tcx>>
445 {
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());
448 v
449 }
450}
451
452/// Empty set of bounds.
453impl<'tcx> GetTypeParameterBounds<'tcx> for () {
454 fn get_type_parameter_bounds(&self,
455 _astconv: &AstConv<'tcx>,
456 _span: Span,
457 _node_id: ast::NodeId)
458 -> Vec<ty::Predicate<'tcx>>
459 {
460 Vec::new()
461 }
462}
463
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.
467impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
468 fn get_type_parameter_bounds(&self,
469 astconv: &AstConv<'tcx>,
470 _span: Span,
471 node_id: ast::NodeId)
472 -> Vec<ty::Predicate<'tcx>>
473 {
474 let def = astconv.tcx().type_parameter_def(node_id);
475
476 self.predicates
477 .iter()
478 .filter(|predicate| {
479 match **predicate {
480 ty::Predicate::Trait(ref data) => {
481 data.skip_binder().self_ty().is_param(def.space, def.index)
482 }
483 ty::Predicate::TypeOutlives(ref data) => {
484 data.skip_binder().0.is_param(def.space, def.index)
485 }
486 ty::Predicate::Equate(..) |
487 ty::Predicate::RegionOutlives(..) |
488 ty::Predicate::Projection(..) => {
489 false
490 }
491 }
492 })
493 .cloned()
494 .collect()
495 }
496}
497
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.
502impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
503 fn get_type_parameter_bounds(&self,
504 astconv: &AstConv<'tcx>,
505 _: Span,
506 node_id: ast::NodeId)
507 -> Vec<ty::Predicate<'tcx>>
508 {
509 // In the AST, bounds can derive from two places. Either
510 // written inline like `<T:Foo>` or in a where clause like
511 // `where T:Foo`.
512
513 let def = astconv.tcx().type_parameter_def(node_id);
514 let ty = ty::mk_param_from_def(astconv.tcx(), &def);
515
516 let from_ty_params =
517 self.ty_params
518 .iter()
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());
522
523 let from_where_clauses =
524 self.where_clause
525 .predicates
526 .iter()
527 .filter_map(|wp| match *wp {
528 ast::WherePredicate::BoundPredicate(ref bp) => Some(bp),
529 _ => None
530 })
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());
534
535 from_ty_params.chain(from_where_clauses).collect()
536 }
537}
538
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.
543fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
544 ast_ty: &ast::Ty,
545 param_id: ast::NodeId)
546 -> bool
547{
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 {
9346a6ac
AL
551 def::DefSelfTy(Some(def_id), None) => {
552 path_res.depth == 0 && def_id.node == param_id
553 }
554 def::DefTyParam(_, _, def_id, _) => {
555 path_res.depth == 0 && def_id == local_def(param_id)
556 }
557 _ => {
558 false
559 }
c34b1796
AL
560 }
561 } else {
562 false
563 }
564}
565
566fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
567 enum_scheme: ty::TypeScheme<'tcx>,
568 enum_predicates: ty::GenericPredicates<'tcx>,
569 variants: &[P<ast::Variant>]) {
1a4d82fc 570 let tcx = ccx.tcx;
c34b1796 571 let icx = ccx.icx(&enum_predicates);
1a4d82fc
JJ
572
573 // Create a set of parameter types shared among all the variants.
85aaf69f 574 for variant in variants {
1a4d82fc
JJ
575 let variant_def_id = local_def(variant.node.id);
576
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 {
9346a6ac 580 ast::TupleVariantKind(ref args) if !args.is_empty() => {
1a4d82fc 581 let rs = ExplicitRscope;
c34b1796
AL
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)
1a4d82fc
JJ
584 }
585
586 ast::TupleVariantKind(_) => {
85aaf69f 587 enum_scheme.ty
1a4d82fc
JJ
588 }
589
590 ast::StructVariantKind(ref struct_def) => {
85aaf69f
SL
591 convert_struct(ccx, &**struct_def, enum_scheme.clone(),
592 enum_predicates.clone(), variant.node.id);
593 enum_scheme.ty
1a4d82fc
JJ
594 }
595 };
596
85aaf69f
SL
597 let variant_scheme = TypeScheme {
598 generics: enum_scheme.generics.clone(),
1a4d82fc
JJ
599 ty: result_ty
600 };
601
85aaf69f
SL
602 tcx.tcache.borrow_mut().insert(variant_def_id, variant_scheme.clone());
603 tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
1a4d82fc
JJ
604 write_ty_to_tcx(tcx, variant.node.id, result_ty);
605 }
606}
607
c34b1796
AL
608fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
609 container: ImplOrTraitItemContainer,
610 sig: &ast::MethodSig,
611 id: ast::NodeId,
612 ident: ast::Ident,
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);
618
619 let ty_generic_predicates =
620 ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
621
622 let (fty, explicit_self_category) =
623 astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
624 sig, untransformed_rcvr_ty);
625
626 let def_id = local_def(id);
627 let ty_method = ty::Method::new(ident.name,
628 ty_generics,
629 ty_generic_predicates,
630 fty,
631 explicit_self_category,
632 vis,
633 def_id,
634 container,
635 None);
636
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(),
643 ty: fty
644 });
645 ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
1a4d82fc 646
c34b1796 647 write_ty_to_tcx(ccx.tcx, id, fty);
1a4d82fc 648
c34b1796
AL
649 debug!("writing method type: def_id={:?} mty={}",
650 def_id, ty_method.repr(ccx.tcx));
1a4d82fc 651
c34b1796
AL
652 ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id,
653 ty::MethodTraitItem(Rc::new(ty_method)));
1a4d82fc
JJ
654}
655
c34b1796
AL
656fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
657 struct_generics: &ty::Generics<'tcx>,
658 struct_predicates: &ty::GenericPredicates<'tcx>,
659 v: &ast::StructField,
660 origin: ast::DefId)
661 -> ty::field_ty
662{
663 let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
1a4d82fc 664 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
85aaf69f 665
1a4d82fc
JJ
666 /* add the field to the tcache */
667 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
668 ty::TypeScheme {
669 generics: struct_generics.clone(),
670 ty: tt
671 });
85aaf69f
SL
672 ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
673 struct_predicates.clone());
1a4d82fc
JJ
674
675 match v.node.kind {
676 ast::NamedField(ident, visibility) => {
677 ty::field_ty {
678 name: ident.name,
679 id: local_def(v.node.id),
680 vis: visibility,
681 origin: origin,
682 }
683 }
684 ast::UnnamedField(visibility) => {
685 ty::field_ty {
686 name: special_idents::unnamed_field.name,
687 id: local_def(v.node.id),
688 vis: visibility,
689 origin: origin,
690 }
691 }
692 }
693}
694
d9579d0f
AL
695fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
696 container: ImplOrTraitItemContainer,
697 ident: ast::Ident,
698 id: ast::NodeId,
699 vis: ast::Visibility,
700 ty: ty::Ty<'tcx>,
701 default: Option<&ast::Expr>)
702{
703 ccx.tcx.predicates.borrow_mut().insert(local_def(id),
704 ty::GenericPredicates::empty());
705
706 write_ty_to_tcx(ccx.tcx, id, ty);
707 let default_id = default.map(|expr| local_def(expr.id));
708
709 let associated_const = Rc::new(ty::AssociatedConst {
710 name: ident.name,
711 vis: vis,
712 def_id: local_def(id),
713 container: container,
714 ty: ty,
715 default: default_id,
716 });
717 ccx.tcx.impl_or_trait_items.borrow_mut()
718 .insert(local_def(id), ty::ConstTraitItem(associated_const));
719}
720
c34b1796 721fn as_refsociated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
d9579d0f
AL
722 container: ImplOrTraitItemContainer,
723 ident: ast::Ident,
724 id: ast::NodeId,
725 vis: ast::Visibility)
1a4d82fc
JJ
726{
727 let associated_type = Rc::new(ty::AssociatedType {
c34b1796
AL
728 name: ident.name,
729 vis: vis,
730 def_id: local_def(id),
731 container: container
1a4d82fc 732 });
c34b1796
AL
733 ccx.tcx.impl_or_trait_items.borrow_mut()
734 .insert(local_def(id), ty::TypeTraitItem(associated_type));
1a4d82fc
JJ
735}
736
c34b1796 737fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 738 container: ImplOrTraitItemContainer,
c34b1796 739 methods: I,
1a4d82fc
JJ
740 untransformed_rcvr_ty: Ty<'tcx>,
741 rcvr_ty_generics: &ty::Generics<'tcx>,
c34b1796
AL
742 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>)
743 where I: Iterator<Item=(&'i ast::MethodSig, ast::NodeId, ast::Ident, ast::Visibility, Span)>
744{
745 debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={}, rcvr_ty_predicates={})",
1a4d82fc 746 untransformed_rcvr_ty.repr(ccx.tcx),
c34b1796
AL
747 rcvr_ty_generics.repr(ccx.tcx),
748 rcvr_ty_predicates.repr(ccx.tcx));
1a4d82fc
JJ
749
750 let tcx = ccx.tcx;
85aaf69f 751 let mut seen_methods = FnvHashSet();
c34b1796
AL
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");
1a4d82fc
JJ
755 }
756
c34b1796
AL
757 convert_method(ccx,
758 container,
759 sig,
760 id,
761 ident,
762 vis,
763 untransformed_rcvr_ty,
764 rcvr_ty_generics,
765 rcvr_ty_predicates);
1a4d82fc
JJ
766 }
767}
768
c34b1796 769fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
1a4d82fc
JJ
770 span: Span,
771 generics: &ast::Generics,
772 thing: &'static str) {
773 let mut warn = false;
774
85aaf69f
SL
775 for ty_param in &*generics.ty_params {
776 for bound in &*ty_param.bounds {
1a4d82fc
JJ
777 match *bound {
778 ast::TraitTyParamBound(..) => {
779 warn = true;
780 }
781 ast::RegionTyParamBound(..) => { }
782 }
783 }
784 }
785
786 if warn {
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 \
793 in {} definitions",
794 thing);
795 }
796}
797
c34b1796 798fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
1a4d82fc
JJ
799 let tcx = ccx.tcx;
800 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
801 match it.node {
802 // These don't define types.
85aaf69f
SL
803 ast::ItemExternCrate(_) | ast::ItemUse(_) |
804 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {
805 }
806 ast::ItemEnum(ref enum_definition, _) => {
807 let (scheme, predicates) = convert_typed_item(ccx, it);
1a4d82fc
JJ
808 write_ty_to_tcx(tcx, it.id, scheme.ty);
809 get_enum_variant_types(ccx,
85aaf69f
SL
810 scheme,
811 predicates,
812 &enum_definition.variants);
1a4d82fc 813 },
c34b1796
AL
814 ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
815 let trait_ref =
816 astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
817 &ExplicitRscope,
818 ast_trait_ref,
819 None);
820
821 ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
822
823 tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
824 }
1a4d82fc
JJ
825 ast::ItemImpl(_, _,
826 ref generics,
827 ref opt_trait_ref,
828 ref selfty,
829 ref impl_items) => {
830 // Create generics from the generics specified in the impl head.
85aaf69f
SL
831
832 debug!("convert: ast_generics={:?}", generics);
1a4d82fc 833 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
c34b1796 834 let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
85aaf69f
SL
835
836 debug!("convert: impl_bounds={:?}", ty_predicates);
1a4d82fc 837
c34b1796 838 let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
1a4d82fc
JJ
839 write_ty_to_tcx(tcx, it.id, selfty);
840
85aaf69f
SL
841 tcx.tcache.borrow_mut().insert(local_def(it.id),
842 TypeScheme { generics: ty_generics.clone(),
843 ty: selfty });
844 tcx.predicates.borrow_mut().insert(local_def(it.id),
845 ty_predicates.clone());
1a4d82fc
JJ
846
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() {
853 ast::Public
854 } else {
855 it.vis
856 };
857
d9579d0f 858 // Convert all the associated consts.
85aaf69f 859 for impl_item in impl_items {
d9579d0f
AL
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),
864 TypeScheme {
865 generics: ty_generics.clone(),
866 ty: ty,
867 });
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),
871 ty, Some(&*expr));
872 }
873 }
c34b1796 874
d9579d0f
AL
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");
1a4d82fc 881 }
d9579d0f
AL
882
883 as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
884 impl_item.ident, impl_item.id, impl_item.vis);
885
886 let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
887 tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
888 TypeScheme {
889 generics: ty::Generics::empty(),
890 ty: typ,
891 });
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);
1a4d82fc
JJ
895 }
896 }
897
c34b1796 898 let methods = impl_items.iter().filter_map(|ii| {
d9579d0f
AL
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
903 // foo(); }`).
904 let method_vis = ii.vis.inherit_from(parent_visibility);
905 Some((sig, ii.id, ii.ident, method_vis, ii.span))
906 } else {
907 None
c34b1796
AL
908 }
909 });
1a4d82fc
JJ
910 convert_methods(ccx,
911 ImplContainer(local_def(it.id)),
c34b1796 912 methods,
1a4d82fc
JJ
913 selfty,
914 &ty_generics,
c34b1796
AL
915 &ty_predicates);
916
917 for impl_item in impl_items {
d9579d0f
AL
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),
923 selfty,
924 &sig.explicit_self,
925 body_id);
c34b1796
AL
926 }
927 }
928
929 if let Some(ref ast_trait_ref) = *opt_trait_ref {
930 let trait_ref =
931 astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
932 &ExplicitRscope,
933 ast_trait_ref,
934 Some(selfty));
935
936 tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
1a4d82fc
JJ
937 }
938
9346a6ac
AL
939 enforce_impl_params_are_constrained(tcx,
940 generics,
941 local_def(it.id),
942 impl_items);
1a4d82fc 943 },
c34b1796 944 ast::ItemTrait(_, _, _, ref trait_items) => {
1a4d82fc 945 let trait_def = trait_def_of_item(ccx, it);
c34b1796
AL
946 let _: Result<(), ErrorReported> = // any error is already reported, can ignore
947 ccx.ensure_super_predicates(it.span, local_def(it.id));
85aaf69f 948 convert_trait_predicates(ccx, it);
c34b1796 949 let trait_predicates = ty::lookup_predicates(tcx, local_def(it.id));
1a4d82fc 950
85aaf69f 951 debug!("convert: trait_bounds={:?}", trait_predicates);
1a4d82fc 952
c34b1796
AL
953 // Convert all the associated types.
954 for trait_item in trait_items {
955 match trait_item.node {
d9579d0f
AL
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),
960 TypeScheme {
961 generics: trait_def.generics.clone(),
962 ty: ty,
963 });
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));
967 }
968 _ => {}
969 }
970 };
971
972 // Convert all the associated types.
973 for trait_item in trait_items {
974 match trait_item.node {
c34b1796
AL
975 ast::TypeTraitItem(..) => {
976 as_refsociated_type(ccx, TraitContainer(local_def(it.id)),
977 trait_item.ident, trait_item.id, ast::Public);
1a4d82fc 978 }
d9579d0f 979 _ => {}
1a4d82fc 980 }
c34b1796
AL
981 };
982
983 let methods = trait_items.iter().filter_map(|ti| {
984 let sig = match ti.node {
985 ast::MethodTraitItem(ref sig, _) => sig,
d9579d0f 986 _ => return None,
c34b1796
AL
987 };
988 Some((sig, ti.id, ti.ident, ast::Inherited, ti.span))
989 });
1a4d82fc 990
c34b1796 991 // Run convert_methods on the trait methods.
1a4d82fc
JJ
992 convert_methods(ccx,
993 TraitContainer(local_def(it.id)),
c34b1796
AL
994 methods,
995 ty::mk_self_type(tcx),
1a4d82fc 996 &trait_def.generics,
c34b1796 997 &trait_predicates);
1a4d82fc 998
c34b1796
AL
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 {
d9579d0f
AL
1003 ast::ConstTraitItem(..) => {
1004 ty::ConstTraitItemId(def_id)
1005 }
c34b1796
AL
1006 ast::MethodTraitItem(..) => {
1007 ty::MethodTraitItemId(def_id)
1008 }
1009 ast::TypeTraitItem(..) => {
1010 ty::TypeTraitItemId(def_id)
1011 }
1012 }
1013 }).collect());
1014 tcx.trait_item_def_ids.borrow_mut().insert(local_def(it.id), trait_item_def_ids);
1015
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,
d9579d0f 1021 _ => continue
c34b1796
AL
1022 };
1023 check_method_self_type(ccx,
1024 &BindingRscope::new(),
1025 ccx.method_ty(trait_item.id),
1026 ty::mk_self_type(tcx),
1027 &sig.explicit_self,
1028 it.id)
1029 }
1a4d82fc
JJ
1030 },
1031 ast::ItemStruct(ref struct_def, _) => {
1032 // Write the class type.
85aaf69f 1033 let (scheme, predicates) = convert_typed_item(ccx, it);
1a4d82fc 1034 write_ty_to_tcx(tcx, it.id, scheme.ty);
85aaf69f 1035 convert_struct(ccx, &**struct_def, scheme, predicates, it.id);
1a4d82fc
JJ
1036 },
1037 ast::ItemTy(_, ref generics) => {
1038 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
85aaf69f
SL
1039 let (scheme, _) = convert_typed_item(ccx, it);
1040 write_ty_to_tcx(tcx, it.id, scheme.ty);
1a4d82fc
JJ
1041 },
1042 _ => {
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.
85aaf69f 1046 let (scheme, _) = convert_typed_item(ccx, it);
1a4d82fc
JJ
1047 write_ty_to_tcx(tcx, it.id, scheme.ty);
1048 },
1049 }
1050}
1051
c34b1796 1052fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1053 struct_def: &ast::StructDef,
1054 scheme: ty::TypeScheme<'tcx>,
1055 predicates: ty::GenericPredicates<'tcx>,
1056 id: ast::NodeId) {
1a4d82fc
JJ
1057 let tcx = ccx.tcx;
1058
1059 // Write the type of each of the members and check for duplicate fields.
85aaf69f 1060 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
1a4d82fc 1061 let field_tys = struct_def.fields.iter().map(|f| {
85aaf69f 1062 let result = convert_field(ccx, &scheme.generics, &predicates, f, local_def(id));
1a4d82fc
JJ
1063
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");
1071 true
1072 },
1073 None => false,
1074 };
1075 // FIXME(#6393) this whole dup thing is just to satisfy
1076 // the borrow checker :-(
1077 if !dup {
1078 seen_fields.insert(result.name, f.span);
1079 }
1080 }
1081
1082 result
1083 }).collect();
1084
1085 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
1086
1087 let substs = mk_item_substs(ccx, &scheme.generics);
1088 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
1089
1090 // If this struct is enum-like or tuple-like, create the type of its
1091 // constructor.
1092 match struct_def.ctor_id {
1093 None => {}
1094 Some(ctor_id) => {
9346a6ac 1095 if struct_def.fields.is_empty() {
1a4d82fc
JJ
1096 // Enum-like.
1097 write_ty_to_tcx(tcx, ctor_id, selfty);
1098
1099 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
85aaf69f 1100 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1a4d82fc
JJ
1101 } else if struct_def.fields[0].node.kind.is_unnamed() {
1102 // Tuple-like.
c34b1796
AL
1103 let inputs: Vec<_> =
1104 struct_def.fields
1105 .iter()
1106 .map(|field| tcx.tcache.borrow().get(&local_def(field.node.id))
1107 .unwrap()
1108 .ty)
1109 .collect();
1a4d82fc
JJ
1110 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
1111 local_def(ctor_id),
85aaf69f 1112 &inputs[..],
1a4d82fc
JJ
1113 selfty);
1114 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
1115 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
85aaf69f
SL
1116 TypeScheme {
1117 generics: scheme.generics,
1118 ty: ctor_fn_ty
1119 });
1120 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1a4d82fc
JJ
1121 }
1122 }
1123 }
1124}
1125
c34b1796
AL
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
1132/// converted.
1133fn ensure_super_predicates_step(ccx: &CrateCtxt,
1134 trait_def_id: ast::DefId)
1135 -> Vec<ast::DefId>
1136{
85aaf69f
SL
1137 let tcx = ccx.tcx;
1138
c34b1796 1139 debug!("ensure_super_predicates_step(trait_def_id={})", trait_def_id.repr(tcx));
1a4d82fc 1140
c34b1796
AL
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.
1147 return Vec::new();
1a4d82fc 1148 }
c34b1796
AL
1149
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;
1153
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))
1157 };
1158
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"),
1163 };
1164
1165 // In-scope when converting the superbounds for `Trait` are
1166 // that `Self:Trait` as well as any bounds that appear on the
1167 // generic types:
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()],
1172 vec![])
1173 };
1174 let scope = &(generics, &self_predicate);
1175
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);
1181
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);
1185
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![])
1190 };
1191 debug!("superpredicates for trait {} = {}",
1192 local_def(item.id).repr(ccx.tcx),
1193 superpredicates.repr(ccx.tcx));
1194
1195 tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
1196
1197 superpredicates
1198 });
1199
1200 let def_ids: Vec<_> = superpredicates.predicates
1201 .iter()
1202 .filter_map(|p| p.to_opt_poly_trait_ref())
1203 .map(|tr| tr.def_id())
1204 .collect();
1205
1206 debug!("ensure_super_predicates_step: def_ids={}", def_ids.repr(tcx));
1207
1208 def_ids
1a4d82fc
JJ
1209}
1210
c34b1796 1211fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 1212 it: &ast::Item)
d9579d0f 1213 -> &'tcx ty::TraitDef<'tcx>
1a4d82fc
JJ
1214{
1215 let def_id = local_def(it.id);
1216 let tcx = ccx.tcx;
85aaf69f 1217
1a4d82fc
JJ
1218 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
1219 return def.clone();
1220 }
1221
c34b1796
AL
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"),
1a4d82fc
JJ
1225 };
1226
85aaf69f
SL
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(
1230 it.span,
1231 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
1232 which traits can use parenthetical notation");
c34b1796 1233 fileline_help!(ccx.tcx.sess, it.span,
85aaf69f
SL
1234 "add `#![feature(unboxed_closures)]` to \
1235 the crate attributes to use it");
1236 }
1237
1a4d82fc
JJ
1238 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
1239
85aaf69f 1240 let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics);
1a4d82fc 1241
c34b1796
AL
1242 let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
1243 match trait_item.node {
c34b1796 1244 ast::TypeTraitItem(..) => Some(trait_item.ident.name),
d9579d0f 1245 _ => None,
c34b1796
AL
1246 }
1247 }).collect();
1a4d82fc 1248
d9579d0f 1249 let trait_ref = ty::TraitRef {
1a4d82fc 1250 def_id: def_id,
85aaf69f 1251 substs: substs,
d9579d0f 1252 };
1a4d82fc 1253
d9579d0f 1254 let trait_def = ty::TraitDef {
85aaf69f 1255 paren_sugar: paren_sugar,
1a4d82fc
JJ
1256 unsafety: unsafety,
1257 generics: ty_generics,
1a4d82fc
JJ
1258 trait_ref: trait_ref,
1259 associated_type_names: associated_type_names,
d9579d0f
AL
1260 nonblanket_impls: RefCell::new(FnvHashMap()),
1261 blanket_impls: RefCell::new(vec![]),
1262 flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS)
1263 };
1a4d82fc 1264
d9579d0f 1265 return tcx.intern_trait_def(trait_def);
1a4d82fc 1266
c34b1796 1267 fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 1268 generics: &ast::Generics)
c34b1796 1269 -> Substs<'tcx>
1a4d82fc 1270 {
85aaf69f
SL
1271 let tcx = ccx.tcx;
1272
1a4d82fc
JJ
1273 // Creates a no-op substitution for the trait's type parameters.
1274 let regions =
1275 generics.lifetimes
1276 .iter()
1277 .enumerate()
9346a6ac
AL
1278 .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
1279 param_id: def.lifetime.id,
1280 space: TypeSpace,
1281 index: i as u32,
1282 name: def.lifetime.name
1283 }))
1a4d82fc
JJ
1284 .collect();
1285
1286 // Start with the generics in the type parameters...
1287 let types: Vec<_> =
1288 generics.ty_params
1289 .iter()
1290 .enumerate()
c34b1796 1291 .map(|(i, def)| ty::mk_param(tcx, TypeSpace,
1a4d82fc
JJ
1292 i as u32, def.ident.name))
1293 .collect();
1294
1295 // ...and also create the `Self` parameter.
85aaf69f 1296 let self_ty = ty::mk_self_type(tcx);
1a4d82fc 1297
c34b1796 1298 Substs::new_trait(types, regions, self_ty)
1a4d82fc
JJ
1299 }
1300}
1301
c34b1796
AL
1302fn trait_defines_associated_type_named(ccx: &CrateCtxt,
1303 trait_node_id: ast::NodeId,
1304 assoc_name: ast::Name)
1305 -> bool
1306{
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))
1310 };
1311
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))
1315 };
1316
1317 trait_items.iter().any(|trait_item| {
1318 match trait_item.node {
1319 ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
d9579d0f 1320 _ => false,
c34b1796
AL
1321 }
1322 })
1323}
1324
1325fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
1a4d82fc 1326 let tcx = ccx.tcx;
85aaf69f
SL
1327 let trait_def = trait_def_of_item(ccx, it);
1328
1329 let def_id = local_def(it.id);
1330
1331 let (generics, items) = match it.node {
1332 ast::ItemTrait(_, ref generics, _, ref items) => (generics, items),
1333 ref s => {
1334 tcx.sess.span_bug(
1335 it.span,
c34b1796 1336 &format!("trait_def_of_item invoked on {:?}", s));
85aaf69f
SL
1337 }
1338 };
1339
c34b1796 1340 let super_predicates = ty::lookup_super_predicates(ccx.tcx, def_id);
85aaf69f 1341
c34b1796 1342 // `ty_generic_predicates` below will consider the bounds on the type
85aaf69f
SL
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.
c34b1796 1347 let mut base_predicates = super_predicates;
85aaf69f 1348
c34b1796
AL
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);
85aaf69f
SL
1353
1354 // add in the explicit where-clauses
c34b1796
AL
1355 let mut trait_predicates =
1356 ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
1357
1358 let assoc_predicates = predicates_for_associated_types(ccx,
1359 generics,
1360 &trait_predicates,
d9579d0f 1361 trait_def.trait_ref,
c34b1796
AL
1362 items);
1363 trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
85aaf69f
SL
1364
1365 let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
1366 assert!(prev_predicates.is_none());
1367
1368 return;
1369
c34b1796
AL
1370 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1371 ast_generics: &ast::Generics,
1372 trait_predicates: &ty::GenericPredicates<'tcx>,
d9579d0f 1373 self_trait_ref: ty::TraitRef<'tcx>,
c34b1796 1374 trait_items: &[P<ast::TraitItem>])
85aaf69f
SL
1375 -> Vec<ty::Predicate<'tcx>>
1376 {
c34b1796
AL
1377 trait_items.iter().flat_map(|trait_item| {
1378 let bounds = match trait_item.node {
1379 ast::TypeTraitItem(ref bounds, _) => bounds,
d9579d0f 1380 _ => {
c34b1796
AL
1381 return vec!().into_iter();
1382 }
1383 };
85aaf69f 1384
c34b1796 1385 let assoc_ty = ty::mk_projection(ccx.tcx,
d9579d0f 1386 self_trait_ref,
c34b1796 1387 trait_item.ident.name);
85aaf69f 1388
c34b1796
AL
1389 let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
1390 assoc_ty,
1391 bounds,
1392 SizedByDefault::Yes,
1393 trait_item.span);
85aaf69f 1394
c34b1796
AL
1395 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
1396 }).collect()
1a4d82fc 1397 }
85aaf69f
SL
1398}
1399
c34b1796
AL
1400fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1401 def_id: ast::DefId)
1402 -> ty::TypeScheme<'tcx>
1403{
1404 if def_id.krate != ast::LOCAL_CRATE {
1405 return ty::lookup_item_type(ccx.tcx, def_id);
1406 }
1407
1408 match ccx.tcx.map.find(def_id.node) {
1409 Some(ast_map::NodeItem(item)) => {
1410 type_scheme_of_item(ccx, &*item)
1411 }
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)
1415 }
1416 x => {
1417 ccx.tcx.sess.bug(&format!("unexpected sort of node \
1418 in get_item_type_scheme(): {:?}",
1419 x));
1420 }
1421 }
1422}
1423
1424fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
85aaf69f
SL
1425 it: &ast::Item)
1426 -> ty::TypeScheme<'tcx>
1427{
1428 memoized(&ccx.tcx.tcache,
1429 local_def(it.id),
1430 |_| compute_type_scheme_of_item(ccx, it))
1431}
1432
c34b1796
AL
1433fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1434 it: &ast::Item)
1435 -> ty::TypeScheme<'tcx>
85aaf69f
SL
1436{
1437 let tcx = ccx.tcx;
1a4d82fc
JJ
1438 match it.node {
1439 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
c34b1796 1440 let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
85aaf69f 1441 ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
1a4d82fc
JJ
1442 }
1443 ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
c34b1796
AL
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);
85aaf69f
SL
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 }
1a4d82fc
JJ
1448 }
1449 ast::ItemTy(ref t, ref generics) => {
85aaf69f 1450 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
c34b1796 1451 let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
85aaf69f 1452 ty::TypeScheme { ty: ty, generics: ty_generics }
1a4d82fc
JJ
1453 }
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));
85aaf69f 1459 ty::TypeScheme { ty: t, generics: ty_generics }
1a4d82fc
JJ
1460 }
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));
85aaf69f
SL
1465 ty::TypeScheme { ty: t, generics: ty_generics }
1466 }
c34b1796 1467 ast::ItemDefaultImpl(..) |
85aaf69f
SL
1468 ast::ItemTrait(..) |
1469 ast::ItemImpl(..) |
1470 ast::ItemMod(..) |
1471 ast::ItemForeignMod(..) |
1472 ast::ItemExternCrate(..) |
1473 ast::ItemUse(..) |
1474 ast::ItemMac(..) => {
1475 tcx.sess.span_bug(
1476 it.span,
c34b1796
AL
1477 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1478 it.node));
85aaf69f
SL
1479 }
1480 }
1481}
1482
c34b1796 1483fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1484 it: &ast::Item)
1485 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
1486{
1487 let tcx = ccx.tcx;
1a4d82fc 1488
85aaf69f
SL
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()
1a4d82fc 1494 }
85aaf69f 1495 ast::ItemFn(_, _, _, ref ast_generics, _) => {
c34b1796 1496 ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
85aaf69f
SL
1497 }
1498 ast::ItemTy(_, ref generics) => {
c34b1796 1499 ty_generic_predicates_for_type_or_impl(ccx, generics)
85aaf69f
SL
1500 }
1501 ast::ItemEnum(_, ref generics) => {
c34b1796 1502 ty_generic_predicates_for_type_or_impl(ccx, generics)
85aaf69f
SL
1503 }
1504 ast::ItemStruct(_, ref generics) => {
c34b1796 1505 ty_generic_predicates_for_type_or_impl(ccx, generics)
85aaf69f 1506 }
c34b1796 1507 ast::ItemDefaultImpl(..) |
85aaf69f
SL
1508 ast::ItemTrait(..) |
1509 ast::ItemExternCrate(..) |
1510 ast::ItemUse(..) |
1511 ast::ItemImpl(..) |
1512 ast::ItemMod(..) |
1513 ast::ItemForeignMod(..) |
1514 ast::ItemMac(..) => {
1515 tcx.sess.span_bug(
1516 it.span,
c34b1796
AL
1517 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1518 it.node));
85aaf69f
SL
1519 }
1520 };
1521
1522 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id),
1523 predicates.clone());
1524 assert!(prev_predicates.is_none());
1525
1526 // Debugging aid.
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)) =>
1532 r.user_string(tcx),
1533 d =>
c34b1796 1534 d.repr(ccx.tcx),
85aaf69f
SL
1535 })
1536 .collect::<Vec<String>>()
1537 .connect(",");
1538
1539 tcx.sess.span_err(it.span, &object_lifetime_default_reprs);
1a4d82fc 1540 }
85aaf69f
SL
1541
1542 return (scheme, predicates);
1a4d82fc
JJ
1543}
1544
85aaf69f 1545fn type_scheme_of_foreign_item<'a, 'tcx>(
c34b1796 1546 ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1547 it: &ast::ForeignItem,
1548 abi: abi::Abi)
1549 -> ty::TypeScheme<'tcx>
1550{
c34b1796 1551 memoized(&ccx.tcx.tcache,
85aaf69f
SL
1552 local_def(it.id),
1553 |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
1554}
1555
1556fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
c34b1796 1557 ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1558 it: &ast::ForeignItem,
1559 abi: abi::Abi)
1560 -> ty::TypeScheme<'tcx>
1a4d82fc
JJ
1561{
1562 match it.node {
1563 ast::ForeignItemFn(ref fn_decl, ref generics) => {
85aaf69f 1564 compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
1a4d82fc
JJ
1565 }
1566 ast::ForeignItemStatic(ref t, _) => {
1567 ty::TypeScheme {
1568 generics: ty::Generics::empty(),
c34b1796 1569 ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
1a4d82fc
JJ
1570 }
1571 }
1572 }
1573}
1574
c34b1796 1575fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1576 it: &ast::ForeignItem)
1577{
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
1582 let tcx = ccx.tcx;
1583 let abi = tcx.map.get_foreign_abi(it.id);
1584
1585 let scheme = type_scheme_of_foreign_item(ccx, it, abi);
1586 write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
1587
1588 let predicates = match it.node {
1589 ast::ForeignItemFn(_, ref generics) => {
c34b1796 1590 ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
85aaf69f
SL
1591 }
1592 ast::ForeignItemStatic(..) => {
1593 ty::GenericPredicates::empty()
1594 }
1595 };
1596
1597 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id), predicates);
1598 assert!(prev_predicates.is_none());
1599}
1600
c34b1796 1601fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc
JJ
1602 generics: &ast::Generics)
1603 -> ty::Generics<'tcx> {
c34b1796 1604 ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
85aaf69f
SL
1605}
1606
c34b1796
AL
1607fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1608 generics: &ast::Generics)
1609 -> ty::GenericPredicates<'tcx>
85aaf69f 1610{
c34b1796 1611 ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
1a4d82fc
JJ
1612}
1613
c34b1796 1614fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 1615 trait_id: ast::NodeId,
c34b1796 1616 substs: &'tcx Substs<'tcx>,
85aaf69f 1617 ast_generics: &ast::Generics)
1a4d82fc
JJ
1618 -> ty::Generics<'tcx>
1619{
1620 debug!("ty_generics_for_trait(trait_id={}, substs={})",
1621 local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
1622
c34b1796 1623 let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
1a4d82fc
JJ
1624
1625 // Add in the self type parameter.
1626 //
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;
1630
1a4d82fc 1631 let def = ty::TypeParameterDef {
c34b1796 1632 space: SelfSpace,
1a4d82fc
JJ
1633 index: 0,
1634 name: special_idents::type_self.name,
1635 def_id: local_def(param_id),
85aaf69f
SL
1636 default: None,
1637 object_lifetime_default: None,
1a4d82fc
JJ
1638 };
1639
1640 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1641
c34b1796 1642 generics.types.push(SelfSpace, def);
1a4d82fc 1643
1a4d82fc 1644 return generics;
1a4d82fc
JJ
1645}
1646
c34b1796
AL
1647fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1648 generics: &ast::Generics,
1649 base_generics: &ty::Generics<'tcx>)
1650 -> ty::Generics<'tcx>
1a4d82fc 1651{
c34b1796 1652 ty_generics(ccx, FnSpace, generics, base_generics)
85aaf69f
SL
1653}
1654
c34b1796
AL
1655fn 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>
85aaf69f 1659{
c34b1796 1660 ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
1a4d82fc
JJ
1661}
1662
1663// Add the Sized bound, unless the type parameter is marked as `?Sized`.
c34b1796
AL
1664fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
1665 bounds: &mut ty::BuiltinBounds,
1666 ast_bounds: &[ast::TyParamBound],
1667 span: Span)
1a4d82fc 1668{
c34b1796
AL
1669 let tcx = astconv.tcx();
1670
1a4d82fc
JJ
1671 // Try to find an unbound in bounds.
1672 let mut unbound = None;
85aaf69f 1673 for ab in ast_bounds {
1a4d82fc
JJ
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());
1678 } else {
c34b1796 1679 span_err!(tcx.sess, span, E0203,
85aaf69f 1680 "type parameter has more than one relaxed default \
1a4d82fc
JJ
1681 bound, only one is supported");
1682 }
1683 }
1684 }
1685
c34b1796 1686 let kind_id = tcx.lang_items.require(SizedTraitLangItem);
1a4d82fc
JJ
1687 match unbound {
1688 Some(ref tpb) => {
1689 // FIXME(#8559) currently requires the unbound to be built-in.
c34b1796 1690 let trait_def_id = ty::trait_ref_to_def_id(tcx, tpb);
1a4d82fc
JJ
1691 match kind_id {
1692 Ok(kind_id) if trait_def_id != kind_id => {
c34b1796
AL
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);
1a4d82fc
JJ
1698 }
1699 _ => {}
1700 }
1701 }
1702 _ if kind_id.is_ok() => {
c34b1796 1703 ty::try_add_builtin_trait(tcx, kind_id.unwrap(), bounds);
1a4d82fc
JJ
1704 }
1705 // No lang item for Sized, so we can't add it as a bound.
1706 None => {}
1707 }
1708}
1709
c34b1796
AL
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`.
1715fn early_bound_lifetimes_from_generics(space: ParamSpace,
1716 ast_generics: &ast::Generics)
1717 -> Vec<ast::LifetimeDef>
1718{
1719 match space {
1720 SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
1721 FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics),
1722 }
1723}
1724
1725fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1726 space: ParamSpace,
1727 ast_generics: &ast::Generics,
1728 base_predicates: &ty::GenericPredicates<'tcx>)
1729 -> ty::GenericPredicates<'tcx>
1a4d82fc 1730{
85aaf69f 1731 let tcx = ccx.tcx;
c34b1796
AL
1732 let mut result = base_predicates.clone();
1733
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)),
1740 param_ty,
1741 &param.bounds,
1742 SizedByDefault::Yes,
1743 param.span);
1744 let predicates = ty::predicates(ccx.tcx, param_ty, &bounds);
1745 result.predicates.extend(space, predicates.into_iter());
1a4d82fc 1746 }
c34b1796
AL
1747
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;
9346a6ac
AL
1754 let region =
1755 ty::ReEarlyBound(ty::EarlyBoundRegion {
1756 param_id: param.lifetime.id,
1757 space: space,
1758 index: index,
1759 name: param.lifetime.name
1760 });
c34b1796
AL
1761 for bound in &param.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());
1765 }
1a4d82fc
JJ
1766 }
1767
c34b1796
AL
1768 // Add in the bounds that appear in the where-clause
1769 let where_clause = &ast_generics.where_clause;
85aaf69f 1770 for predicate in &where_clause.predicates {
1a4d82fc
JJ
1771 match predicate {
1772 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
c34b1796
AL
1773 let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
1774 &ExplicitRscope,
1775 &*bound_pred.bounded_ty);
1a4d82fc 1776
85aaf69f 1777 for bound in &*bound_pred.bounds {
1a4d82fc
JJ
1778 match bound {
1779 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1780 let mut projections = Vec::new();
1781
c34b1796
AL
1782 let trait_ref =
1783 conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
1784 ty,
1785 poly_trait_ref,
1786 &mut projections);
1a4d82fc
JJ
1787
1788 result.predicates.push(space, trait_ref.as_predicate());
1789
85aaf69f 1790 for projection in &projections {
1a4d82fc
JJ
1791 result.predicates.push(space, projection.as_predicate());
1792 }
1793 }
1794
1795 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
85aaf69f 1796 let region = ast_region_to_region(tcx, lifetime);
1a4d82fc
JJ
1797 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1798 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1799 }
1800 }
1801 }
1802 }
1803
1804 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
85aaf69f
SL
1805 let r1 = ast_region_to_region(tcx, &region_pred.lifetime);
1806 for bound in &region_pred.bounds {
1807 let r2 = ast_region_to_region(tcx, bound);
1a4d82fc
JJ
1808 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1809 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1810 }
1811 }
1812
1813 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1814 // FIXME(#20041)
85aaf69f
SL
1815 tcx.sess.span_bug(eq_pred.span,
1816 "Equality constraints are not yet \
1817 implemented (#20041)")
1a4d82fc
JJ
1818 }
1819 }
1820 }
1821
1822 return result;
85aaf69f 1823}
1a4d82fc 1824
c34b1796
AL
1825fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1826 space: ParamSpace,
1827 ast_generics: &ast::Generics,
1828 base_generics: &ty::Generics<'tcx>)
85aaf69f
SL
1829 -> ty::Generics<'tcx>
1830{
1831 let tcx = ccx.tcx;
c34b1796 1832 let mut result = base_generics.clone();
1a4d82fc 1833
c34b1796
AL
1834 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1835 for (i, l) in early_lifetimes.iter().enumerate() {
85aaf69f
SL
1836 let bounds = l.bounds.iter()
1837 .map(|l| ast_region_to_region(tcx, l))
1838 .collect();
1839 let def = ty::RegionParameterDef { name: l.lifetime.name,
1840 space: space,
1841 index: i as u32,
1842 def_id: local_def(l.lifetime.id),
1843 bounds: bounds };
85aaf69f 1844 result.regions.push(space, def);
1a4d82fc 1845 }
85aaf69f
SL
1846
1847 assert!(result.types.is_empty_in(space));
1848
1849 // Now create the real type parameters.
c34b1796
AL
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);
85aaf69f
SL
1852 debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
1853 result.types.push(space, def);
1854 }
1855
1856 result
1a4d82fc
JJ
1857}
1858
c34b1796
AL
1859fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1860 ast_generics: &ast::Generics,
1861 space: ParamSpace,
1862 index: u32)
1a4d82fc
JJ
1863 -> ty::TypeParameterDef<'tcx>
1864{
c34b1796
AL
1865 let param = &ast_generics.ty_params[index as usize];
1866
85aaf69f
SL
1867 let tcx = ccx.tcx;
1868 match tcx.ty_param_defs.borrow().get(&param.id) {
1869 Some(d) => { return d.clone(); }
1a4d82fc
JJ
1870 None => { }
1871 }
1872
1a4d82fc
JJ
1873 let default = match param.default {
1874 None => None,
1875 Some(ref path) => {
c34b1796 1876 let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &**path);
1a4d82fc
JJ
1877 let cur_idx = index;
1878
1879 ty::walk_ty(ty, |t| {
1880 match t.sty {
1881 ty::ty_param(p) => if p.idx > cur_idx {
85aaf69f 1882 span_err!(tcx.sess, path.span, E0128,
1a4d82fc 1883 "type parameters with a default cannot use \
9346a6ac 1884 forward declared identifiers");
1a4d82fc
JJ
1885 },
1886 _ => {}
1887 }
1888 });
1889
1890 Some(ty)
1891 }
1892 };
1893
85aaf69f 1894 let object_lifetime_default =
c34b1796
AL
1895 compute_object_lifetime_default(ccx, param.id,
1896 &param.bounds, &ast_generics.where_clause);
85aaf69f 1897
1a4d82fc
JJ
1898 let def = ty::TypeParameterDef {
1899 space: space,
1900 index: index,
1901 name: param.ident.name,
1902 def_id: local_def(param.id),
85aaf69f
SL
1903 default: default,
1904 object_lifetime_default: object_lifetime_default,
1a4d82fc
JJ
1905 };
1906
85aaf69f 1907 tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1a4d82fc
JJ
1908
1909 def
1910}
1911
85aaf69f
SL
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.
c34b1796
AL
1918fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1919 param_id: ast::NodeId,
85aaf69f
SL
1920 param_bounds: &[ast::TyParamBound],
1921 where_clause: &ast::WhereClause)
1922 -> Option<ty::ObjectLifetimeDefault>
1923{
1924 let inline_bounds = from_bounds(ccx, param_bounds);
c34b1796 1925 let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
85aaf69f
SL
1926 let all_bounds: HashSet<_> = inline_bounds.into_iter()
1927 .chain(where_bounds.into_iter())
1928 .collect();
1929 return if all_bounds.len() > 1 {
1930 Some(ty::ObjectLifetimeDefault::Ambiguous)
1931 } else {
1932 all_bounds.into_iter()
1933 .next()
1934 .map(ty::ObjectLifetimeDefault::Specific)
1935 };
1936
c34b1796 1937 fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
85aaf69f
SL
1938 bounds: &[ast::TyParamBound])
1939 -> Vec<ty::Region>
1940 {
1941 bounds.iter()
1942 .filter_map(|bound| {
1943 match *bound {
1944 ast::TraitTyParamBound(..) =>
1945 None,
1946 ast::RegionTyParamBound(ref lifetime) =>
c34b1796 1947 Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
85aaf69f
SL
1948 }
1949 })
1950 .collect()
1951 }
1952
c34b1796
AL
1953 fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1954 param_id: ast::NodeId,
85aaf69f
SL
1955 predicates: &[ast::WherePredicate])
1956 -> Vec<ty::Region>
1957 {
1958 predicates.iter()
1959 .flat_map(|predicate| {
1960 match *predicate {
1961 ast::WherePredicate::BoundPredicate(ref data) => {
9346a6ac 1962 if data.bound_lifetimes.is_empty() &&
c34b1796 1963 is_param(ccx.tcx, &data.bounded_ty, param_id)
85aaf69f
SL
1964 {
1965 from_bounds(ccx, &data.bounds).into_iter()
1966 } else {
1967 Vec::new().into_iter()
1968 }
1969 }
1970 ast::WherePredicate::RegionPredicate(..) |
1971 ast::WherePredicate::EqPredicate(..) => {
1972 Vec::new().into_iter()
1973 }
1974 }
1975 })
1976 .collect()
1977 }
85aaf69f
SL
1978}
1979
c34b1796 1980enum SizedByDefault { Yes, No, }
1a4d82fc
JJ
1981
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.
c34b1796
AL
1985fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
1986 param_ty: ty::Ty<'tcx>,
1987 ast_bounds: &[ast::TyParamBound],
1988 sized_by_default: SizedByDefault,
1989 span: Span)
1990 -> ty::ParamBounds<'tcx>
1a4d82fc 1991{
c34b1796 1992 let mut param_bounds = conv_param_bounds(astconv,
1a4d82fc
JJ
1993 span,
1994 param_ty,
1995 ast_bounds);
1996
1997 if let SizedByDefault::Yes = sized_by_default {
c34b1796 1998 add_unsized_bound(astconv,
1a4d82fc
JJ
1999 &mut param_bounds.builtin_bounds,
2000 ast_bounds,
2001 span);
1a4d82fc
JJ
2002 }
2003
2004 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
2005
2006 param_bounds
2007}
2008
c34b1796
AL
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`).
2014fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
2015 param_ty: Ty<'tcx>,
2016 bound: &ast::TyParamBound)
2017 -> Vec<ty::Predicate<'tcx>>
2018{
2019 match *bound {
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())
2026 .collect()
2027 }
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)]
2032 }
2033 ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {
2034 Vec::new()
2035 }
1a4d82fc
JJ
2036 }
2037}
2038
c34b1796
AL
2039fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
2040 param_ty: Ty<'tcx>,
2041 trait_ref: &ast::PolyTraitRef,
2042 projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
2043 -> ty::PolyTraitRef<'tcx>
2044{
2045 astconv::instantiate_poly_trait_ref(astconv,
2046 &ExplicitRscope,
2047 trait_ref,
2048 Some(param_ty),
2049 projections)
2050}
2051
2052fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
1a4d82fc
JJ
2053 span: Span,
2054 param_ty: ty::Ty<'tcx>,
2055 ast_bounds: &[ast::TyParamBound])
2056 -> ty::ParamBounds<'tcx>
2057{
c34b1796 2058 let tcx = astconv.tcx();
85aaf69f
SL
2059 let astconv::PartitionedBounds {
2060 builtin_bounds,
2061 trait_bounds,
2062 region_bounds
c34b1796 2063 } = astconv::partition_bounds(tcx, span, &ast_bounds);
1a4d82fc
JJ
2064
2065 let mut projection_bounds = Vec::new();
2066
2067 let trait_bounds: Vec<ty::PolyTraitRef> =
c34b1796
AL
2068 trait_bounds.iter()
2069 .map(|bound| conv_poly_trait_ref(astconv,
2070 param_ty,
2071 *bound,
2072 &mut projection_bounds))
2073 .collect();
85aaf69f 2074
1a4d82fc
JJ
2075 let region_bounds: Vec<ty::Region> =
2076 region_bounds.into_iter()
c34b1796 2077 .map(|r| ast_region_to_region(tcx, r))
85aaf69f
SL
2078 .collect();
2079
1a4d82fc
JJ
2080 ty::ParamBounds {
2081 region_bounds: region_bounds,
2082 builtin_bounds: builtin_bounds,
2083 trait_bounds: trait_bounds,
2084 projection_bounds: projection_bounds,
2085 }
2086}
2087
85aaf69f 2088fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
c34b1796 2089 ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
2090 decl: &ast::FnDecl,
2091 ast_generics: &ast::Generics,
2092 abi: abi::Abi)
2093 -> ty::TypeScheme<'tcx>
2094{
1a4d82fc
JJ
2095 for i in decl.inputs.iter() {
2096 match (*i).pat.node {
2097 ast::PatIdent(_, _, _) => (),
2098 ast::PatWild(ast::PatWildSingle) => (),
2099 _ => {
2100 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
2101 "patterns aren't allowed in foreign function declarations");
2102 }
2103 }
2104 }
2105
c34b1796 2106 let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
85aaf69f 2107
1a4d82fc
JJ
2108 let rb = BindingRscope::new();
2109 let input_tys = decl.inputs
2110 .iter()
c34b1796 2111 .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
1a4d82fc
JJ
2112 .collect();
2113
2114 let output = match decl.output {
2115 ast::Return(ref ty) =>
c34b1796 2116 ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
85aaf69f
SL
2117 ast::DefaultReturn(..) =>
2118 ty::FnConverging(ty::mk_nil(ccx.tcx)),
2119 ast::NoReturn(..) =>
1a4d82fc
JJ
2120 ty::FnDiverging
2121 };
2122
2123 let t_fn = ty::mk_bare_fn(
2124 ccx.tcx,
2125 None,
2126 ccx.tcx.mk_bare_fn(ty::BareFnTy {
2127 abi: abi,
2128 unsafety: ast::Unsafety::Unsafe,
2129 sig: ty::Binder(ty::FnSig {inputs: input_tys,
2130 output: output,
2131 variadic: decl.variadic}),
2132 }));
1a4d82fc 2133
85aaf69f
SL
2134 ty::TypeScheme {
2135 generics: ty_generics,
2136 ty: t_fn
2137 }
1a4d82fc
JJ
2138}
2139
c34b1796 2140fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 2141 ty_generics: &ty::Generics<'tcx>)
c34b1796 2142 -> Substs<'tcx>
1a4d82fc
JJ
2143{
2144 let types =
2145 ty_generics.types.map(
2146 |def| ty::mk_param_from_def(ccx.tcx, def));
2147
2148 let regions =
2149 ty_generics.regions.map(
2150 |def| def.to_early_bound_region());
2151
c34b1796 2152 Substs::new(types, regions)
1a4d82fc
JJ
2153}
2154
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.
2161fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
c34b1796 2162 ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 2163 rs: &RS,
c34b1796 2164 method_type: Rc<ty::Method<'tcx>>,
1a4d82fc
JJ
2165 required_type: Ty<'tcx>,
2166 explicit_self: &ast::ExplicitSelf,
2167 body_id: ast::NodeId)
2168{
85aaf69f 2169 let tcx = ccx.tcx;
1a4d82fc 2170 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
c34b1796 2171 let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
1a4d82fc
JJ
2172 let base_type = match typ.sty {
2173 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
2174 ty::ty_uniq(typ) => typ,
2175 _ => typ,
2176 };
2177
85aaf69f 2178 let body_scope = region::DestructionScopeData::new(body_id);
1a4d82fc
JJ
2179
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
2183 // parameters).
2184 assert!(!base_type.has_regions_escaping_depth(1));
2185 let required_type_free =
2186 liberate_early_bound_regions(
85aaf69f 2187 tcx, body_scope,
1a4d82fc 2188 &ty::liberate_late_bound_regions(
85aaf69f 2189 tcx, body_scope, &ty::Binder(required_type)));
1a4d82fc
JJ
2190
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(
85aaf69f 2196 tcx, body_scope,
1a4d82fc 2197 &ty::liberate_late_bound_regions(
85aaf69f 2198 tcx, body_scope, &ty::Binder(base_type)));
1a4d82fc
JJ
2199
2200 debug!("required_type={} required_type_free={} \
2201 base_type={} base_type_free={}",
85aaf69f
SL
2202 required_type.repr(tcx),
2203 required_type_free.repr(tcx),
2204 base_type.repr(tcx),
2205 base_type_free.repr(tcx));
2206
2207 let infcx = infer::new_infer_ctxt(tcx);
2208 drop(::require_same_types(tcx,
1a4d82fc
JJ
2209 Some(&infcx),
2210 false,
2211 explicit_self.span,
2212 base_type_free,
2213 required_type_free,
2214 || {
2215 format!("mismatched self type: expected `{}`",
85aaf69f 2216 ppaux::ty_to_string(tcx, required_type))
1a4d82fc 2217 }));
bd371182
AL
2218
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();
2226
2227 infcx.resolve_regions_and_report_errors(&free_regions, body_id);
1a4d82fc
JJ
2228 }
2229
2230 fn liberate_early_bound_regions<'tcx,T>(
2231 tcx: &ty::ctxt<'tcx>,
85aaf69f 2232 scope: region::DestructionScopeData,
1a4d82fc
JJ
2233 value: &T)
2234 -> T
2235 where T : TypeFoldable<'tcx> + Repr<'tcx>
2236 {
2237 /*!
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.
2242 */
2243
2244 ty_fold::fold_regions(tcx, value, |region, _| {
2245 match region {
9346a6ac
AL
2246 ty::ReEarlyBound(data) => {
2247 let def_id = local_def(data.param_id);
1a4d82fc 2248 ty::ReFree(ty::FreeRegion { scope: scope,
9346a6ac 2249 bound_region: ty::BrNamed(def_id, data.name) })
1a4d82fc
JJ
2250 }
2251 _ => region
2252 }
2253 })
2254 }
2255}
2256
2257/// Checks that all the type parameters on an impl
9346a6ac
AL
2258fn 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>])
1a4d82fc
JJ
2262{
2263 let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
85aaf69f 2264 let impl_predicates = ty::lookup_predicates(tcx, impl_def_id);
1a4d82fc
JJ
2265 let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
2266
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<_> =
9346a6ac
AL
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));
2274 }
2275
2276 ctp::identify_constrained_type_params(tcx,
2277 impl_predicates.predicates.as_slice(),
2278 impl_trait_ref,
2279 &mut input_parameters);
1a4d82fc
JJ
2280
2281 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
2282 let param_ty = ty::ParamTy { space: TypeSpace,
2283 idx: index as u32,
2284 name: ty_param.ident.name };
9346a6ac
AL
2285 if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
2286 report_unused_parameter(tcx, ty_param.span, "type", &param_ty.user_string(tcx));
1a4d82fc
JJ
2287 }
2288 }
9346a6ac
AL
2289
2290 // Every lifetime used in an associated type must be constrained.
2291
2292 let lifetimes_in_associated_types: HashSet<_> =
2293 impl_items.iter()
2294 .filter_map(|item| match item.node {
2295 ast::TypeImplItem(..) => Some(ty::node_id_to_type(tcx, item.id)),
d9579d0f
AL
2296 ast::ConstImplItem(..) | ast::MethodImplItem(..) |
2297 ast::MacImplItem(..) => None,
9346a6ac
AL
2298 })
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),
2303 })
2304 .collect();
2305
2306 for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
2307 let region = ty::EarlyBoundRegion { param_id: lifetime_def.lifetime.id,
2308 space: TypeSpace,
2309 index: index as u32,
2310 name: lifetime_def.lifetime.name };
2311 if
2312 lifetimes_in_associated_types.contains(&region) && // (*)
2313 !input_parameters.contains(&ctp::Parameter::Region(region))
2314 {
2315 report_unused_parameter(tcx, lifetime_def.lifetime.span,
2316 "lifetime", &region.name.user_string(tcx));
2317 }
2318 }
2319
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:
2323 //
2324 // ```
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> {
2328 // ....
2329 // }
2330 // }
2331 // }
2332 // ```
2333 //
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.
2338}
2339
2340fn report_unused_parameter(tcx: &ty::ctxt,
2341 span: Span,
2342 kind: &str,
2343 name: &str)
2344{
2345 span_err!(tcx.sess, span, E0207,
2346 "the {} parameter `{}` is not constrained by the \
2347 impl trait, self type, or predicates",
2348 kind, name);
1a4d82fc 2349}