]>
Commit | Line | Data |
---|---|---|
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 | ||
15 | The collect phase of type check has the job of visiting all items, | |
16 | determining their type, and writing that type into the `tcx.tcache` | |
17 | table. Despite its name, this table does not really operate as a | |
18 | *cache*, at least not for the types of items defined within the | |
19 | current crate: we assume that after the collect phase, the types of | |
20 | all local items will be present in the table. | |
21 | ||
22 | Unlike most of the types that are present in Rust, the types computed | |
85aaf69f SL |
23 | for each item are in fact type schemes. This means that they are |
24 | generic types that may have type parameters. TypeSchemes are | |
25 | represented by an instance of `ty::TypeScheme`. This combines the | |
26 | core type along with a list of the bounds for each parameter. Type | |
27 | parameters themselves are represented as `ty_param()` instances. | |
28 | ||
c34b1796 AL |
29 | The phasing of type conversion is somewhat complicated. There is no |
30 | clear set of phases we can enforce (e.g., converting traits first, | |
31 | then types, or something like that) because the user can introduce | |
32 | arbitrary interdependencies. So instead we generally convert things | |
33 | lazilly and on demand, and include logic that checks for cycles. | |
34 | Demand is driven by calls to `AstConv::get_item_type_scheme` or | |
35 | `AstConv::lookup_trait_def`. | |
36 | ||
37 | Currently, we "convert" types and traits in three phases (note that | |
38 | conversion only affects the types of items / enum variants / methods; | |
39 | it does not e.g. compute the types of individual expressions): | |
85aaf69f SL |
40 | |
41 | 0. Intrinsics | |
42 | 1. Trait definitions | |
43 | 2. Type definitions | |
44 | ||
45 | Conversion itself is done by simply walking each of the items in turn | |
46 | and invoking an appropriate function (e.g., `trait_def_of_item` or | |
47 | `convert_item`). However, it is possible that while converting an | |
48 | item, we may need to compute the *type scheme* or *trait definition* | |
c34b1796 | 49 | for other items. |
85aaf69f SL |
50 | |
51 | There 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 | 67 | use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region}; |
85aaf69f | 68 | use middle::def; |
9346a6ac | 69 | use constrained_type_params as ctp; |
1a4d82fc | 70 | use middle::lang_items::SizedTraitLangItem; |
bd371182 | 71 | use middle::free_region::FreeRegionMap; |
1a4d82fc JJ |
72 | use middle::region; |
73 | use middle::resolve_lifetime; | |
c34b1796 | 74 | use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; |
1a4d82fc | 75 | use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; |
c34b1796 | 76 | use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme}; |
1a4d82fc JJ |
77 | use middle::ty_fold::{self, TypeFolder, TypeFoldable}; |
78 | use middle::infer; | |
1a4d82fc | 79 | use rscope::*; |
62682a34 | 80 | use rustc::ast_map; |
c34b1796 | 81 | use util::common::{ErrorReported, memoized}; |
1a4d82fc | 82 | use util::nodemap::{FnvHashMap, FnvHashSet}; |
1a4d82fc JJ |
83 | use write_ty_to_tcx; |
84 | ||
d9579d0f | 85 | use std::cell::{Cell, RefCell}; |
1a4d82fc JJ |
86 | use std::collections::HashSet; |
87 | use std::rc::Rc; | |
88 | ||
89 | use syntax::abi; | |
90 | use syntax::ast; | |
c34b1796 | 91 | use syntax::ast_util::local_def; |
1a4d82fc | 92 | use syntax::codemap::Span; |
c34b1796 | 93 | use syntax::parse::token::special_idents; |
1a4d82fc JJ |
94 | use syntax::parse::token; |
95 | use syntax::ptr::P; | |
96 | use syntax::visit; | |
97 | ||
98 | /////////////////////////////////////////////////////////////////////////// | |
99 | // Main entry point | |
100 | ||
101 | pub 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 | 113 | struct 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). | |
132 | struct 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)] |
138 | enum 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 | ||
150 | struct CollectTraitDefVisitor<'a, 'tcx: 'a> { | |
c34b1796 | 151 | ccx: &'a CrateCtxt<'a, 'tcx> |
1a4d82fc JJ |
152 | } |
153 | ||
154 | impl<'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 | ||
171 | struct CollectItemTypesVisitor<'a, 'tcx: 'a> { | |
c34b1796 | 172 | ccx: &'a CrateCtxt<'a, 'tcx> |
1a4d82fc JJ |
173 | } |
174 | ||
175 | impl<'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 |
189 | impl<'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 | ||
343 | impl<'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 | ||
349 | impl<'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. | |
425 | trait 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. | |
434 | impl<'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. | |
450 | impl<'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. | |
464 | impl<'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. | |
499 | impl<'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. | |
540 | fn 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 | ||
563 | fn 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 |
605 | fn 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 |
653 | fn 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 |
692 | fn 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 |
718 | fn 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 | 736 | fn 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 | 773 | fn 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 | 802 | fn 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 | 1055 | fn 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. | |
1136 | fn 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 | 1218 | fn 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 |
1309 | fn 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 | ||
1332 | fn 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 |
1407 | fn 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 | ||
1431 | fn 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 |
1440 | fn 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 | 1490 | fn 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 | 1550 | fn 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 | ||
1561 | fn 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 | 1580 | fn 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 | 1606 | fn 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 |
1612 | fn 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 | 1619 | fn 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 |
1652 | fn 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 |
1660 | fn 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 |
1669 | fn 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`. | |
1720 | fn 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 | ||
1730 | fn 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 | ¶m.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 ¶m.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, ®ion_pred.lifetime); |
1811 | for bound in ®ion_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 |
1830 | fn 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 |
1864 | fn 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(¶m.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 | ¶m.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 |
1923 | fn 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 | 1986 | enum 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 |
1991 | fn 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`). | |
2021 | fn 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 |
2046 | fn 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 | ||
2059 | fn 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 | 2095 | fn 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 | 2147 | fn 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. | |
2168 | fn 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 |
2265 | fn 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", ¶m_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(®ion) && // (*) | |
2320 | !input_parameters.contains(&ctp::Parameter::Region(region)) | |
2321 | { | |
2322 | report_unused_parameter(tcx, lifetime_def.lifetime.span, | |
62682a34 | 2323 | "lifetime", ®ion.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 | ||
2347 | fn 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 | } |