]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/collect.rs
Imported Upstream version 1.2.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::*;
62682a34 80use rustc::ast_map;
c34b1796 81use util::common::{ErrorReported, memoized};
1a4d82fc 82use util::nodemap::{FnvHashMap, FnvHashSet};
1a4d82fc
JJ
83use write_ty_to_tcx;
84
d9579d0f 85use std::cell::{Cell, RefCell};
1a4d82fc
JJ
86use std::collections::HashSet;
87use std::rc::Rc;
88
89use syntax::abi;
90use syntax::ast;
c34b1796 91use syntax::ast_util::local_def;
1a4d82fc 92use syntax::codemap::Span;
c34b1796 93use syntax::parse::token::special_idents;
1a4d82fc
JJ
94use syntax::parse::token;
95use syntax::ptr::P;
96use syntax::visit;
97
98///////////////////////////////////////////////////////////////////////////
99// Main entry point
100
101pub fn collect_item_types(tcx: &ty::ctxt) {
c34b1796 102 let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
1a4d82fc
JJ
103
104 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
105 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
106
107 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
108 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
109}
110
111///////////////////////////////////////////////////////////////////////////
112
c34b1796 113struct CrateCtxt<'a,'tcx:'a> {
1a4d82fc 114 tcx: &'a ty::ctxt<'tcx>,
c34b1796
AL
115
116 // This stack is used to identify cycles in the user's source.
117 // Note that these cycles can cross multiple items.
118 stack: RefCell<Vec<AstConvRequest>>,
1a4d82fc
JJ
119}
120
c34b1796
AL
121/// Context specific to some particular item. This is what implements
122/// AstConv. It has information about the predicates that are defined
123/// on the trait. Unfortunately, this predicate information is
124/// available in various different forms at various points in the
125/// process. So we can't just store a pointer to e.g. the AST or the
126/// parsed ty form, we have to be more flexible. To this end, the
127/// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object
128/// that it uses to satisfy `get_type_parameter_bounds` requests.
129/// This object might draw the information from the AST
130/// (`ast::Generics`) or it might draw from a `ty::GenericPredicates`
131/// or both (a tuple).
132struct ItemCtxt<'a,'tcx:'a> {
133 ccx: &'a CrateCtxt<'a,'tcx>,
134 param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
135}
1a4d82fc 136
c34b1796
AL
137#[derive(Copy, Clone, PartialEq, Eq)]
138enum AstConvRequest {
139 GetItemTypeScheme(ast::DefId),
140 GetTraitDef(ast::DefId),
141 EnsureSuperPredicates(ast::DefId),
142 GetTypeParameterBounds(ast::NodeId),
1a4d82fc
JJ
143}
144
145///////////////////////////////////////////////////////////////////////////
146// First phase: just collect *trait definitions* -- basically, the set
147// of type parameters and supertraits. This is information we need to
148// know later when parsing field defs.
149
150struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
c34b1796 151 ccx: &'a CrateCtxt<'a, 'tcx>
1a4d82fc
JJ
152}
153
154impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
155 fn visit_item(&mut self, i: &ast::Item) {
156 match i.node {
157 ast::ItemTrait(..) => {
158 // computing the trait def also fills in the table
159 let _ = trait_def_of_item(self.ccx, i);
160 }
161 _ => { }
162 }
163
164 visit::walk_item(self, i);
165 }
166}
167
168///////////////////////////////////////////////////////////////////////////
169// Second phase: collection proper.
170
171struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
c34b1796 172 ccx: &'a CrateCtxt<'a, 'tcx>
1a4d82fc
JJ
173}
174
175impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
176 fn visit_item(&mut self, i: &ast::Item) {
85aaf69f 177 convert_item(self.ccx, i);
1a4d82fc
JJ
178 visit::walk_item(self, i);
179 }
180 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
85aaf69f 181 convert_foreign_item(self.ccx, i);
1a4d82fc
JJ
182 visit::walk_foreign_item(self, i);
183 }
184}
185
186///////////////////////////////////////////////////////////////////////////
187// Utility types and common code for the above passes.
188
c34b1796
AL
189impl<'a,'tcx> CrateCtxt<'a,'tcx> {
190 fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> {
191 ItemCtxt { ccx: self, param_bounds: param_bounds }
192 }
1a4d82fc 193
c34b1796
AL
194 fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
195 let def_id = local_def(method_id);
196 match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() {
197 ty::MethodTraitItem(ref mty) => mty.clone(),
d9579d0f 198 _ => {
c34b1796
AL
199 self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
200 }
201 }
1a4d82fc 202 }
1a4d82fc 203
c34b1796
AL
204 fn cycle_check<F,R>(&self,
205 span: Span,
206 request: AstConvRequest,
207 code: F)
208 -> Result<R,ErrorReported>
209 where F: FnOnce() -> Result<R,ErrorReported>
210 {
211 {
212 let mut stack = self.stack.borrow_mut();
213 match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) {
214 None => { }
215 Some((i, _)) => {
216 let cycle = &stack[i..];
217 self.report_cycle(span, cycle);
218 return Err(ErrorReported);
219 }
220 }
221 stack.push(request);
222 }
1a4d82fc 223
c34b1796
AL
224 let result = code();
225
226 self.stack.borrow_mut().pop();
227 result
228 }
229
230 fn report_cycle(&self,
231 span: Span,
232 cycle: &[AstConvRequest])
233 {
234 assert!(!cycle.is_empty());
235 let tcx = self.tcx;
236
62682a34
SL
237 span_err!(tcx.sess, span, E0391,
238 "unsupported cyclic reference between types/traits detected");
c34b1796
AL
239
240 match cycle[0] {
241 AstConvRequest::GetItemTypeScheme(def_id) |
242 AstConvRequest::GetTraitDef(def_id) => {
243 tcx.sess.note(
244 &format!("the cycle begins when processing `{}`...",
245 ty::item_path_str(tcx, def_id)));
246 }
247 AstConvRequest::EnsureSuperPredicates(def_id) => {
248 tcx.sess.note(
249 &format!("the cycle begins when computing the supertraits of `{}`...",
250 ty::item_path_str(tcx, def_id)));
251 }
252 AstConvRequest::GetTypeParameterBounds(id) => {
253 let def = tcx.type_parameter_def(id);
254 tcx.sess.note(
255 &format!("the cycle begins when computing the bounds \
256 for type parameter `{}`...",
62682a34 257 def.name));
c34b1796
AL
258 }
259 }
260
62682a34 261 for request in &cycle[1..] {
c34b1796
AL
262 match *request {
263 AstConvRequest::GetItemTypeScheme(def_id) |
264 AstConvRequest::GetTraitDef(def_id) => {
265 tcx.sess.note(
266 &format!("...which then requires processing `{}`...",
267 ty::item_path_str(tcx, def_id)));
268 }
269 AstConvRequest::EnsureSuperPredicates(def_id) => {
270 tcx.sess.note(
271 &format!("...which then requires computing the supertraits of `{}`...",
272 ty::item_path_str(tcx, def_id)));
273 }
274 AstConvRequest::GetTypeParameterBounds(id) => {
275 let def = tcx.type_parameter_def(id);
276 tcx.sess.note(
277 &format!("...which then requires computing the bounds \
278 for type parameter `{}`...",
62682a34 279 def.name));
c34b1796
AL
280 }
281 }
1a4d82fc
JJ
282 }
283
c34b1796
AL
284 match cycle[0] {
285 AstConvRequest::GetItemTypeScheme(def_id) |
286 AstConvRequest::GetTraitDef(def_id) => {
287 tcx.sess.note(
288 &format!("...which then again requires processing `{}`, completing the cycle.",
289 ty::item_path_str(tcx, def_id)));
1a4d82fc 290 }
c34b1796
AL
291 AstConvRequest::EnsureSuperPredicates(def_id) => {
292 tcx.sess.note(
293 &format!("...which then again requires computing the supertraits of `{}`, \
294 completing the cycle.",
295 ty::item_path_str(tcx, def_id)));
1a4d82fc 296 }
c34b1796
AL
297 AstConvRequest::GetTypeParameterBounds(id) => {
298 let def = tcx.type_parameter_def(id);
299 tcx.sess.note(
300 &format!("...which then again requires computing the bounds \
301 for type parameter `{}`, completing the cycle.",
62682a34 302 def.name));
1a4d82fc
JJ
303 }
304 }
305 }
306
c34b1796
AL
307 /// Loads the trait def for a given trait, returning ErrorReported if a cycle arises.
308 fn get_trait_def(&self, trait_id: ast::DefId)
d9579d0f 309 -> &'tcx ty::TraitDef<'tcx>
c34b1796
AL
310 {
311 let tcx = self.tcx;
312
313 if trait_id.krate != ast::LOCAL_CRATE {
314 return ty::lookup_trait_def(tcx, trait_id)
315 }
316
317 let item = match tcx.map.get(trait_id.node) {
318 ast_map::NodeItem(item) => item,
62682a34 319 _ => tcx.sess.bug(&format!("get_trait_def({:?}): not an item", trait_id))
c34b1796
AL
320 };
321
322 trait_def_of_item(self, &*item)
323 }
324
325 /// Ensure that the (transitive) super predicates for
326 /// `trait_def_id` are available. This will report a cycle error
327 /// if a trait `X` (transitively) extends itself in some form.
328 fn ensure_super_predicates(&self, span: Span, trait_def_id: ast::DefId)
329 -> Result<(), ErrorReported>
330 {
331 self.cycle_check(span, AstConvRequest::EnsureSuperPredicates(trait_def_id), || {
332 let def_ids = ensure_super_predicates_step(self, trait_def_id);
333
334 for def_id in def_ids {
335 try!(self.ensure_super_predicates(span, def_id));
336 }
337
338 Ok(())
339 })
340 }
341}
342
343impl<'a,'tcx> ItemCtxt<'a,'tcx> {
344 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
345 ast_ty_to_ty(self, rs, ast_ty)
346 }
347}
348
349impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
350 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
351
352 fn get_item_type_scheme(&self, span: Span, id: ast::DefId)
353 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
354 {
355 self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || {
356 Ok(type_scheme_of_def_id(self.ccx, id))
357 })
358 }
359
360 fn get_trait_def(&self, span: Span, id: ast::DefId)
d9579d0f 361 -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
c34b1796
AL
362 {
363 self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || {
364 Ok(self.ccx.get_trait_def(id))
365 })
366 }
367
368 fn ensure_super_predicates(&self,
369 span: Span,
370 trait_def_id: ast::DefId)
371 -> Result<(), ErrorReported>
372 {
62682a34
SL
373 debug!("ensure_super_predicates(trait_def_id={:?})",
374 trait_def_id);
c34b1796
AL
375
376 self.ccx.ensure_super_predicates(span, trait_def_id)
377 }
378
379
380 fn get_type_parameter_bounds(&self,
381 span: Span,
382 node_id: ast::NodeId)
383 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
384 {
385 self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || {
386 let v = self.param_bounds.get_type_parameter_bounds(self, span, node_id)
387 .into_iter()
388 .filter_map(|p| p.to_opt_poly_trait_ref())
389 .collect();
390 Ok(v)
391 })
392 }
393
394 fn trait_defines_associated_type_named(&self,
395 trait_def_id: ast::DefId,
396 assoc_name: ast::Name)
397 -> bool
398 {
399 if trait_def_id.krate == ast::LOCAL_CRATE {
400 trait_defines_associated_type_named(self.ccx, trait_def_id.node, assoc_name)
401 } else {
402 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
403 trait_def.associated_type_names.contains(&assoc_name)
404 }
1a4d82fc
JJ
405 }
406
407 fn ty_infer(&self, span: Span) -> Ty<'tcx> {
85aaf69f 408 span_err!(self.tcx().sess, span, E0121,
1a4d82fc
JJ
409 "the type placeholder `_` is not allowed within types on item signatures");
410 self.tcx().types.err
411 }
412
413 fn projected_ty(&self,
414 _span: Span,
d9579d0f 415 trait_ref: ty::TraitRef<'tcx>,
1a4d82fc
JJ
416 item_name: ast::Name)
417 -> Ty<'tcx>
418 {
85aaf69f 419 ty::mk_projection(self.tcx(), trait_ref, item_name)
1a4d82fc
JJ
420 }
421}
422
c34b1796
AL
423/// Interface used to find the bounds on a type parameter from within
424/// an `ItemCtxt`. This allows us to use multiple kinds of sources.
425trait GetTypeParameterBounds<'tcx> {
426 fn get_type_parameter_bounds(&self,
427 astconv: &AstConv<'tcx>,
428 span: Span,
429 node_id: ast::NodeId)
430 -> Vec<ty::Predicate<'tcx>>;
431}
432
433/// Find bounds from both elements of the tuple.
434impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
435 where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx>
436{
437 fn get_type_parameter_bounds(&self,
438 astconv: &AstConv<'tcx>,
439 span: Span,
440 node_id: ast::NodeId)
441 -> Vec<ty::Predicate<'tcx>>
442 {
443 let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id);
62682a34 444 v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id));
c34b1796
AL
445 v
446 }
447}
448
449/// Empty set of bounds.
450impl<'tcx> GetTypeParameterBounds<'tcx> for () {
451 fn get_type_parameter_bounds(&self,
452 _astconv: &AstConv<'tcx>,
453 _span: Span,
454 _node_id: ast::NodeId)
455 -> Vec<ty::Predicate<'tcx>>
456 {
457 Vec::new()
458 }
459}
460
461/// Find bounds from the parsed and converted predicates. This is
462/// used when converting methods, because by that time the predicates
463/// from the trait/impl have been fully converted.
464impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
465 fn get_type_parameter_bounds(&self,
466 astconv: &AstConv<'tcx>,
467 _span: Span,
468 node_id: ast::NodeId)
469 -> Vec<ty::Predicate<'tcx>>
470 {
471 let def = astconv.tcx().type_parameter_def(node_id);
472
473 self.predicates
474 .iter()
475 .filter(|predicate| {
476 match **predicate {
477 ty::Predicate::Trait(ref data) => {
478 data.skip_binder().self_ty().is_param(def.space, def.index)
479 }
480 ty::Predicate::TypeOutlives(ref data) => {
481 data.skip_binder().0.is_param(def.space, def.index)
482 }
483 ty::Predicate::Equate(..) |
484 ty::Predicate::RegionOutlives(..) |
485 ty::Predicate::Projection(..) => {
486 false
487 }
488 }
489 })
490 .cloned()
491 .collect()
492 }
493}
494
495/// Find bounds from ast::Generics. This requires scanning through the
496/// AST. We do this to avoid having to convert *all* the bounds, which
497/// would create artificial cycles. Instead we can only convert the
498/// bounds for those a type parameter `X` if `X::Foo` is used.
499impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
500 fn get_type_parameter_bounds(&self,
501 astconv: &AstConv<'tcx>,
502 _: Span,
503 node_id: ast::NodeId)
504 -> Vec<ty::Predicate<'tcx>>
505 {
506 // In the AST, bounds can derive from two places. Either
507 // written inline like `<T:Foo>` or in a where clause like
508 // `where T:Foo`.
509
510 let def = astconv.tcx().type_parameter_def(node_id);
511 let ty = ty::mk_param_from_def(astconv.tcx(), &def);
512
513 let from_ty_params =
514 self.ty_params
515 .iter()
516 .filter(|p| p.id == node_id)
517 .flat_map(|p| p.bounds.iter())
62682a34 518 .flat_map(|b| predicates_from_bound(astconv, ty, b));
c34b1796
AL
519
520 let from_where_clauses =
521 self.where_clause
522 .predicates
523 .iter()
524 .filter_map(|wp| match *wp {
525 ast::WherePredicate::BoundPredicate(ref bp) => Some(bp),
526 _ => None
527 })
528 .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
529 .flat_map(|bp| bp.bounds.iter())
62682a34 530 .flat_map(|b| predicates_from_bound(astconv, ty, b));
c34b1796
AL
531
532 from_ty_params.chain(from_where_clauses).collect()
533 }
534}
535
536/// Tests whether this is the AST for a reference to the type
537/// parameter with id `param_id`. We use this so as to avoid running
538/// `ast_ty_to_ty`, because we want to avoid triggering an all-out
539/// conversion of the type to avoid inducing unnecessary cycles.
540fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
541 ast_ty: &ast::Ty,
542 param_id: ast::NodeId)
543 -> bool
544{
545 if let ast::TyPath(None, _) = ast_ty.node {
546 let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
547 match path_res.base_def {
9346a6ac
AL
548 def::DefSelfTy(Some(def_id), None) => {
549 path_res.depth == 0 && def_id.node == param_id
550 }
551 def::DefTyParam(_, _, def_id, _) => {
552 path_res.depth == 0 && def_id == local_def(param_id)
553 }
554 _ => {
555 false
556 }
c34b1796
AL
557 }
558 } else {
559 false
560 }
561}
562
563fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
564 enum_scheme: ty::TypeScheme<'tcx>,
565 enum_predicates: ty::GenericPredicates<'tcx>,
566 variants: &[P<ast::Variant>]) {
1a4d82fc 567 let tcx = ccx.tcx;
c34b1796 568 let icx = ccx.icx(&enum_predicates);
1a4d82fc
JJ
569
570 // Create a set of parameter types shared among all the variants.
85aaf69f 571 for variant in variants {
1a4d82fc
JJ
572 let variant_def_id = local_def(variant.node.id);
573
574 // Nullary enum constructors get turned into constants; n-ary enum
575 // constructors get turned into functions.
576 let result_ty = match variant.node.kind {
9346a6ac 577 ast::TupleVariantKind(ref args) if !args.is_empty() => {
1a4d82fc 578 let rs = ExplicitRscope;
c34b1796
AL
579 let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
580 ty::mk_ctor_fn(tcx, variant_def_id, &input_tys, enum_scheme.ty)
1a4d82fc
JJ
581 }
582
583 ast::TupleVariantKind(_) => {
85aaf69f 584 enum_scheme.ty
1a4d82fc
JJ
585 }
586
587 ast::StructVariantKind(ref struct_def) => {
85aaf69f
SL
588 convert_struct(ccx, &**struct_def, enum_scheme.clone(),
589 enum_predicates.clone(), variant.node.id);
590 enum_scheme.ty
1a4d82fc
JJ
591 }
592 };
593
85aaf69f
SL
594 let variant_scheme = TypeScheme {
595 generics: enum_scheme.generics.clone(),
1a4d82fc
JJ
596 ty: result_ty
597 };
598
85aaf69f
SL
599 tcx.tcache.borrow_mut().insert(variant_def_id, variant_scheme.clone());
600 tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
1a4d82fc
JJ
601 write_ty_to_tcx(tcx, variant.node.id, result_ty);
602 }
603}
604
c34b1796
AL
605fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
606 container: ImplOrTraitItemContainer,
607 sig: &ast::MethodSig,
608 id: ast::NodeId,
609 ident: ast::Ident,
610 vis: ast::Visibility,
611 untransformed_rcvr_ty: Ty<'tcx>,
612 rcvr_ty_generics: &ty::Generics<'tcx>,
613 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
614 let ty_generics = ty_generics_for_fn(ccx, &sig.generics, rcvr_ty_generics);
615
616 let ty_generic_predicates =
617 ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
618
619 let (fty, explicit_self_category) =
620 astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
621 sig, untransformed_rcvr_ty);
622
623 let def_id = local_def(id);
624 let ty_method = ty::Method::new(ident.name,
625 ty_generics,
626 ty_generic_predicates,
627 fty,
628 explicit_self_category,
629 vis,
630 def_id,
631 container,
632 None);
633
634 let fty = ty::mk_bare_fn(ccx.tcx, Some(def_id),
635 ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
62682a34
SL
636 debug!("method {} (id {}) has type {:?}",
637 ident, id, fty);
c34b1796
AL
638 ccx.tcx.tcache.borrow_mut().insert(def_id,TypeScheme {
639 generics: ty_method.generics.clone(),
640 ty: fty
641 });
642 ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
1a4d82fc 643
c34b1796 644 write_ty_to_tcx(ccx.tcx, id, fty);
1a4d82fc 645
62682a34
SL
646 debug!("writing method type: def_id={:?} mty={:?}",
647 def_id, ty_method);
1a4d82fc 648
c34b1796
AL
649 ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id,
650 ty::MethodTraitItem(Rc::new(ty_method)));
1a4d82fc
JJ
651}
652
c34b1796
AL
653fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
654 struct_generics: &ty::Generics<'tcx>,
655 struct_predicates: &ty::GenericPredicates<'tcx>,
656 v: &ast::StructField,
657 origin: ast::DefId)
658 -> ty::field_ty
659{
660 let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
1a4d82fc 661 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
85aaf69f 662
1a4d82fc
JJ
663 /* add the field to the tcache */
664 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
665 ty::TypeScheme {
666 generics: struct_generics.clone(),
667 ty: tt
668 });
85aaf69f
SL
669 ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
670 struct_predicates.clone());
1a4d82fc
JJ
671
672 match v.node.kind {
673 ast::NamedField(ident, visibility) => {
674 ty::field_ty {
675 name: ident.name,
676 id: local_def(v.node.id),
677 vis: visibility,
678 origin: origin,
679 }
680 }
681 ast::UnnamedField(visibility) => {
682 ty::field_ty {
683 name: special_idents::unnamed_field.name,
684 id: local_def(v.node.id),
685 vis: visibility,
686 origin: origin,
687 }
688 }
689 }
690}
691
d9579d0f
AL
692fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
693 container: ImplOrTraitItemContainer,
694 ident: ast::Ident,
695 id: ast::NodeId,
696 vis: ast::Visibility,
697 ty: ty::Ty<'tcx>,
698 default: Option<&ast::Expr>)
699{
700 ccx.tcx.predicates.borrow_mut().insert(local_def(id),
701 ty::GenericPredicates::empty());
702
703 write_ty_to_tcx(ccx.tcx, id, ty);
704 let default_id = default.map(|expr| local_def(expr.id));
705
706 let associated_const = Rc::new(ty::AssociatedConst {
707 name: ident.name,
708 vis: vis,
709 def_id: local_def(id),
710 container: container,
711 ty: ty,
712 default: default_id,
713 });
714 ccx.tcx.impl_or_trait_items.borrow_mut()
715 .insert(local_def(id), ty::ConstTraitItem(associated_const));
716}
717
62682a34
SL
718fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
719 container: ImplOrTraitItemContainer,
720 ident: ast::Ident,
721 id: ast::NodeId,
722 vis: ast::Visibility,
723 ty: Option<Ty<'tcx>>)
1a4d82fc
JJ
724{
725 let associated_type = Rc::new(ty::AssociatedType {
c34b1796
AL
726 name: ident.name,
727 vis: vis,
62682a34 728 ty: ty,
c34b1796
AL
729 def_id: local_def(id),
730 container: container
1a4d82fc 731 });
c34b1796
AL
732 ccx.tcx.impl_or_trait_items.borrow_mut()
733 .insert(local_def(id), ty::TypeTraitItem(associated_type));
1a4d82fc
JJ
734}
735
c34b1796 736fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 737 container: ImplOrTraitItemContainer,
c34b1796 738 methods: I,
1a4d82fc
JJ
739 untransformed_rcvr_ty: Ty<'tcx>,
740 rcvr_ty_generics: &ty::Generics<'tcx>,
c34b1796
AL
741 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>)
742 where I: Iterator<Item=(&'i ast::MethodSig, ast::NodeId, ast::Ident, ast::Visibility, Span)>
743{
62682a34
SL
744 debug!("convert_methods(untransformed_rcvr_ty={:?}, rcvr_ty_generics={:?}, \
745 rcvr_ty_predicates={:?})",
746 untransformed_rcvr_ty,
747 rcvr_ty_generics,
748 rcvr_ty_predicates);
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) {
62682a34
SL
754 let fn_desc = match sig.explicit_self.node {
755 ast::SelfStatic => "associated function",
756 _ => "method",
757 };
758 span_err!(tcx.sess, span, E0201, "duplicate {}", fn_desc);
1a4d82fc
JJ
759 }
760
c34b1796
AL
761 convert_method(ccx,
762 container,
763 sig,
764 id,
765 ident,
766 vis,
767 untransformed_rcvr_ty,
768 rcvr_ty_generics,
769 rcvr_ty_predicates);
1a4d82fc
JJ
770 }
771}
772
c34b1796 773fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
1a4d82fc
JJ
774 span: Span,
775 generics: &ast::Generics,
776 thing: &'static str) {
777 let mut warn = false;
778
62682a34
SL
779 for ty_param in generics.ty_params.iter() {
780 for bound in ty_param.bounds.iter() {
1a4d82fc
JJ
781 match *bound {
782 ast::TraitTyParamBound(..) => {
783 warn = true;
784 }
785 ast::RegionTyParamBound(..) => { }
786 }
787 }
788 }
789
790 if warn {
791 // According to accepted RFC #XXX, we should
792 // eventually accept these, but it will not be
793 // part of this PR. Still, convert to warning to
794 // make bootstrapping easier.
795 span_warn!(ccx.tcx.sess, span, E0122,
796 "trait bounds are not (yet) enforced \
797 in {} definitions",
798 thing);
799 }
800}
801
c34b1796 802fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
1a4d82fc
JJ
803 let tcx = ccx.tcx;
804 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
805 match it.node {
806 // These don't define types.
85aaf69f
SL
807 ast::ItemExternCrate(_) | ast::ItemUse(_) |
808 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {
809 }
810 ast::ItemEnum(ref enum_definition, _) => {
811 let (scheme, predicates) = convert_typed_item(ccx, it);
1a4d82fc
JJ
812 write_ty_to_tcx(tcx, it.id, scheme.ty);
813 get_enum_variant_types(ccx,
85aaf69f
SL
814 scheme,
815 predicates,
816 &enum_definition.variants);
1a4d82fc 817 },
c34b1796
AL
818 ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
819 let trait_ref =
820 astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
821 &ExplicitRscope,
822 ast_trait_ref,
823 None);
824
825 ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
826
62682a34 827 tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), Some(trait_ref));
c34b1796 828 }
1a4d82fc
JJ
829 ast::ItemImpl(_, _,
830 ref generics,
831 ref opt_trait_ref,
832 ref selfty,
833 ref impl_items) => {
834 // Create generics from the generics specified in the impl head.
85aaf69f 835 debug!("convert: ast_generics={:?}", generics);
1a4d82fc 836 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
c34b1796 837 let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
85aaf69f
SL
838
839 debug!("convert: impl_bounds={:?}", ty_predicates);
1a4d82fc 840
c34b1796 841 let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
1a4d82fc
JJ
842 write_ty_to_tcx(tcx, it.id, selfty);
843
85aaf69f
SL
844 tcx.tcache.borrow_mut().insert(local_def(it.id),
845 TypeScheme { generics: ty_generics.clone(),
846 ty: selfty });
847 tcx.predicates.borrow_mut().insert(local_def(it.id),
848 ty_predicates.clone());
1a4d82fc
JJ
849
850 // If there is a trait reference, treat the methods as always public.
851 // This is to work around some incorrect behavior in privacy checking:
852 // when the method belongs to a trait, it should acquire the privacy
853 // from the trait, not the impl. Forcing the visibility to be public
854 // makes things sorta work.
855 let parent_visibility = if opt_trait_ref.is_some() {
856 ast::Public
857 } else {
858 it.vis
859 };
860
d9579d0f 861 // Convert all the associated consts.
85aaf69f 862 for impl_item in impl_items {
d9579d0f
AL
863 if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
864 let ty = ccx.icx(&ty_predicates)
865 .to_ty(&ExplicitRscope, &*ty);
866 tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
867 TypeScheme {
868 generics: ty_generics.clone(),
869 ty: ty,
870 });
871 convert_associated_const(ccx, ImplContainer(local_def(it.id)),
872 impl_item.ident, impl_item.id,
873 impl_item.vis.inherit_from(parent_visibility),
874 ty, Some(&*expr));
875 }
876 }
c34b1796 877
d9579d0f
AL
878 // Convert all the associated types.
879 for impl_item in impl_items {
880 if let ast::TypeImplItem(ref ty) = impl_item.node {
881 if opt_trait_ref.is_none() {
882 span_err!(tcx.sess, impl_item.span, E0202,
62682a34 883 "associated types are not allowed in inherent impls");
1a4d82fc 884 }
d9579d0f 885
d9579d0f 886 let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
62682a34
SL
887
888 convert_associated_type(ccx, ImplContainer(local_def(it.id)),
889 impl_item.ident, impl_item.id, impl_item.vis,
890 Some(typ));
1a4d82fc
JJ
891 }
892 }
893
c34b1796 894 let methods = impl_items.iter().filter_map(|ii| {
d9579d0f
AL
895 if let ast::MethodImplItem(ref sig, _) = ii.node {
896 // if the method specifies a visibility, use that, otherwise
897 // inherit the visibility from the impl (so `foo` in `pub impl
898 // { fn foo(); }` is public, but private in `impl { fn
899 // foo(); }`).
900 let method_vis = ii.vis.inherit_from(parent_visibility);
901 Some((sig, ii.id, ii.ident, method_vis, ii.span))
902 } else {
903 None
c34b1796
AL
904 }
905 });
1a4d82fc
JJ
906 convert_methods(ccx,
907 ImplContainer(local_def(it.id)),
c34b1796 908 methods,
1a4d82fc
JJ
909 selfty,
910 &ty_generics,
c34b1796
AL
911 &ty_predicates);
912
913 for impl_item in impl_items {
d9579d0f
AL
914 if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
915 let body_id = body.id;
916 check_method_self_type(ccx,
917 &BindingRscope::new(),
918 ccx.method_ty(impl_item.id),
919 selfty,
920 &sig.explicit_self,
921 body_id);
c34b1796
AL
922 }
923 }
924
62682a34
SL
925 if let &Some(ref ast_trait_ref) = opt_trait_ref {
926 tcx.impl_trait_refs.borrow_mut().insert(
927 local_def(it.id),
928 Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
929 &ExplicitRscope,
930 ast_trait_ref,
931 Some(selfty)))
932 );
933 } else {
934 tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), None);
1a4d82fc
JJ
935 }
936
9346a6ac
AL
937 enforce_impl_params_are_constrained(tcx,
938 generics,
939 local_def(it.id),
940 impl_items);
1a4d82fc 941 },
c34b1796 942 ast::ItemTrait(_, _, _, ref trait_items) => {
1a4d82fc 943 let trait_def = trait_def_of_item(ccx, it);
c34b1796
AL
944 let _: Result<(), ErrorReported> = // any error is already reported, can ignore
945 ccx.ensure_super_predicates(it.span, local_def(it.id));
85aaf69f 946 convert_trait_predicates(ccx, it);
c34b1796 947 let trait_predicates = ty::lookup_predicates(tcx, local_def(it.id));
1a4d82fc 948
85aaf69f 949 debug!("convert: trait_bounds={:?}", trait_predicates);
1a4d82fc 950
c34b1796
AL
951 // Convert all the associated types.
952 for trait_item in trait_items {
953 match trait_item.node {
d9579d0f
AL
954 ast::ConstTraitItem(ref ty, ref default) => {
955 let ty = ccx.icx(&trait_predicates)
956 .to_ty(&ExplicitRscope, ty);
957 tcx.tcache.borrow_mut().insert(local_def(trait_item.id),
958 TypeScheme {
959 generics: trait_def.generics.clone(),
960 ty: ty,
961 });
962 convert_associated_const(ccx, TraitContainer(local_def(it.id)),
963 trait_item.ident, trait_item.id,
964 ast::Public, ty, default.as_ref().map(|d| &**d));
965 }
966 _ => {}
967 }
968 };
969
970 // Convert all the associated types.
971 for trait_item in trait_items {
972 match trait_item.node {
62682a34
SL
973 ast::TypeTraitItem(_, ref opt_ty) => {
974 let typ = opt_ty.as_ref().map({
975 |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
976 });
977
978 convert_associated_type(ccx, TraitContainer(local_def(it.id)),
979 trait_item.ident, trait_item.id, ast::Public,
980 typ);
1a4d82fc 981 }
d9579d0f 982 _ => {}
1a4d82fc 983 }
c34b1796
AL
984 };
985
986 let methods = trait_items.iter().filter_map(|ti| {
987 let sig = match ti.node {
988 ast::MethodTraitItem(ref sig, _) => sig,
d9579d0f 989 _ => return None,
c34b1796
AL
990 };
991 Some((sig, ti.id, ti.ident, ast::Inherited, ti.span))
992 });
1a4d82fc 993
c34b1796 994 // Run convert_methods on the trait methods.
1a4d82fc
JJ
995 convert_methods(ccx,
996 TraitContainer(local_def(it.id)),
c34b1796
AL
997 methods,
998 ty::mk_self_type(tcx),
1a4d82fc 999 &trait_def.generics,
c34b1796 1000 &trait_predicates);
1a4d82fc 1001
c34b1796
AL
1002 // Add an entry mapping
1003 let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
1004 let def_id = local_def(trait_item.id);
1005 match trait_item.node {
d9579d0f
AL
1006 ast::ConstTraitItem(..) => {
1007 ty::ConstTraitItemId(def_id)
1008 }
c34b1796
AL
1009 ast::MethodTraitItem(..) => {
1010 ty::MethodTraitItemId(def_id)
1011 }
1012 ast::TypeTraitItem(..) => {
1013 ty::TypeTraitItemId(def_id)
1014 }
1015 }
1016 }).collect());
1017 tcx.trait_item_def_ids.borrow_mut().insert(local_def(it.id), trait_item_def_ids);
1018
1019 // This must be done after `collect_trait_methods` so that
1020 // we have a method type stored for every method.
1021 for trait_item in trait_items {
1022 let sig = match trait_item.node {
1023 ast::MethodTraitItem(ref sig, _) => sig,
d9579d0f 1024 _ => continue
c34b1796
AL
1025 };
1026 check_method_self_type(ccx,
1027 &BindingRscope::new(),
1028 ccx.method_ty(trait_item.id),
1029 ty::mk_self_type(tcx),
1030 &sig.explicit_self,
1031 it.id)
1032 }
1a4d82fc
JJ
1033 },
1034 ast::ItemStruct(ref struct_def, _) => {
1035 // Write the class type.
85aaf69f 1036 let (scheme, predicates) = convert_typed_item(ccx, it);
1a4d82fc 1037 write_ty_to_tcx(tcx, it.id, scheme.ty);
85aaf69f 1038 convert_struct(ccx, &**struct_def, scheme, predicates, it.id);
1a4d82fc
JJ
1039 },
1040 ast::ItemTy(_, ref generics) => {
1041 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
85aaf69f
SL
1042 let (scheme, _) = convert_typed_item(ccx, it);
1043 write_ty_to_tcx(tcx, it.id, scheme.ty);
1a4d82fc
JJ
1044 },
1045 _ => {
1046 // This call populates the type cache with the converted type
1047 // of the item in passing. All we have to do here is to write
1048 // it into the node type table.
85aaf69f 1049 let (scheme, _) = convert_typed_item(ccx, it);
1a4d82fc
JJ
1050 write_ty_to_tcx(tcx, it.id, scheme.ty);
1051 },
1052 }
1053}
1054
c34b1796 1055fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1056 struct_def: &ast::StructDef,
1057 scheme: ty::TypeScheme<'tcx>,
1058 predicates: ty::GenericPredicates<'tcx>,
1059 id: ast::NodeId) {
1a4d82fc
JJ
1060 let tcx = ccx.tcx;
1061
1062 // Write the type of each of the members and check for duplicate fields.
85aaf69f 1063 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
1a4d82fc 1064 let field_tys = struct_def.fields.iter().map(|f| {
85aaf69f 1065 let result = convert_field(ccx, &scheme.generics, &predicates, f, local_def(id));
1a4d82fc
JJ
1066
1067 if result.name != special_idents::unnamed_field.name {
1068 let dup = match seen_fields.get(&result.name) {
1069 Some(prev_span) => {
1070 span_err!(tcx.sess, f.span, E0124,
1071 "field `{}` is already declared",
1072 token::get_name(result.name));
1073 span_note!(tcx.sess, *prev_span, "previously declared here");
1074 true
1075 },
1076 None => false,
1077 };
1078 // FIXME(#6393) this whole dup thing is just to satisfy
1079 // the borrow checker :-(
1080 if !dup {
1081 seen_fields.insert(result.name, f.span);
1082 }
1083 }
1084
1085 result
1086 }).collect();
1087
1088 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
1089
1090 let substs = mk_item_substs(ccx, &scheme.generics);
1091 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
1092
1093 // If this struct is enum-like or tuple-like, create the type of its
1094 // constructor.
1095 match struct_def.ctor_id {
1096 None => {}
1097 Some(ctor_id) => {
9346a6ac 1098 if struct_def.fields.is_empty() {
1a4d82fc
JJ
1099 // Enum-like.
1100 write_ty_to_tcx(tcx, ctor_id, selfty);
1101
1102 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
85aaf69f 1103 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1a4d82fc
JJ
1104 } else if struct_def.fields[0].node.kind.is_unnamed() {
1105 // Tuple-like.
c34b1796
AL
1106 let inputs: Vec<_> =
1107 struct_def.fields
1108 .iter()
1109 .map(|field| tcx.tcache.borrow().get(&local_def(field.node.id))
1110 .unwrap()
1111 .ty)
1112 .collect();
1a4d82fc
JJ
1113 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
1114 local_def(ctor_id),
85aaf69f 1115 &inputs[..],
1a4d82fc
JJ
1116 selfty);
1117 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
1118 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
85aaf69f
SL
1119 TypeScheme {
1120 generics: scheme.generics,
1121 ty: ctor_fn_ty
1122 });
1123 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1a4d82fc
JJ
1124 }
1125 }
1126 }
1127}
1128
c34b1796
AL
1129/// Ensures that the super-predicates of the trait with def-id
1130/// trait_def_id are converted and stored. This does NOT ensure that
1131/// the transitive super-predicates are converted; that is the job of
1132/// the `ensure_super_predicates()` method in the `AstConv` impl
1133/// above. Returns a list of trait def-ids that must be ensured as
1134/// well to guarantee that the transitive superpredicates are
1135/// converted.
1136fn ensure_super_predicates_step(ccx: &CrateCtxt,
1137 trait_def_id: ast::DefId)
1138 -> Vec<ast::DefId>
1139{
85aaf69f
SL
1140 let tcx = ccx.tcx;
1141
62682a34 1142 debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id);
1a4d82fc 1143
c34b1796
AL
1144 if trait_def_id.krate != ast::LOCAL_CRATE {
1145 // If this trait comes from an external crate, then all of the
1146 // supertraits it may depend on also must come from external
1147 // crates, and hence all of them already have their
1148 // super-predicates "converted" (and available from crate
1149 // meta-data), so there is no need to transitively test them.
1150 return Vec::new();
1a4d82fc 1151 }
c34b1796
AL
1152
1153 let superpredicates = tcx.super_predicates.borrow().get(&trait_def_id).cloned();
1154 let superpredicates = superpredicates.unwrap_or_else(|| {
1155 let trait_node_id = trait_def_id.node;
1156
1157 let item = match ccx.tcx.map.get(trait_node_id) {
1158 ast_map::NodeItem(item) => item,
1159 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1160 };
1161
1162 let (generics, bounds) = match item.node {
1163 ast::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
1164 _ => tcx.sess.span_bug(item.span,
1165 "ensure_super_predicates_step invoked on non-trait"),
1166 };
1167
1168 // In-scope when converting the superbounds for `Trait` are
1169 // that `Self:Trait` as well as any bounds that appear on the
1170 // generic types:
1171 let trait_def = trait_def_of_item(ccx, item);
1172 let self_predicate = ty::GenericPredicates {
1173 predicates: VecPerParamSpace::new(vec![],
1174 vec![trait_def.trait_ref.as_predicate()],
1175 vec![])
1176 };
1177 let scope = &(generics, &self_predicate);
1178
1179 // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
1180 let self_param_ty = ty::mk_self_type(tcx);
62682a34
SL
1181 let superbounds1 = compute_bounds(&ccx.icx(scope),
1182 self_param_ty,
1183 bounds,
1184 SizedByDefault::No,
1185 item.span);
1186
1187 let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
c34b1796
AL
1188
1189 // Convert any explicit superbounds in the where clause,
1190 // e.g. `trait Foo where Self : Bar`:
1191 let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id);
1192
1193 // Combine the two lists to form the complete set of superbounds:
62682a34 1194 let superbounds = superbounds1.into_iter().chain(superbounds2).collect();
c34b1796
AL
1195 let superpredicates = ty::GenericPredicates {
1196 predicates: VecPerParamSpace::new(superbounds, vec![], vec![])
1197 };
62682a34
SL
1198 debug!("superpredicates for trait {:?} = {:?}",
1199 local_def(item.id),
1200 superpredicates);
c34b1796
AL
1201
1202 tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
1203
1204 superpredicates
1205 });
1206
1207 let def_ids: Vec<_> = superpredicates.predicates
1208 .iter()
1209 .filter_map(|p| p.to_opt_poly_trait_ref())
1210 .map(|tr| tr.def_id())
1211 .collect();
1212
62682a34 1213 debug!("ensure_super_predicates_step: def_ids={:?}", def_ids);
c34b1796
AL
1214
1215 def_ids
1a4d82fc
JJ
1216}
1217
c34b1796 1218fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 1219 it: &ast::Item)
d9579d0f 1220 -> &'tcx ty::TraitDef<'tcx>
1a4d82fc
JJ
1221{
1222 let def_id = local_def(it.id);
1223 let tcx = ccx.tcx;
85aaf69f 1224
1a4d82fc
JJ
1225 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
1226 return def.clone();
1227 }
1228
c34b1796
AL
1229 let (unsafety, generics, items) = match it.node {
1230 ast::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
1231 _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"),
1a4d82fc
JJ
1232 };
1233
85aaf69f
SL
1234 let paren_sugar = ty::has_attr(tcx, def_id, "rustc_paren_sugar");
1235 if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
1236 ccx.tcx.sess.span_err(
1237 it.span,
1238 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
1239 which traits can use parenthetical notation");
c34b1796 1240 fileline_help!(ccx.tcx.sess, it.span,
85aaf69f
SL
1241 "add `#![feature(unboxed_closures)]` to \
1242 the crate attributes to use it");
1243 }
1244
1a4d82fc
JJ
1245 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
1246
85aaf69f 1247 let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics);
1a4d82fc 1248
c34b1796
AL
1249 let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
1250 match trait_item.node {
c34b1796 1251 ast::TypeTraitItem(..) => Some(trait_item.ident.name),
d9579d0f 1252 _ => None,
c34b1796
AL
1253 }
1254 }).collect();
1a4d82fc 1255
d9579d0f 1256 let trait_ref = ty::TraitRef {
1a4d82fc 1257 def_id: def_id,
85aaf69f 1258 substs: substs,
d9579d0f 1259 };
1a4d82fc 1260
d9579d0f 1261 let trait_def = ty::TraitDef {
85aaf69f 1262 paren_sugar: paren_sugar,
1a4d82fc
JJ
1263 unsafety: unsafety,
1264 generics: ty_generics,
1a4d82fc
JJ
1265 trait_ref: trait_ref,
1266 associated_type_names: associated_type_names,
d9579d0f
AL
1267 nonblanket_impls: RefCell::new(FnvHashMap()),
1268 blanket_impls: RefCell::new(vec![]),
1269 flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS)
1270 };
1a4d82fc 1271
d9579d0f 1272 return tcx.intern_trait_def(trait_def);
1a4d82fc 1273
c34b1796 1274 fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 1275 generics: &ast::Generics)
c34b1796 1276 -> Substs<'tcx>
1a4d82fc 1277 {
85aaf69f
SL
1278 let tcx = ccx.tcx;
1279
1a4d82fc
JJ
1280 // Creates a no-op substitution for the trait's type parameters.
1281 let regions =
1282 generics.lifetimes
1283 .iter()
1284 .enumerate()
9346a6ac
AL
1285 .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
1286 param_id: def.lifetime.id,
1287 space: TypeSpace,
1288 index: i as u32,
1289 name: def.lifetime.name
1290 }))
1a4d82fc
JJ
1291 .collect();
1292
1293 // Start with the generics in the type parameters...
1294 let types: Vec<_> =
1295 generics.ty_params
1296 .iter()
1297 .enumerate()
c34b1796 1298 .map(|(i, def)| ty::mk_param(tcx, TypeSpace,
1a4d82fc
JJ
1299 i as u32, def.ident.name))
1300 .collect();
1301
1302 // ...and also create the `Self` parameter.
85aaf69f 1303 let self_ty = ty::mk_self_type(tcx);
1a4d82fc 1304
c34b1796 1305 Substs::new_trait(types, regions, self_ty)
1a4d82fc
JJ
1306 }
1307}
1308
c34b1796
AL
1309fn trait_defines_associated_type_named(ccx: &CrateCtxt,
1310 trait_node_id: ast::NodeId,
1311 assoc_name: ast::Name)
1312 -> bool
1313{
1314 let item = match ccx.tcx.map.get(trait_node_id) {
1315 ast_map::NodeItem(item) => item,
1316 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1317 };
1318
1319 let trait_items = match item.node {
1320 ast::ItemTrait(_, _, _, ref trait_items) => trait_items,
1321 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id))
1322 };
1323
1324 trait_items.iter().any(|trait_item| {
1325 match trait_item.node {
1326 ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
d9579d0f 1327 _ => false,
c34b1796
AL
1328 }
1329 })
1330}
1331
1332fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
1a4d82fc 1333 let tcx = ccx.tcx;
85aaf69f
SL
1334 let trait_def = trait_def_of_item(ccx, it);
1335
1336 let def_id = local_def(it.id);
1337
1338 let (generics, items) = match it.node {
1339 ast::ItemTrait(_, ref generics, _, ref items) => (generics, items),
1340 ref s => {
1341 tcx.sess.span_bug(
1342 it.span,
c34b1796 1343 &format!("trait_def_of_item invoked on {:?}", s));
85aaf69f
SL
1344 }
1345 };
1346
c34b1796 1347 let super_predicates = ty::lookup_super_predicates(ccx.tcx, def_id);
85aaf69f 1348
c34b1796 1349 // `ty_generic_predicates` below will consider the bounds on the type
85aaf69f
SL
1350 // parameters (including `Self`) and the explicit where-clauses,
1351 // but to get the full set of predicates on a trait we need to add
1352 // in the supertrait bounds and anything declared on the
1353 // associated types.
c34b1796 1354 let mut base_predicates = super_predicates;
85aaf69f 1355
c34b1796
AL
1356 // Add in a predicate that `Self:Trait` (where `Trait` is the
1357 // current trait). This is needed for builtin bounds.
1358 let self_predicate = trait_def.trait_ref.to_poly_trait_ref().as_predicate();
1359 base_predicates.predicates.push(SelfSpace, self_predicate);
85aaf69f
SL
1360
1361 // add in the explicit where-clauses
c34b1796
AL
1362 let mut trait_predicates =
1363 ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
1364
1365 let assoc_predicates = predicates_for_associated_types(ccx,
1366 generics,
1367 &trait_predicates,
d9579d0f 1368 trait_def.trait_ref,
c34b1796
AL
1369 items);
1370 trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
85aaf69f
SL
1371
1372 let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
1373 assert!(prev_predicates.is_none());
1374
1375 return;
1376
c34b1796
AL
1377 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1378 ast_generics: &ast::Generics,
1379 trait_predicates: &ty::GenericPredicates<'tcx>,
d9579d0f 1380 self_trait_ref: ty::TraitRef<'tcx>,
c34b1796 1381 trait_items: &[P<ast::TraitItem>])
85aaf69f
SL
1382 -> Vec<ty::Predicate<'tcx>>
1383 {
c34b1796
AL
1384 trait_items.iter().flat_map(|trait_item| {
1385 let bounds = match trait_item.node {
1386 ast::TypeTraitItem(ref bounds, _) => bounds,
d9579d0f 1387 _ => {
c34b1796
AL
1388 return vec!().into_iter();
1389 }
1390 };
85aaf69f 1391
c34b1796 1392 let assoc_ty = ty::mk_projection(ccx.tcx,
d9579d0f 1393 self_trait_ref,
c34b1796 1394 trait_item.ident.name);
85aaf69f 1395
c34b1796
AL
1396 let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
1397 assoc_ty,
1398 bounds,
1399 SizedByDefault::Yes,
1400 trait_item.span);
85aaf69f 1401
62682a34 1402 bounds.predicates(ccx.tcx, assoc_ty).into_iter()
c34b1796 1403 }).collect()
1a4d82fc 1404 }
85aaf69f
SL
1405}
1406
c34b1796
AL
1407fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1408 def_id: ast::DefId)
1409 -> ty::TypeScheme<'tcx>
1410{
1411 if def_id.krate != ast::LOCAL_CRATE {
1412 return ty::lookup_item_type(ccx.tcx, def_id);
1413 }
1414
1415 match ccx.tcx.map.find(def_id.node) {
1416 Some(ast_map::NodeItem(item)) => {
1417 type_scheme_of_item(ccx, &*item)
1418 }
1419 Some(ast_map::NodeForeignItem(foreign_item)) => {
1420 let abi = ccx.tcx.map.get_foreign_abi(def_id.node);
1421 type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
1422 }
1423 x => {
1424 ccx.tcx.sess.bug(&format!("unexpected sort of node \
1425 in get_item_type_scheme(): {:?}",
1426 x));
1427 }
1428 }
1429}
1430
1431fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
85aaf69f
SL
1432 it: &ast::Item)
1433 -> ty::TypeScheme<'tcx>
1434{
1435 memoized(&ccx.tcx.tcache,
1436 local_def(it.id),
1437 |_| compute_type_scheme_of_item(ccx, it))
1438}
1439
c34b1796
AL
1440fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1441 it: &ast::Item)
1442 -> ty::TypeScheme<'tcx>
85aaf69f
SL
1443{
1444 let tcx = ccx.tcx;
1a4d82fc
JJ
1445 match it.node {
1446 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
c34b1796 1447 let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
85aaf69f 1448 ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
1a4d82fc 1449 }
62682a34 1450 ast::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
c34b1796
AL
1451 let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
1452 let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
85aaf69f
SL
1453 let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
1454 ty::TypeScheme { ty: ty, generics: ty_generics }
1a4d82fc
JJ
1455 }
1456 ast::ItemTy(ref t, ref generics) => {
85aaf69f 1457 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
c34b1796 1458 let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
85aaf69f 1459 ty::TypeScheme { ty: ty, generics: ty_generics }
1a4d82fc
JJ
1460 }
1461 ast::ItemEnum(_, ref generics) => {
1462 // Create a new generic polytype.
1463 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1464 let substs = mk_item_substs(ccx, &ty_generics);
1465 let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
85aaf69f 1466 ty::TypeScheme { ty: t, generics: ty_generics }
1a4d82fc
JJ
1467 }
1468 ast::ItemStruct(_, ref generics) => {
1469 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1470 let substs = mk_item_substs(ccx, &ty_generics);
1471 let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
85aaf69f
SL
1472 ty::TypeScheme { ty: t, generics: ty_generics }
1473 }
c34b1796 1474 ast::ItemDefaultImpl(..) |
85aaf69f
SL
1475 ast::ItemTrait(..) |
1476 ast::ItemImpl(..) |
1477 ast::ItemMod(..) |
1478 ast::ItemForeignMod(..) |
1479 ast::ItemExternCrate(..) |
1480 ast::ItemUse(..) |
1481 ast::ItemMac(..) => {
1482 tcx.sess.span_bug(
1483 it.span,
c34b1796
AL
1484 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1485 it.node));
85aaf69f
SL
1486 }
1487 }
1488}
1489
c34b1796 1490fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1491 it: &ast::Item)
1492 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
1493{
1494 let tcx = ccx.tcx;
1a4d82fc 1495
85aaf69f
SL
1496 let tag = type_scheme_of_item(ccx, it);
1497 let scheme = TypeScheme { generics: tag.generics, ty: tag.ty };
1498 let predicates = match it.node {
1499 ast::ItemStatic(..) | ast::ItemConst(..) => {
1500 ty::GenericPredicates::empty()
1a4d82fc 1501 }
62682a34 1502 ast::ItemFn(_, _, _, _, ref ast_generics, _) => {
c34b1796 1503 ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
85aaf69f
SL
1504 }
1505 ast::ItemTy(_, ref generics) => {
c34b1796 1506 ty_generic_predicates_for_type_or_impl(ccx, generics)
85aaf69f
SL
1507 }
1508 ast::ItemEnum(_, ref generics) => {
c34b1796 1509 ty_generic_predicates_for_type_or_impl(ccx, generics)
85aaf69f
SL
1510 }
1511 ast::ItemStruct(_, ref generics) => {
c34b1796 1512 ty_generic_predicates_for_type_or_impl(ccx, generics)
85aaf69f 1513 }
c34b1796 1514 ast::ItemDefaultImpl(..) |
85aaf69f
SL
1515 ast::ItemTrait(..) |
1516 ast::ItemExternCrate(..) |
1517 ast::ItemUse(..) |
1518 ast::ItemImpl(..) |
1519 ast::ItemMod(..) |
1520 ast::ItemForeignMod(..) |
1521 ast::ItemMac(..) => {
1522 tcx.sess.span_bug(
1523 it.span,
c34b1796
AL
1524 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1525 it.node));
85aaf69f
SL
1526 }
1527 };
1528
1529 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id),
1530 predicates.clone());
1531 assert!(prev_predicates.is_none());
1532
1533 // Debugging aid.
1534 if ty::has_attr(tcx, local_def(it.id), "rustc_object_lifetime_default") {
1535 let object_lifetime_default_reprs: String =
1536 scheme.generics.types.iter()
1537 .map(|t| match t.object_lifetime_default {
62682a34
SL
1538 ty::ObjectLifetimeDefault::Specific(r) => r.to_string(),
1539 d => format!("{:?}", d),
85aaf69f
SL
1540 })
1541 .collect::<Vec<String>>()
1542 .connect(",");
1543
1544 tcx.sess.span_err(it.span, &object_lifetime_default_reprs);
1a4d82fc 1545 }
85aaf69f
SL
1546
1547 return (scheme, predicates);
1a4d82fc
JJ
1548}
1549
85aaf69f 1550fn type_scheme_of_foreign_item<'a, 'tcx>(
c34b1796 1551 ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1552 it: &ast::ForeignItem,
1553 abi: abi::Abi)
1554 -> ty::TypeScheme<'tcx>
1555{
c34b1796 1556 memoized(&ccx.tcx.tcache,
85aaf69f
SL
1557 local_def(it.id),
1558 |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
1559}
1560
1561fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
c34b1796 1562 ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1563 it: &ast::ForeignItem,
1564 abi: abi::Abi)
1565 -> ty::TypeScheme<'tcx>
1a4d82fc
JJ
1566{
1567 match it.node {
1568 ast::ForeignItemFn(ref fn_decl, ref generics) => {
85aaf69f 1569 compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
1a4d82fc
JJ
1570 }
1571 ast::ForeignItemStatic(ref t, _) => {
1572 ty::TypeScheme {
1573 generics: ty::Generics::empty(),
c34b1796 1574 ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
1a4d82fc
JJ
1575 }
1576 }
1577 }
1578}
1579
c34b1796 1580fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
1581 it: &ast::ForeignItem)
1582{
1583 // For reasons I cannot fully articulate, I do so hate the AST
1584 // map, and I regard each time that I use it as a personal and
1585 // moral failing, but at the moment it seems like the only
1586 // convenient way to extract the ABI. - ndm
1587 let tcx = ccx.tcx;
1588 let abi = tcx.map.get_foreign_abi(it.id);
1589
1590 let scheme = type_scheme_of_foreign_item(ccx, it, abi);
1591 write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
1592
1593 let predicates = match it.node {
1594 ast::ForeignItemFn(_, ref generics) => {
c34b1796 1595 ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
85aaf69f
SL
1596 }
1597 ast::ForeignItemStatic(..) => {
1598 ty::GenericPredicates::empty()
1599 }
1600 };
1601
1602 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id), predicates);
1603 assert!(prev_predicates.is_none());
1604}
1605
c34b1796 1606fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc
JJ
1607 generics: &ast::Generics)
1608 -> ty::Generics<'tcx> {
c34b1796 1609 ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
85aaf69f
SL
1610}
1611
c34b1796
AL
1612fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1613 generics: &ast::Generics)
1614 -> ty::GenericPredicates<'tcx>
85aaf69f 1615{
c34b1796 1616 ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
1a4d82fc
JJ
1617}
1618
c34b1796 1619fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 1620 trait_id: ast::NodeId,
c34b1796 1621 substs: &'tcx Substs<'tcx>,
85aaf69f 1622 ast_generics: &ast::Generics)
1a4d82fc
JJ
1623 -> ty::Generics<'tcx>
1624{
62682a34
SL
1625 debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})",
1626 local_def(trait_id), substs);
1a4d82fc 1627
c34b1796 1628 let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
1a4d82fc
JJ
1629
1630 // Add in the self type parameter.
1631 //
1632 // Something of a hack: use the node id for the trait, also as
1633 // the node id for the Self type parameter.
1634 let param_id = trait_id;
1635
1a4d82fc 1636 let def = ty::TypeParameterDef {
c34b1796 1637 space: SelfSpace,
1a4d82fc
JJ
1638 index: 0,
1639 name: special_idents::type_self.name,
1640 def_id: local_def(param_id),
85aaf69f 1641 default: None,
62682a34 1642 object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
1a4d82fc
JJ
1643 };
1644
1645 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1646
c34b1796 1647 generics.types.push(SelfSpace, def);
1a4d82fc 1648
1a4d82fc 1649 return generics;
1a4d82fc
JJ
1650}
1651
c34b1796
AL
1652fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1653 generics: &ast::Generics,
1654 base_generics: &ty::Generics<'tcx>)
1655 -> ty::Generics<'tcx>
1a4d82fc 1656{
c34b1796 1657 ty_generics(ccx, FnSpace, generics, base_generics)
85aaf69f
SL
1658}
1659
c34b1796
AL
1660fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1661 generics: &ast::Generics,
1662 base_predicates: &ty::GenericPredicates<'tcx>)
1663 -> ty::GenericPredicates<'tcx>
85aaf69f 1664{
c34b1796 1665 ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
1a4d82fc
JJ
1666}
1667
1668// Add the Sized bound, unless the type parameter is marked as `?Sized`.
c34b1796
AL
1669fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
1670 bounds: &mut ty::BuiltinBounds,
1671 ast_bounds: &[ast::TyParamBound],
1672 span: Span)
1a4d82fc 1673{
c34b1796
AL
1674 let tcx = astconv.tcx();
1675
1a4d82fc
JJ
1676 // Try to find an unbound in bounds.
1677 let mut unbound = None;
85aaf69f 1678 for ab in ast_bounds {
1a4d82fc
JJ
1679 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1680 if unbound.is_none() {
1681 assert!(ptr.bound_lifetimes.is_empty());
1682 unbound = Some(ptr.trait_ref.clone());
1683 } else {
c34b1796 1684 span_err!(tcx.sess, span, E0203,
85aaf69f 1685 "type parameter has more than one relaxed default \
1a4d82fc
JJ
1686 bound, only one is supported");
1687 }
1688 }
1689 }
1690
c34b1796 1691 let kind_id = tcx.lang_items.require(SizedTraitLangItem);
1a4d82fc
JJ
1692 match unbound {
1693 Some(ref tpb) => {
1694 // FIXME(#8559) currently requires the unbound to be built-in.
c34b1796 1695 let trait_def_id = ty::trait_ref_to_def_id(tcx, tpb);
1a4d82fc
JJ
1696 match kind_id {
1697 Ok(kind_id) if trait_def_id != kind_id => {
c34b1796
AL
1698 tcx.sess.span_warn(span,
1699 "default bound relaxed for a type parameter, but \
1700 this does nothing because the given bound is not \
1701 a default. Only `?Sized` is supported");
1702 ty::try_add_builtin_trait(tcx, kind_id, bounds);
1a4d82fc
JJ
1703 }
1704 _ => {}
1705 }
1706 }
1707 _ if kind_id.is_ok() => {
c34b1796 1708 ty::try_add_builtin_trait(tcx, kind_id.unwrap(), bounds);
1a4d82fc
JJ
1709 }
1710 // No lang item for Sized, so we can't add it as a bound.
1711 None => {}
1712 }
1713}
1714
c34b1796
AL
1715/// Returns the early-bound lifetimes declared in this generics
1716/// listing. For anything other than fns/methods, this is just all
1717/// the lifetimes that are declared. For fns or methods, we have to
1718/// screen out those that do not appear in any where-clauses etc using
1719/// `resolve_lifetime::early_bound_lifetimes`.
1720fn early_bound_lifetimes_from_generics(space: ParamSpace,
1721 ast_generics: &ast::Generics)
1722 -> Vec<ast::LifetimeDef>
1723{
1724 match space {
1725 SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
1726 FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics),
1727 }
1728}
1729
1730fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1731 space: ParamSpace,
1732 ast_generics: &ast::Generics,
1733 base_predicates: &ty::GenericPredicates<'tcx>)
1734 -> ty::GenericPredicates<'tcx>
1a4d82fc 1735{
85aaf69f 1736 let tcx = ccx.tcx;
c34b1796
AL
1737 let mut result = base_predicates.clone();
1738
1739 // Collect the predicates that were written inline by the user on each
1740 // type parameter (e.g., `<T:Foo>`).
1741 for (index, param) in ast_generics.ty_params.iter().enumerate() {
1742 let index = index as u32;
1743 let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx);
1744 let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
1745 param_ty,
1746 &param.bounds,
1747 SizedByDefault::Yes,
1748 param.span);
62682a34 1749 let predicates = bounds.predicates(ccx.tcx, param_ty);
c34b1796 1750 result.predicates.extend(space, predicates.into_iter());
1a4d82fc 1751 }
c34b1796
AL
1752
1753 // Collect the region predicates that were declared inline as
1754 // well. In the case of parameters declared on a fn or method, we
1755 // have to be careful to only iterate over early-bound regions.
1756 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1757 for (index, param) in early_lifetimes.iter().enumerate() {
1758 let index = index as u32;
9346a6ac
AL
1759 let region =
1760 ty::ReEarlyBound(ty::EarlyBoundRegion {
1761 param_id: param.lifetime.id,
1762 space: space,
1763 index: index,
1764 name: param.lifetime.name
1765 });
c34b1796
AL
1766 for bound in &param.bounds {
1767 let bound_region = ast_region_to_region(ccx.tcx, bound);
1768 let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
1769 result.predicates.push(space, outlives.as_predicate());
1770 }
1a4d82fc
JJ
1771 }
1772
c34b1796
AL
1773 // Add in the bounds that appear in the where-clause
1774 let where_clause = &ast_generics.where_clause;
85aaf69f 1775 for predicate in &where_clause.predicates {
1a4d82fc
JJ
1776 match predicate {
1777 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
c34b1796
AL
1778 let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
1779 &ExplicitRscope,
1780 &*bound_pred.bounded_ty);
1a4d82fc 1781
62682a34 1782 for bound in bound_pred.bounds.iter() {
1a4d82fc
JJ
1783 match bound {
1784 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1785 let mut projections = Vec::new();
1786
c34b1796
AL
1787 let trait_ref =
1788 conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
1789 ty,
1790 poly_trait_ref,
1791 &mut projections);
1a4d82fc
JJ
1792
1793 result.predicates.push(space, trait_ref.as_predicate());
1794
85aaf69f 1795 for projection in &projections {
1a4d82fc
JJ
1796 result.predicates.push(space, projection.as_predicate());
1797 }
1798 }
1799
1800 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
85aaf69f 1801 let region = ast_region_to_region(tcx, lifetime);
1a4d82fc
JJ
1802 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1803 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1804 }
1805 }
1806 }
1807 }
1808
1809 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
85aaf69f
SL
1810 let r1 = ast_region_to_region(tcx, &region_pred.lifetime);
1811 for bound in &region_pred.bounds {
1812 let r2 = ast_region_to_region(tcx, bound);
1a4d82fc
JJ
1813 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1814 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1815 }
1816 }
1817
1818 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1819 // FIXME(#20041)
85aaf69f
SL
1820 tcx.sess.span_bug(eq_pred.span,
1821 "Equality constraints are not yet \
1822 implemented (#20041)")
1a4d82fc
JJ
1823 }
1824 }
1825 }
1826
1827 return result;
85aaf69f 1828}
1a4d82fc 1829
c34b1796
AL
1830fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1831 space: ParamSpace,
1832 ast_generics: &ast::Generics,
1833 base_generics: &ty::Generics<'tcx>)
85aaf69f
SL
1834 -> ty::Generics<'tcx>
1835{
1836 let tcx = ccx.tcx;
c34b1796 1837 let mut result = base_generics.clone();
1a4d82fc 1838
c34b1796
AL
1839 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1840 for (i, l) in early_lifetimes.iter().enumerate() {
85aaf69f
SL
1841 let bounds = l.bounds.iter()
1842 .map(|l| ast_region_to_region(tcx, l))
1843 .collect();
1844 let def = ty::RegionParameterDef { name: l.lifetime.name,
1845 space: space,
1846 index: i as u32,
1847 def_id: local_def(l.lifetime.id),
1848 bounds: bounds };
85aaf69f 1849 result.regions.push(space, def);
1a4d82fc 1850 }
85aaf69f
SL
1851
1852 assert!(result.types.is_empty_in(space));
1853
1854 // Now create the real type parameters.
c34b1796
AL
1855 for i in 0..ast_generics.ty_params.len() {
1856 let def = get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32);
85aaf69f
SL
1857 debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
1858 result.types.push(space, def);
1859 }
1860
1861 result
1a4d82fc
JJ
1862}
1863
c34b1796
AL
1864fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1865 ast_generics: &ast::Generics,
1866 space: ParamSpace,
1867 index: u32)
1a4d82fc
JJ
1868 -> ty::TypeParameterDef<'tcx>
1869{
c34b1796
AL
1870 let param = &ast_generics.ty_params[index as usize];
1871
85aaf69f
SL
1872 let tcx = ccx.tcx;
1873 match tcx.ty_param_defs.borrow().get(&param.id) {
1874 Some(d) => { return d.clone(); }
1a4d82fc
JJ
1875 None => { }
1876 }
1877
1a4d82fc
JJ
1878 let default = match param.default {
1879 None => None,
1880 Some(ref path) => {
c34b1796 1881 let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &**path);
1a4d82fc
JJ
1882 let cur_idx = index;
1883
1884 ty::walk_ty(ty, |t| {
1885 match t.sty {
62682a34 1886 ty::TyParam(p) => if p.idx > cur_idx {
85aaf69f 1887 span_err!(tcx.sess, path.span, E0128,
1a4d82fc 1888 "type parameters with a default cannot use \
9346a6ac 1889 forward declared identifiers");
1a4d82fc
JJ
1890 },
1891 _ => {}
1892 }
1893 });
1894
1895 Some(ty)
1896 }
1897 };
1898
85aaf69f 1899 let object_lifetime_default =
c34b1796
AL
1900 compute_object_lifetime_default(ccx, param.id,
1901 &param.bounds, &ast_generics.where_clause);
85aaf69f 1902
1a4d82fc
JJ
1903 let def = ty::TypeParameterDef {
1904 space: space,
1905 index: index,
1906 name: param.ident.name,
1907 def_id: local_def(param.id),
85aaf69f
SL
1908 default: default,
1909 object_lifetime_default: object_lifetime_default,
1a4d82fc
JJ
1910 };
1911
85aaf69f 1912 tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1a4d82fc
JJ
1913
1914 def
1915}
1916
85aaf69f
SL
1917/// Scan the bounds and where-clauses on a parameter to extract bounds
1918/// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
1919/// This runs as part of computing the minimal type scheme, so we
1920/// intentionally avoid just asking astconv to convert all the where
1921/// clauses into a `ty::Predicate`. This is because that could induce
1922/// artificial cycles.
c34b1796
AL
1923fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1924 param_id: ast::NodeId,
85aaf69f
SL
1925 param_bounds: &[ast::TyParamBound],
1926 where_clause: &ast::WhereClause)
62682a34 1927 -> ty::ObjectLifetimeDefault
85aaf69f
SL
1928{
1929 let inline_bounds = from_bounds(ccx, param_bounds);
c34b1796 1930 let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
85aaf69f 1931 let all_bounds: HashSet<_> = inline_bounds.into_iter()
62682a34 1932 .chain(where_bounds)
85aaf69f
SL
1933 .collect();
1934 return if all_bounds.len() > 1 {
62682a34
SL
1935 ty::ObjectLifetimeDefault::Ambiguous
1936 } else if all_bounds.len() == 0 {
1937 ty::ObjectLifetimeDefault::BaseDefault
85aaf69f 1938 } else {
62682a34
SL
1939 ty::ObjectLifetimeDefault::Specific(
1940 all_bounds.into_iter().next().unwrap())
85aaf69f
SL
1941 };
1942
c34b1796 1943 fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
85aaf69f
SL
1944 bounds: &[ast::TyParamBound])
1945 -> Vec<ty::Region>
1946 {
1947 bounds.iter()
1948 .filter_map(|bound| {
1949 match *bound {
1950 ast::TraitTyParamBound(..) =>
1951 None,
1952 ast::RegionTyParamBound(ref lifetime) =>
c34b1796 1953 Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
85aaf69f
SL
1954 }
1955 })
1956 .collect()
1957 }
1958
c34b1796
AL
1959 fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1960 param_id: ast::NodeId,
85aaf69f
SL
1961 predicates: &[ast::WherePredicate])
1962 -> Vec<ty::Region>
1963 {
1964 predicates.iter()
1965 .flat_map(|predicate| {
1966 match *predicate {
1967 ast::WherePredicate::BoundPredicate(ref data) => {
9346a6ac 1968 if data.bound_lifetimes.is_empty() &&
c34b1796 1969 is_param(ccx.tcx, &data.bounded_ty, param_id)
85aaf69f
SL
1970 {
1971 from_bounds(ccx, &data.bounds).into_iter()
1972 } else {
1973 Vec::new().into_iter()
1974 }
1975 }
1976 ast::WherePredicate::RegionPredicate(..) |
1977 ast::WherePredicate::EqPredicate(..) => {
1978 Vec::new().into_iter()
1979 }
1980 }
1981 })
1982 .collect()
1983 }
85aaf69f
SL
1984}
1985
c34b1796 1986enum SizedByDefault { Yes, No, }
1a4d82fc
JJ
1987
1988/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1989/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1990/// built-in trait (formerly known as kind): Send.
c34b1796
AL
1991fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
1992 param_ty: ty::Ty<'tcx>,
1993 ast_bounds: &[ast::TyParamBound],
1994 sized_by_default: SizedByDefault,
1995 span: Span)
62682a34 1996 -> astconv::Bounds<'tcx>
1a4d82fc 1997{
62682a34
SL
1998 let mut bounds =
1999 conv_param_bounds(astconv,
2000 span,
2001 param_ty,
2002 ast_bounds);
1a4d82fc
JJ
2003
2004 if let SizedByDefault::Yes = sized_by_default {
c34b1796 2005 add_unsized_bound(astconv,
62682a34 2006 &mut bounds.builtin_bounds,
1a4d82fc
JJ
2007 ast_bounds,
2008 span);
1a4d82fc
JJ
2009 }
2010
62682a34 2011 bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
1a4d82fc 2012
62682a34 2013 bounds
1a4d82fc
JJ
2014}
2015
c34b1796
AL
2016/// Converts a specific TyParamBound from the AST into a set of
2017/// predicates that apply to the self-type. A vector is returned
2018/// because this can be anywhere from 0 predicates (`T:?Sized` adds no
2019/// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
2020/// and `<T as Bar>::X == i32`).
2021fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
2022 param_ty: Ty<'tcx>,
2023 bound: &ast::TyParamBound)
2024 -> Vec<ty::Predicate<'tcx>>
2025{
2026 match *bound {
2027 ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => {
2028 let mut projections = Vec::new();
2029 let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
2030 projections.into_iter()
2031 .map(|p| p.as_predicate())
62682a34 2032 .chain(Some(pred.as_predicate()))
c34b1796
AL
2033 .collect()
2034 }
2035 ast::RegionTyParamBound(ref lifetime) => {
2036 let region = ast_region_to_region(astconv.tcx(), lifetime);
2037 let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
2038 vec![ty::Predicate::TypeOutlives(pred)]
2039 }
2040 ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {
2041 Vec::new()
2042 }
1a4d82fc
JJ
2043 }
2044}
2045
c34b1796
AL
2046fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
2047 param_ty: Ty<'tcx>,
2048 trait_ref: &ast::PolyTraitRef,
2049 projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
2050 -> ty::PolyTraitRef<'tcx>
2051{
2052 astconv::instantiate_poly_trait_ref(astconv,
2053 &ExplicitRscope,
2054 trait_ref,
2055 Some(param_ty),
2056 projections)
2057}
2058
2059fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
1a4d82fc
JJ
2060 span: Span,
2061 param_ty: ty::Ty<'tcx>,
2062 ast_bounds: &[ast::TyParamBound])
62682a34 2063 -> astconv::Bounds<'tcx>
1a4d82fc 2064{
c34b1796 2065 let tcx = astconv.tcx();
85aaf69f
SL
2066 let astconv::PartitionedBounds {
2067 builtin_bounds,
2068 trait_bounds,
2069 region_bounds
c34b1796 2070 } = astconv::partition_bounds(tcx, span, &ast_bounds);
1a4d82fc
JJ
2071
2072 let mut projection_bounds = Vec::new();
2073
2074 let trait_bounds: Vec<ty::PolyTraitRef> =
c34b1796
AL
2075 trait_bounds.iter()
2076 .map(|bound| conv_poly_trait_ref(astconv,
2077 param_ty,
2078 *bound,
2079 &mut projection_bounds))
2080 .collect();
85aaf69f 2081
1a4d82fc
JJ
2082 let region_bounds: Vec<ty::Region> =
2083 region_bounds.into_iter()
c34b1796 2084 .map(|r| ast_region_to_region(tcx, r))
85aaf69f
SL
2085 .collect();
2086
62682a34 2087 astconv::Bounds {
1a4d82fc
JJ
2088 region_bounds: region_bounds,
2089 builtin_bounds: builtin_bounds,
2090 trait_bounds: trait_bounds,
2091 projection_bounds: projection_bounds,
2092 }
2093}
2094
85aaf69f 2095fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
c34b1796 2096 ccx: &CrateCtxt<'a, 'tcx>,
85aaf69f
SL
2097 decl: &ast::FnDecl,
2098 ast_generics: &ast::Generics,
2099 abi: abi::Abi)
2100 -> ty::TypeScheme<'tcx>
2101{
62682a34 2102 for i in &decl.inputs {
1a4d82fc
JJ
2103 match (*i).pat.node {
2104 ast::PatIdent(_, _, _) => (),
2105 ast::PatWild(ast::PatWildSingle) => (),
2106 _ => {
2107 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
2108 "patterns aren't allowed in foreign function declarations");
2109 }
2110 }
2111 }
2112
c34b1796 2113 let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
85aaf69f 2114
1a4d82fc
JJ
2115 let rb = BindingRscope::new();
2116 let input_tys = decl.inputs
2117 .iter()
c34b1796 2118 .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
1a4d82fc
JJ
2119 .collect();
2120
2121 let output = match decl.output {
2122 ast::Return(ref ty) =>
c34b1796 2123 ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
85aaf69f
SL
2124 ast::DefaultReturn(..) =>
2125 ty::FnConverging(ty::mk_nil(ccx.tcx)),
2126 ast::NoReturn(..) =>
1a4d82fc
JJ
2127 ty::FnDiverging
2128 };
2129
2130 let t_fn = ty::mk_bare_fn(
2131 ccx.tcx,
2132 None,
2133 ccx.tcx.mk_bare_fn(ty::BareFnTy {
2134 abi: abi,
2135 unsafety: ast::Unsafety::Unsafe,
2136 sig: ty::Binder(ty::FnSig {inputs: input_tys,
2137 output: output,
2138 variadic: decl.variadic}),
2139 }));
1a4d82fc 2140
85aaf69f
SL
2141 ty::TypeScheme {
2142 generics: ty_generics,
2143 ty: t_fn
2144 }
1a4d82fc
JJ
2145}
2146
c34b1796 2147fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 2148 ty_generics: &ty::Generics<'tcx>)
c34b1796 2149 -> Substs<'tcx>
1a4d82fc
JJ
2150{
2151 let types =
2152 ty_generics.types.map(
2153 |def| ty::mk_param_from_def(ccx.tcx, def));
2154
2155 let regions =
2156 ty_generics.regions.map(
2157 |def| def.to_early_bound_region());
2158
c34b1796 2159 Substs::new(types, regions)
1a4d82fc
JJ
2160}
2161
2162/// Verifies that the explicit self type of a method matches the impl
2163/// or trait. This is a bit weird but basically because right now we
2164/// don't handle the general case, but instead map it to one of
2165/// several pre-defined options using various heuristics, this method
2166/// comes back to check after the fact that explicit type the user
2167/// wrote actually matches what the pre-defined option said.
2168fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
c34b1796 2169 ccx: &CrateCtxt<'a, 'tcx>,
1a4d82fc 2170 rs: &RS,
c34b1796 2171 method_type: Rc<ty::Method<'tcx>>,
1a4d82fc
JJ
2172 required_type: Ty<'tcx>,
2173 explicit_self: &ast::ExplicitSelf,
2174 body_id: ast::NodeId)
2175{
85aaf69f 2176 let tcx = ccx.tcx;
1a4d82fc 2177 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
c34b1796 2178 let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
1a4d82fc 2179 let base_type = match typ.sty {
62682a34
SL
2180 ty::TyRef(_, tm) => tm.ty,
2181 ty::TyBox(typ) => typ,
1a4d82fc
JJ
2182 _ => typ,
2183 };
2184
85aaf69f 2185 let body_scope = region::DestructionScopeData::new(body_id);
1a4d82fc
JJ
2186
2187 // "Required type" comes from the trait definition. It may
2188 // contain late-bound regions from the method, but not the
2189 // trait (since traits only have early-bound region
2190 // parameters).
2191 assert!(!base_type.has_regions_escaping_depth(1));
2192 let required_type_free =
2193 liberate_early_bound_regions(
85aaf69f 2194 tcx, body_scope,
1a4d82fc 2195 &ty::liberate_late_bound_regions(
85aaf69f 2196 tcx, body_scope, &ty::Binder(required_type)));
1a4d82fc
JJ
2197
2198 // The "base type" comes from the impl. It too may have late-bound
2199 // regions from the method.
2200 assert!(!base_type.has_regions_escaping_depth(1));
2201 let base_type_free =
2202 liberate_early_bound_regions(
85aaf69f 2203 tcx, body_scope,
1a4d82fc 2204 &ty::liberate_late_bound_regions(
85aaf69f 2205 tcx, body_scope, &ty::Binder(base_type)));
1a4d82fc 2206
62682a34
SL
2207 debug!("required_type={:?} required_type_free={:?} \
2208 base_type={:?} base_type_free={:?}",
2209 required_type,
2210 required_type_free,
2211 base_type,
2212 base_type_free);
85aaf69f
SL
2213
2214 let infcx = infer::new_infer_ctxt(tcx);
2215 drop(::require_same_types(tcx,
1a4d82fc
JJ
2216 Some(&infcx),
2217 false,
2218 explicit_self.span,
2219 base_type_free,
2220 required_type_free,
2221 || {
2222 format!("mismatched self type: expected `{}`",
62682a34 2223 required_type)
1a4d82fc 2224 }));
bd371182 2225
62682a34 2226 // We could conceviably add more free-region relations here,
bd371182
AL
2227 // but since this code is just concerned with checking that
2228 // the `&Self` types etc match up, it's not really necessary.
2229 // It would just allow people to be more approximate in some
2230 // cases. In any case, we can do it later as we feel the need;
2231 // I'd like this function to go away eventually.
2232 let free_regions = FreeRegionMap::new();
2233
2234 infcx.resolve_regions_and_report_errors(&free_regions, body_id);
1a4d82fc
JJ
2235 }
2236
2237 fn liberate_early_bound_regions<'tcx,T>(
2238 tcx: &ty::ctxt<'tcx>,
85aaf69f 2239 scope: region::DestructionScopeData,
1a4d82fc
JJ
2240 value: &T)
2241 -> T
62682a34 2242 where T : TypeFoldable<'tcx>
1a4d82fc
JJ
2243 {
2244 /*!
2245 * Convert early-bound regions into free regions; normally this is done by
2246 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
2247 * method-self-type check is kind of hacky and done very early in the process,
2248 * before we really have a `ParameterEnvironment` to check.
2249 */
2250
2251 ty_fold::fold_regions(tcx, value, |region, _| {
2252 match region {
9346a6ac
AL
2253 ty::ReEarlyBound(data) => {
2254 let def_id = local_def(data.param_id);
1a4d82fc 2255 ty::ReFree(ty::FreeRegion { scope: scope,
9346a6ac 2256 bound_region: ty::BrNamed(def_id, data.name) })
1a4d82fc
JJ
2257 }
2258 _ => region
2259 }
2260 })
2261 }
2262}
2263
2264/// Checks that all the type parameters on an impl
9346a6ac
AL
2265fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
2266 ast_generics: &ast::Generics,
2267 impl_def_id: ast::DefId,
2268 impl_items: &[P<ast::ImplItem>])
1a4d82fc
JJ
2269{
2270 let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
85aaf69f 2271 let impl_predicates = ty::lookup_predicates(tcx, impl_def_id);
1a4d82fc
JJ
2272 let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
2273
2274 // The trait reference is an input, so find all type parameters
2275 // reachable from there, to start (if this is an inherent impl,
2276 // then just examine the self type).
2277 let mut input_parameters: HashSet<_> =
9346a6ac
AL
2278 ctp::parameters_for_type(impl_scheme.ty).into_iter().collect();
2279 if let Some(ref trait_ref) = impl_trait_ref {
2280 input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref));
2281 }
2282
2283 ctp::identify_constrained_type_params(tcx,
2284 impl_predicates.predicates.as_slice(),
2285 impl_trait_ref,
2286 &mut input_parameters);
1a4d82fc
JJ
2287
2288 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
2289 let param_ty = ty::ParamTy { space: TypeSpace,
2290 idx: index as u32,
2291 name: ty_param.ident.name };
9346a6ac 2292 if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
62682a34 2293 report_unused_parameter(tcx, ty_param.span, "type", &param_ty.to_string());
1a4d82fc
JJ
2294 }
2295 }
9346a6ac
AL
2296
2297 // Every lifetime used in an associated type must be constrained.
2298
2299 let lifetimes_in_associated_types: HashSet<_> =
2300 impl_items.iter()
62682a34
SL
2301 .map(|item| ty::impl_or_trait_item(tcx, local_def(item.id)))
2302 .filter_map(|item| match item {
2303 ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
2304 ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
9346a6ac 2305 })
62682a34 2306 .flat_map(|ty| ctp::parameters_for_type(ty))
9346a6ac
AL
2307 .filter_map(|p| match p {
2308 ctp::Parameter::Type(_) => None,
2309 ctp::Parameter::Region(r) => Some(r),
2310 })
2311 .collect();
2312
2313 for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
2314 let region = ty::EarlyBoundRegion { param_id: lifetime_def.lifetime.id,
2315 space: TypeSpace,
2316 index: index as u32,
2317 name: lifetime_def.lifetime.name };
2318 if
2319 lifetimes_in_associated_types.contains(&region) && // (*)
2320 !input_parameters.contains(&ctp::Parameter::Region(region))
2321 {
2322 report_unused_parameter(tcx, lifetime_def.lifetime.span,
62682a34 2323 "lifetime", &region.name.to_string());
9346a6ac
AL
2324 }
2325 }
2326
2327 // (*) This is a horrible concession to reality. I think it'd be
2328 // better to just ban unconstrianed lifetimes outright, but in
2329 // practice people do non-hygenic macros like:
2330 //
2331 // ```
2332 // macro_rules! __impl_slice_eq1 {
2333 // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
2334 // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
2335 // ....
2336 // }
2337 // }
2338 // }
2339 // ```
2340 //
2341 // In a concession to backwards compatbility, we continue to
2342 // permit those, so long as the lifetimes aren't used in
2343 // associated types. I believe this is sound, because lifetimes
2344 // used elsewhere are not projected back out.
2345}
2346
2347fn report_unused_parameter(tcx: &ty::ctxt,
2348 span: Span,
2349 kind: &str,
2350 name: &str)
2351{
2352 span_err!(tcx.sess, span, E0207,
2353 "the {} parameter `{}` is not constrained by the \
2354 impl trait, self type, or predicates",
2355 kind, name);
1a4d82fc 2356}