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