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