]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
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 | ||
c1a9b12d | 11 | // FIXME: (@jroesch) @eddyb should remove this when he renames ctxt |
1a4d82fc JJ |
12 | #![allow(non_camel_case_types)] |
13 | ||
1a4d82fc JJ |
14 | pub use self::InferTy::*; |
15 | pub use self::InferRegion::*; | |
16 | pub use self::ImplOrTraitItemId::*; | |
85aaf69f | 17 | pub use self::ClosureKind::*; |
1a4d82fc JJ |
18 | pub use self::Variance::*; |
19 | pub use self::AutoAdjustment::*; | |
20 | pub use self::Representability::*; | |
1a4d82fc | 21 | pub use self::AutoRef::*; |
1a4d82fc JJ |
22 | pub use self::DtorKind::*; |
23 | pub use self::ExplicitSelfCategory::*; | |
24 | pub use self::FnOutput::*; | |
25 | pub use self::Region::*; | |
26 | pub use self::ImplOrTraitItemContainer::*; | |
27 | pub use self::BorrowKind::*; | |
28 | pub use self::ImplOrTraitItem::*; | |
29 | pub use self::BoundRegion::*; | |
62682a34 | 30 | pub use self::TypeVariants::*; |
1a4d82fc | 31 | pub use self::IntVarValue::*; |
1a4d82fc JJ |
32 | pub use self::CopyImplementationError::*; |
33 | ||
62682a34 SL |
34 | pub use self::BuiltinBound::Send as BoundSend; |
35 | pub use self::BuiltinBound::Sized as BoundSized; | |
36 | pub use self::BuiltinBound::Copy as BoundCopy; | |
37 | pub use self::BuiltinBound::Sync as BoundSync; | |
38 | ||
39 | use ast_map::{self, LinkedPath}; | |
1a4d82fc JJ |
40 | use back::svh::Svh; |
41 | use session::Session; | |
42 | use lint; | |
223e47cc | 43 | use metadata::csearch; |
1a4d82fc | 44 | use middle; |
62682a34 | 45 | use middle::cast; |
85aaf69f | 46 | use middle::check_const; |
c1a9b12d SL |
47 | use middle::const_eval::{self, ConstVal, ErrKind}; |
48 | use middle::const_eval::EvalHint::UncheckedExprHint; | |
1a4d82fc JJ |
49 | use middle::def::{self, DefMap, ExportMap}; |
50 | use middle::dependency_format; | |
d9579d0f | 51 | use middle::fast_reject; |
bd371182 | 52 | use middle::free_region::FreeRegionMap; |
c34b1796 | 53 | use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; |
1a4d82fc JJ |
54 | use middle::region; |
55 | use middle::resolve_lifetime; | |
56 | use middle::infer; | |
c1a9b12d | 57 | use middle::infer::type_variable; |
c34b1796 | 58 | use middle::pat_util; |
bd371182 | 59 | use middle::region::RegionMaps; |
1a4d82fc | 60 | use middle::stability; |
c34b1796 | 61 | use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace}; |
1a4d82fc | 62 | use middle::traits; |
223e47cc | 63 | use middle::ty; |
1a4d82fc | 64 | use middle::ty_fold::{self, TypeFoldable, TypeFolder}; |
c34b1796 | 65 | use middle::ty_walk::{self, TypeWalker}; |
1a4d82fc JJ |
66 | use util::common::{memoized, ErrorReported}; |
67 | use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; | |
c34b1796 | 68 | use util::nodemap::FnvHashMap; |
9346a6ac | 69 | use util::num::ToPrimitive; |
1a4d82fc JJ |
70 | |
71 | use arena::TypedArena; | |
85aaf69f | 72 | use std::borrow::{Borrow, Cow}; |
c34b1796 | 73 | use std::cell::{Cell, RefCell, Ref}; |
85aaf69f SL |
74 | use std::cmp; |
75 | use std::fmt; | |
76 | use std::hash::{Hash, SipHasher, Hasher}; | |
1a4d82fc | 77 | use std::mem; |
970d7e83 | 78 | use std::ops; |
1a4d82fc | 79 | use std::rc::Rc; |
c34b1796 | 80 | use std::vec::IntoIter; |
62682a34 | 81 | use collections::enum_set::{self, EnumSet, CLike}; |
1a4d82fc JJ |
82 | use std::collections::{HashMap, HashSet}; |
83 | use syntax::abi; | |
d9579d0f | 84 | use syntax::ast::{CrateNum, DefId, ItemImpl, ItemTrait, LOCAL_CRATE}; |
1a4d82fc | 85 | use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; |
c1a9b12d | 86 | use syntax::ast::{StructField, UnnamedField, Visibility}; |
62682a34 | 87 | use syntax::ast_util::{self, is_local, local_def}; |
c34b1796 | 88 | use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt}; |
1a4d82fc JJ |
89 | use syntax::codemap::Span; |
90 | use syntax::parse::token::{self, InternedString, special_idents}; | |
c34b1796 AL |
91 | use syntax::print::pprust; |
92 | use syntax::ptr::P; | |
93 | use syntax::ast; | |
1a4d82fc JJ |
94 | |
95 | pub type Disr = u64; | |
96 | ||
97 | pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0; | |
223e47cc LB |
98 | |
99 | // Data types | |
100 | ||
1a4d82fc JJ |
101 | /// The complete set of all analyses described in this module. This is |
102 | /// produced by the driver and fed to trans and later passes. | |
62682a34 | 103 | pub struct CrateAnalysis { |
1a4d82fc JJ |
104 | pub export_map: ExportMap, |
105 | pub exported_items: middle::privacy::ExportedItems, | |
106 | pub public_items: middle::privacy::PublicItems, | |
1a4d82fc JJ |
107 | pub reachable: NodeSet, |
108 | pub name: String, | |
109 | pub glob_map: Option<GlobMap>, | |
110 | } | |
111 | ||
112 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
c1a9b12d | 113 | pub struct Field<'tcx> { |
1a4d82fc | 114 | pub name: ast::Name, |
c1a9b12d | 115 | pub mt: TypeAndMut<'tcx> |
1a4d82fc JJ |
116 | } |
117 | ||
c1a9b12d SL |
118 | // Enum information |
119 | #[derive(Clone)] | |
120 | pub struct VariantInfo<'tcx> { | |
121 | pub args: Vec<Ty<'tcx>>, | |
122 | pub arg_names: Option<Vec<ast::Name>>, | |
123 | pub ctor_ty: Option<Ty<'tcx>>, | |
124 | pub name: ast::Name, | |
125 | pub id: ast::DefId, | |
126 | pub disr_val: Disr, | |
127 | pub vis: Visibility | |
128 | } | |
129 | ||
130 | impl<'tcx> VariantInfo<'tcx> { | |
131 | ||
132 | /// Creates a new VariantInfo from the corresponding ast representation. | |
133 | /// | |
134 | /// Does not do any caching of the value in the type context. | |
135 | pub fn from_ast_variant(cx: &ctxt<'tcx>, | |
136 | ast_variant: &ast::Variant, | |
137 | discriminant: Disr) -> VariantInfo<'tcx> { | |
138 | let ctor_ty = cx.node_id_to_type(ast_variant.node.id); | |
139 | ||
140 | match ast_variant.node.kind { | |
141 | ast::TupleVariantKind(ref args) => { | |
142 | let arg_tys = if !args.is_empty() { | |
143 | // the regions in the argument types come from the | |
144 | // enum def'n, and hence will all be early bound | |
145 | cx.no_late_bound_regions(&ctor_ty.fn_args()).unwrap() | |
146 | } else { | |
147 | Vec::new() | |
148 | }; | |
149 | ||
150 | return VariantInfo { | |
151 | args: arg_tys, | |
152 | arg_names: None, | |
153 | ctor_ty: Some(ctor_ty), | |
154 | name: ast_variant.node.name.name, | |
155 | id: ast_util::local_def(ast_variant.node.id), | |
156 | disr_val: discriminant, | |
157 | vis: ast_variant.node.vis | |
158 | }; | |
159 | }, | |
160 | ast::StructVariantKind(ref struct_def) => { | |
161 | let fields: &[StructField] = &struct_def.fields; | |
162 | ||
163 | assert!(!fields.is_empty()); | |
164 | ||
165 | let arg_tys = struct_def.fields.iter() | |
166 | .map(|field| cx.node_id_to_type(field.node.id)).collect(); | |
167 | let arg_names = fields.iter().map(|field| { | |
168 | match field.node.kind { | |
169 | NamedField(ident, _) => ident.name, | |
170 | UnnamedField(..) => cx.sess.bug( | |
171 | "enum_variants: all fields in struct must have a name") | |
172 | } | |
173 | }).collect(); | |
174 | ||
175 | return VariantInfo { | |
176 | args: arg_tys, | |
177 | arg_names: Some(arg_names), | |
178 | ctor_ty: None, | |
179 | name: ast_variant.node.name.name, | |
180 | id: ast_util::local_def(ast_variant.node.id), | |
181 | disr_val: discriminant, | |
182 | vis: ast_variant.node.vis | |
183 | }; | |
184 | } | |
185 | } | |
186 | } | |
187 | } | |
188 | ||
189 | #[derive(Copy, Clone)] | |
190 | pub enum DtorKind { | |
191 | NoDtor, | |
192 | TraitDtor(DefId, bool) | |
193 | } | |
194 | ||
195 | impl DtorKind { | |
196 | pub fn is_present(&self) -> bool { | |
197 | match *self { | |
198 | TraitDtor(..) => true, | |
199 | _ => false | |
200 | } | |
201 | } | |
202 | ||
203 | pub fn has_drop_flag(&self) -> bool { | |
204 | match self { | |
205 | &NoDtor => false, | |
206 | &TraitDtor(_, flag) => flag | |
207 | } | |
208 | } | |
209 | } | |
210 | ||
211 | trait IntTypeExt { | |
212 | fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>; | |
213 | fn i64_to_disr(&self, val: i64) -> Option<Disr>; | |
214 | fn u64_to_disr(&self, val: u64) -> Option<Disr>; | |
215 | fn disr_incr(&self, val: Disr) -> Option<Disr>; | |
216 | fn disr_string(&self, val: Disr) -> String; | |
217 | fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr; | |
218 | } | |
219 | ||
220 | impl IntTypeExt for attr::IntType { | |
221 | fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> { | |
222 | match *self { | |
223 | SignedInt(ast::TyI8) => cx.types.i8, | |
224 | SignedInt(ast::TyI16) => cx.types.i16, | |
225 | SignedInt(ast::TyI32) => cx.types.i32, | |
226 | SignedInt(ast::TyI64) => cx.types.i64, | |
227 | SignedInt(ast::TyIs) => cx.types.isize, | |
228 | UnsignedInt(ast::TyU8) => cx.types.u8, | |
229 | UnsignedInt(ast::TyU16) => cx.types.u16, | |
230 | UnsignedInt(ast::TyU32) => cx.types.u32, | |
231 | UnsignedInt(ast::TyU64) => cx.types.u64, | |
232 | UnsignedInt(ast::TyUs) => cx.types.usize, | |
233 | } | |
234 | } | |
235 | ||
236 | fn i64_to_disr(&self, val: i64) -> Option<Disr> { | |
237 | match *self { | |
238 | SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr), | |
239 | SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr), | |
240 | SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr), | |
241 | SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr), | |
242 | UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr), | |
243 | UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr), | |
244 | UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr), | |
245 | UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr), | |
246 | ||
247 | UnsignedInt(ast::TyUs) | | |
248 | SignedInt(ast::TyIs) => unreachable!(), | |
249 | } | |
250 | } | |
251 | ||
252 | fn u64_to_disr(&self, val: u64) -> Option<Disr> { | |
253 | match *self { | |
254 | SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr), | |
255 | SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr), | |
256 | SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr), | |
257 | SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr), | |
258 | UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr), | |
259 | UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr), | |
260 | UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr), | |
261 | UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr), | |
262 | ||
263 | UnsignedInt(ast::TyUs) | | |
264 | SignedInt(ast::TyIs) => unreachable!(), | |
265 | } | |
266 | } | |
267 | ||
268 | fn disr_incr(&self, val: Disr) -> Option<Disr> { | |
269 | macro_rules! add1 { | |
270 | ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) } | |
271 | } | |
272 | match *self { | |
273 | // SignedInt repr means we *want* to reinterpret the bits | |
274 | // treating the highest bit of Disr as a sign-bit, so | |
275 | // cast to i64 before range-checking. | |
276 | SignedInt(ast::TyI8) => add1!((val as i64).to_i8()), | |
277 | SignedInt(ast::TyI16) => add1!((val as i64).to_i16()), | |
278 | SignedInt(ast::TyI32) => add1!((val as i64).to_i32()), | |
279 | SignedInt(ast::TyI64) => add1!(Some(val as i64)), | |
280 | ||
281 | UnsignedInt(ast::TyU8) => add1!(val.to_u8()), | |
282 | UnsignedInt(ast::TyU16) => add1!(val.to_u16()), | |
283 | UnsignedInt(ast::TyU32) => add1!(val.to_u32()), | |
284 | UnsignedInt(ast::TyU64) => add1!(Some(val)), | |
285 | ||
286 | UnsignedInt(ast::TyUs) | | |
287 | SignedInt(ast::TyIs) => unreachable!(), | |
288 | } | |
289 | } | |
290 | ||
291 | // This returns a String because (1.) it is only used for | |
292 | // rendering an error message and (2.) a string can represent the | |
293 | // full range from `i64::MIN` through `u64::MAX`. | |
294 | fn disr_string(&self, val: Disr) -> String { | |
295 | match *self { | |
296 | SignedInt(ast::TyI8) => format!("{}", val as i8 ), | |
297 | SignedInt(ast::TyI16) => format!("{}", val as i16), | |
298 | SignedInt(ast::TyI32) => format!("{}", val as i32), | |
299 | SignedInt(ast::TyI64) => format!("{}", val as i64), | |
300 | UnsignedInt(ast::TyU8) => format!("{}", val as u8 ), | |
301 | UnsignedInt(ast::TyU16) => format!("{}", val as u16), | |
302 | UnsignedInt(ast::TyU32) => format!("{}", val as u32), | |
303 | UnsignedInt(ast::TyU64) => format!("{}", val as u64), | |
304 | ||
305 | UnsignedInt(ast::TyUs) | | |
306 | SignedInt(ast::TyIs) => unreachable!(), | |
307 | } | |
308 | } | |
309 | ||
310 | fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr { | |
311 | macro_rules! add1 { | |
312 | ($e:expr) => { ($e).wrapping_add(1) as Disr } | |
313 | } | |
314 | let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE); | |
315 | match *self { | |
316 | SignedInt(ast::TyI8) => add1!(val as i8 ), | |
317 | SignedInt(ast::TyI16) => add1!(val as i16), | |
318 | SignedInt(ast::TyI32) => add1!(val as i32), | |
319 | SignedInt(ast::TyI64) => add1!(val as i64), | |
320 | UnsignedInt(ast::TyU8) => add1!(val as u8 ), | |
321 | UnsignedInt(ast::TyU16) => add1!(val as u16), | |
322 | UnsignedInt(ast::TyU32) => add1!(val as u32), | |
323 | UnsignedInt(ast::TyU64) => add1!(val as u64), | |
324 | ||
325 | UnsignedInt(ast::TyUs) | | |
326 | SignedInt(ast::TyIs) => unreachable!(), | |
327 | } | |
328 | } | |
329 | } | |
330 | ||
331 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | |
1a4d82fc JJ |
332 | pub enum ImplOrTraitItemContainer { |
333 | TraitContainer(ast::DefId), | |
334 | ImplContainer(ast::DefId), | |
335 | } | |
336 | ||
337 | impl ImplOrTraitItemContainer { | |
338 | pub fn id(&self) -> ast::DefId { | |
339 | match *self { | |
340 | TraitContainer(id) => id, | |
341 | ImplContainer(id) => id, | |
342 | } | |
343 | } | |
344 | } | |
345 | ||
62682a34 | 346 | #[derive(Clone)] |
1a4d82fc | 347 | pub enum ImplOrTraitItem<'tcx> { |
d9579d0f | 348 | ConstTraitItem(Rc<AssociatedConst<'tcx>>), |
1a4d82fc | 349 | MethodTraitItem(Rc<Method<'tcx>>), |
62682a34 | 350 | TypeTraitItem(Rc<AssociatedType<'tcx>>), |
1a4d82fc JJ |
351 | } |
352 | ||
353 | impl<'tcx> ImplOrTraitItem<'tcx> { | |
354 | fn id(&self) -> ImplOrTraitItemId { | |
355 | match *self { | |
d9579d0f AL |
356 | ConstTraitItem(ref associated_const) => { |
357 | ConstTraitItemId(associated_const.def_id) | |
358 | } | |
1a4d82fc JJ |
359 | MethodTraitItem(ref method) => MethodTraitItemId(method.def_id), |
360 | TypeTraitItem(ref associated_type) => { | |
361 | TypeTraitItemId(associated_type.def_id) | |
362 | } | |
363 | } | |
364 | } | |
365 | ||
366 | pub fn def_id(&self) -> ast::DefId { | |
367 | match *self { | |
d9579d0f | 368 | ConstTraitItem(ref associated_const) => associated_const.def_id, |
1a4d82fc JJ |
369 | MethodTraitItem(ref method) => method.def_id, |
370 | TypeTraitItem(ref associated_type) => associated_type.def_id, | |
371 | } | |
372 | } | |
373 | ||
374 | pub fn name(&self) -> ast::Name { | |
375 | match *self { | |
d9579d0f | 376 | ConstTraitItem(ref associated_const) => associated_const.name, |
1a4d82fc JJ |
377 | MethodTraitItem(ref method) => method.name, |
378 | TypeTraitItem(ref associated_type) => associated_type.name, | |
379 | } | |
380 | } | |
381 | ||
d9579d0f AL |
382 | pub fn vis(&self) -> ast::Visibility { |
383 | match *self { | |
384 | ConstTraitItem(ref associated_const) => associated_const.vis, | |
385 | MethodTraitItem(ref method) => method.vis, | |
386 | TypeTraitItem(ref associated_type) => associated_type.vis, | |
387 | } | |
388 | } | |
389 | ||
1a4d82fc JJ |
390 | pub fn container(&self) -> ImplOrTraitItemContainer { |
391 | match *self { | |
d9579d0f | 392 | ConstTraitItem(ref associated_const) => associated_const.container, |
1a4d82fc JJ |
393 | MethodTraitItem(ref method) => method.container, |
394 | TypeTraitItem(ref associated_type) => associated_type.container, | |
395 | } | |
396 | } | |
397 | ||
398 | pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> { | |
399 | match *self { | |
400 | MethodTraitItem(ref m) => Some((*m).clone()), | |
d9579d0f | 401 | _ => None, |
1a4d82fc JJ |
402 | } |
403 | } | |
404 | } | |
405 | ||
85aaf69f | 406 | #[derive(Clone, Copy, Debug)] |
1a4d82fc | 407 | pub enum ImplOrTraitItemId { |
d9579d0f | 408 | ConstTraitItemId(ast::DefId), |
1a4d82fc JJ |
409 | MethodTraitItemId(ast::DefId), |
410 | TypeTraitItemId(ast::DefId), | |
411 | } | |
412 | ||
413 | impl ImplOrTraitItemId { | |
414 | pub fn def_id(&self) -> ast::DefId { | |
415 | match *self { | |
d9579d0f | 416 | ConstTraitItemId(def_id) => def_id, |
1a4d82fc JJ |
417 | MethodTraitItemId(def_id) => def_id, |
418 | TypeTraitItemId(def_id) => def_id, | |
970d7e83 | 419 | } |
1a4d82fc JJ |
420 | } |
421 | } | |
422 | ||
85aaf69f | 423 | #[derive(Clone, Debug)] |
1a4d82fc JJ |
424 | pub struct Method<'tcx> { |
425 | pub name: ast::Name, | |
85aaf69f SL |
426 | pub generics: Generics<'tcx>, |
427 | pub predicates: GenericPredicates<'tcx>, | |
1a4d82fc JJ |
428 | pub fty: BareFnTy<'tcx>, |
429 | pub explicit_self: ExplicitSelfCategory, | |
430 | pub vis: ast::Visibility, | |
431 | pub def_id: ast::DefId, | |
432 | pub container: ImplOrTraitItemContainer, | |
970d7e83 | 433 | |
1a4d82fc JJ |
434 | // If this method is provided, we need to know where it came from |
435 | pub provided_source: Option<ast::DefId> | |
436 | } | |
437 | ||
438 | impl<'tcx> Method<'tcx> { | |
439 | pub fn new(name: ast::Name, | |
440 | generics: ty::Generics<'tcx>, | |
85aaf69f | 441 | predicates: GenericPredicates<'tcx>, |
1a4d82fc JJ |
442 | fty: BareFnTy<'tcx>, |
443 | explicit_self: ExplicitSelfCategory, | |
444 | vis: ast::Visibility, | |
445 | def_id: ast::DefId, | |
446 | container: ImplOrTraitItemContainer, | |
447 | provided_source: Option<ast::DefId>) | |
448 | -> Method<'tcx> { | |
970d7e83 | 449 | Method { |
1a4d82fc | 450 | name: name, |
970d7e83 | 451 | generics: generics, |
85aaf69f | 452 | predicates: predicates, |
970d7e83 LB |
453 | fty: fty, |
454 | explicit_self: explicit_self, | |
455 | vis: vis, | |
1a4d82fc JJ |
456 | def_id: def_id, |
457 | container: container, | |
458 | provided_source: provided_source | |
970d7e83 LB |
459 | } |
460 | } | |
970d7e83 | 461 | |
1a4d82fc JJ |
462 | pub fn container_id(&self) -> ast::DefId { |
463 | match self.container { | |
464 | TraitContainer(id) => id, | |
465 | ImplContainer(id) => id, | |
466 | } | |
467 | } | |
223e47cc LB |
468 | } |
469 | ||
d9579d0f AL |
470 | #[derive(Clone, Copy, Debug)] |
471 | pub struct AssociatedConst<'tcx> { | |
472 | pub name: ast::Name, | |
473 | pub ty: Ty<'tcx>, | |
474 | pub vis: ast::Visibility, | |
475 | pub def_id: ast::DefId, | |
476 | pub container: ImplOrTraitItemContainer, | |
477 | pub default: Option<ast::DefId>, | |
478 | } | |
479 | ||
85aaf69f | 480 | #[derive(Clone, Copy, Debug)] |
62682a34 | 481 | pub struct AssociatedType<'tcx> { |
1a4d82fc | 482 | pub name: ast::Name, |
62682a34 | 483 | pub ty: Option<Ty<'tcx>>, |
1a4d82fc JJ |
484 | pub vis: ast::Visibility, |
485 | pub def_id: ast::DefId, | |
486 | pub container: ImplOrTraitItemContainer, | |
223e47cc LB |
487 | } |
488 | ||
85aaf69f | 489 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
c1a9b12d | 490 | pub struct TypeAndMut<'tcx> { |
1a4d82fc JJ |
491 | pub ty: Ty<'tcx>, |
492 | pub mutbl: ast::Mutability, | |
223e47cc LB |
493 | } |
494 | ||
85aaf69f | 495 | #[derive(Clone, Copy, Debug)] |
c1a9b12d | 496 | pub struct FieldTy { |
1a4d82fc JJ |
497 | pub name: Name, |
498 | pub id: DefId, | |
499 | pub vis: ast::Visibility, | |
500 | pub origin: ast::DefId, // The DefId of the struct in which the field is declared. | |
223e47cc LB |
501 | } |
502 | ||
1a4d82fc JJ |
503 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)] |
504 | pub struct ItemVariances { | |
505 | pub types: VecPerParamSpace<Variance>, | |
506 | pub regions: VecPerParamSpace<Variance>, | |
507 | } | |
508 | ||
62682a34 | 509 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)] |
1a4d82fc JJ |
510 | pub enum Variance { |
511 | Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type | |
512 | Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell | |
513 | Contravariant, // T<A> <: T<B> iff B <: A -- e.g., function param type | |
514 | Bivariant, // T<A> <: T<B> -- e.g., unused type parameter | |
515 | } | |
516 | ||
c1a9b12d SL |
517 | impl fmt::Debug for Variance { |
518 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
519 | f.write_str(match *self { | |
520 | Covariant => "+", | |
521 | Contravariant => "-", | |
522 | Invariant => "o", | |
523 | Bivariant => "*", | |
524 | }) | |
525 | } | |
526 | } | |
527 | ||
62682a34 | 528 | #[derive(Copy, Clone)] |
1a4d82fc | 529 | pub enum AutoAdjustment<'tcx> { |
9346a6ac AL |
530 | AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type |
531 | AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer | |
532 | AdjustDerefRef(AutoDerefRef<'tcx>), | |
1a4d82fc | 533 | } |
223e47cc | 534 | |
9346a6ac AL |
535 | /// Represents coercing a pointer to a different kind of pointer - where 'kind' |
536 | /// here means either or both of raw vs borrowed vs unique and fat vs thin. | |
537 | /// | |
538 | /// We transform pointers by following the following steps in order: | |
539 | /// 1. Deref the pointer `self.autoderefs` times (may be 0). | |
540 | /// 2. If `autoref` is `Some(_)`, then take the address and produce either a | |
541 | /// `&` or `*` pointer. | |
542 | /// 3. If `unsize` is `Some(_)`, then apply the unsize transformation, | |
543 | /// which will do things like convert thin pointers to fat | |
544 | /// pointers, or convert structs containing thin pointers to | |
545 | /// structs containing fat pointers, or convert between fat | |
546 | /// pointers. We don't store the details of how the transform is | |
547 | /// done (in fact, we don't know that, because it might depend on | |
548 | /// the precise type parameters). We just store the target | |
549 | /// type. Trans figures out what has to be done at monomorphization | |
550 | /// time based on the precise source/target type at hand. | |
551 | /// | |
552 | /// To make that more concrete, here are some common scenarios: | |
553 | /// | |
554 | /// 1. The simplest cases are where the pointer is not adjusted fat vs thin. | |
555 | /// Here the pointer will be dereferenced N times (where a dereference can | |
556 | /// happen to to raw or borrowed pointers or any smart pointer which implements | |
557 | /// Deref, including Box<_>). The number of dereferences is given by | |
558 | /// `autoderefs`. It can then be auto-referenced zero or one times, indicated | |
559 | /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is | |
560 | /// None. | |
561 | /// | |
562 | /// 2. A thin-to-fat coercon involves unsizing the underlying data. We start | |
563 | /// with a thin pointer, deref a number of times, unsize the underlying data, | |
564 | /// then autoref. The 'unsize' phase may change a fixed length array to a | |
565 | /// dynamically sized one, a concrete object to a trait object, or statically | |
566 | /// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is | |
567 | /// represented by: | |
568 | /// | |
569 | /// ``` | |
570 | /// AutoDerefRef { | |
571 | /// autoderefs: 1, // &[i32; 4] -> [i32; 4] | |
572 | /// autoref: Some(AutoPtr), // [i32] -> &[i32] | |
573 | /// unsize: Some([i32]), // [i32; 4] -> [i32] | |
574 | /// } | |
575 | /// ``` | |
576 | /// | |
577 | /// Note that for a struct, the 'deep' unsizing of the struct is not recorded. | |
578 | /// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]> | |
579 | /// The autoderef and -ref are the same as in the above example, but the type | |
580 | /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about | |
581 | /// the underlying conversions from `[i32; 4]` to `[i32]`. | |
582 | /// | |
583 | /// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In | |
584 | /// that case, we have the pointer we need coming in, so there are no | |
585 | /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation. | |
586 | /// At some point, of course, `Box` should move out of the compiler, in which | |
587 | /// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> -> | |
588 | /// Box<[i32]> is represented by: | |
589 | /// | |
590 | /// ``` | |
591 | /// AutoDerefRef { | |
592 | /// autoderefs: 0, | |
593 | /// autoref: None, | |
594 | /// unsize: Some(Box<[i32]>), | |
595 | /// } | |
596 | /// ``` | |
62682a34 | 597 | #[derive(Copy, Clone)] |
1a4d82fc | 598 | pub struct AutoDerefRef<'tcx> { |
9346a6ac | 599 | /// Step 1. Apply a number of dereferences, producing an lvalue. |
c34b1796 | 600 | pub autoderefs: usize, |
223e47cc | 601 | |
9346a6ac AL |
602 | /// Step 2. Optionally produce a pointer/reference from the value. |
603 | pub autoref: Option<AutoRef<'tcx>>, | |
1a4d82fc | 604 | |
9346a6ac AL |
605 | /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to |
606 | /// `&[T]`. The stored type is the target pointer type. Note that | |
607 | /// the source could be a thin or fat pointer. | |
608 | pub unsize: Option<Ty<'tcx>>, | |
223e47cc LB |
609 | } |
610 | ||
9346a6ac AL |
611 | #[derive(Copy, Clone, PartialEq, Debug)] |
612 | pub enum AutoRef<'tcx> { | |
613 | /// Convert from T to &T. | |
614 | AutoPtr(&'tcx Region, ast::Mutability), | |
223e47cc | 615 | |
9346a6ac AL |
616 | /// Convert from T to *T. |
617 | /// Value to thin pointer. | |
618 | AutoUnsafe(ast::Mutability), | |
223e47cc LB |
619 | } |
620 | ||
d9579d0f AL |
621 | #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] |
622 | pub enum CustomCoerceUnsized { | |
623 | /// Records the index of the field being coerced. | |
624 | Struct(usize) | |
625 | } | |
626 | ||
c1a9b12d | 627 | #[derive(Clone, Copy, Debug)] |
1a4d82fc | 628 | pub struct MethodCallee<'tcx> { |
c1a9b12d SL |
629 | /// Impl method ID, for inherent methods, or trait method ID, otherwise. |
630 | pub def_id: ast::DefId, | |
1a4d82fc | 631 | pub ty: Ty<'tcx>, |
c1a9b12d | 632 | pub substs: &'tcx subst::Substs<'tcx> |
223e47cc | 633 | } |
1a4d82fc JJ |
634 | |
635 | /// With method calls, we store some extra information in | |
636 | /// side tables (i.e method_map). We use | |
637 | /// MethodCall as a key to index into these tables instead of | |
638 | /// just directly using the expression's NodeId. The reason | |
639 | /// for this being that we may apply adjustments (coercions) | |
640 | /// with the resulting expression also needing to use the | |
641 | /// side tables. The problem with this is that we don't | |
642 | /// assign a separate NodeId to this new expression | |
643 | /// and so it would clash with the base expression if both | |
644 | /// needed to add to the side tables. Thus to disambiguate | |
645 | /// we also keep track of whether there's an adjustment in | |
646 | /// our key. | |
85aaf69f | 647 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
648 | pub struct MethodCall { |
649 | pub expr_id: ast::NodeId, | |
9346a6ac | 650 | pub autoderef: u32 |
223e47cc LB |
651 | } |
652 | ||
1a4d82fc JJ |
653 | impl MethodCall { |
654 | pub fn expr(id: ast::NodeId) -> MethodCall { | |
655 | MethodCall { | |
656 | expr_id: id, | |
9346a6ac | 657 | autoderef: 0 |
1a4d82fc JJ |
658 | } |
659 | } | |
660 | ||
9346a6ac | 661 | pub fn autoderef(expr_id: ast::NodeId, autoderef: u32) -> MethodCall { |
1a4d82fc JJ |
662 | MethodCall { |
663 | expr_id: expr_id, | |
9346a6ac | 664 | autoderef: 1 + autoderef |
1a4d82fc JJ |
665 | } |
666 | } | |
223e47cc LB |
667 | } |
668 | ||
1a4d82fc JJ |
669 | // maps from an expression id that corresponds to a method call to the details |
670 | // of the method to be invoked | |
c1a9b12d | 671 | pub type MethodMap<'tcx> = FnvHashMap<MethodCall, MethodCallee<'tcx>>; |
223e47cc | 672 | |
62682a34 SL |
673 | // Contains information needed to resolve types and (in the future) look up |
674 | // the types of AST nodes. | |
675 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
c1a9b12d | 676 | pub struct CReaderCacheKey { |
62682a34 SL |
677 | pub cnum: CrateNum, |
678 | pub pos: usize, | |
679 | pub len: usize | |
970d7e83 LB |
680 | } |
681 | ||
1a4d82fc JJ |
682 | /// A restriction that certain types must be the same size. The use of |
683 | /// `transmute` gives rise to these restrictions. These generally | |
684 | /// cannot be checked until trans; therefore, each call to `transmute` | |
685 | /// will push one or more such restriction into the | |
686 | /// `transmute_restrictions` vector during `intrinsicck`. They are | |
687 | /// then checked during `trans` by the fn `check_intrinsics`. | |
c34b1796 | 688 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
689 | pub struct TransmuteRestriction<'tcx> { |
690 | /// The span whence the restriction comes. | |
691 | pub span: Span, | |
970d7e83 | 692 | |
1a4d82fc JJ |
693 | /// The type being transmuted from. |
694 | pub original_from: Ty<'tcx>, | |
970d7e83 | 695 | |
1a4d82fc JJ |
696 | /// The type being transmuted to. |
697 | pub original_to: Ty<'tcx>, | |
970d7e83 | 698 | |
1a4d82fc JJ |
699 | /// The type being transmuted from, with all type parameters |
700 | /// substituted for an arbitrary representative. Not to be shown | |
701 | /// to the end user. | |
702 | pub substituted_from: Ty<'tcx>, | |
223e47cc | 703 | |
1a4d82fc JJ |
704 | /// The type being transmuted to, with all type parameters |
705 | /// substituted for an arbitrary representative. Not to be shown | |
706 | /// to the end user. | |
707 | pub substituted_to: Ty<'tcx>, | |
223e47cc | 708 | |
1a4d82fc JJ |
709 | /// NodeId of the transmute intrinsic. |
710 | pub id: ast::NodeId, | |
223e47cc LB |
711 | } |
712 | ||
1a4d82fc JJ |
713 | /// Internal storage |
714 | pub struct CtxtArenas<'tcx> { | |
d9579d0f | 715 | // internings |
1a4d82fc JJ |
716 | type_: TypedArena<TyS<'tcx>>, |
717 | substs: TypedArena<Substs<'tcx>>, | |
718 | bare_fn: TypedArena<BareFnTy<'tcx>>, | |
719 | region: TypedArena<Region>, | |
62682a34 | 720 | stability: TypedArena<attr::Stability>, |
d9579d0f AL |
721 | |
722 | // references | |
62682a34 | 723 | trait_defs: TypedArena<TraitDef<'tcx>>, |
970d7e83 LB |
724 | } |
725 | ||
1a4d82fc JJ |
726 | impl<'tcx> CtxtArenas<'tcx> { |
727 | pub fn new() -> CtxtArenas<'tcx> { | |
728 | CtxtArenas { | |
729 | type_: TypedArena::new(), | |
730 | substs: TypedArena::new(), | |
731 | bare_fn: TypedArena::new(), | |
732 | region: TypedArena::new(), | |
62682a34 | 733 | stability: TypedArena::new(), |
d9579d0f AL |
734 | |
735 | trait_defs: TypedArena::new() | |
1a4d82fc JJ |
736 | } |
737 | } | |
223e47cc LB |
738 | } |
739 | ||
1a4d82fc JJ |
740 | pub struct CommonTypes<'tcx> { |
741 | pub bool: Ty<'tcx>, | |
742 | pub char: Ty<'tcx>, | |
c34b1796 | 743 | pub isize: Ty<'tcx>, |
1a4d82fc JJ |
744 | pub i8: Ty<'tcx>, |
745 | pub i16: Ty<'tcx>, | |
746 | pub i32: Ty<'tcx>, | |
747 | pub i64: Ty<'tcx>, | |
c34b1796 | 748 | pub usize: Ty<'tcx>, |
1a4d82fc JJ |
749 | pub u8: Ty<'tcx>, |
750 | pub u16: Ty<'tcx>, | |
751 | pub u32: Ty<'tcx>, | |
752 | pub u64: Ty<'tcx>, | |
753 | pub f32: Ty<'tcx>, | |
754 | pub f64: Ty<'tcx>, | |
755 | pub err: Ty<'tcx>, | |
756 | } | |
757 | ||
c1a9b12d SL |
758 | pub struct Tables<'tcx> { |
759 | /// Stores the types for various nodes in the AST. Note that this table | |
760 | /// is not guaranteed to be populated until after typeck. See | |
761 | /// typeck::check::fn_ctxt for details. | |
762 | pub node_types: NodeMap<Ty<'tcx>>, | |
1a4d82fc | 763 | |
c1a9b12d SL |
764 | /// Stores the type parameters which were substituted to obtain the type |
765 | /// of this node. This only applies to nodes that refer to entities | |
766 | /// parameterized by type parameters, such as generic fns, types, or | |
767 | /// other items. | |
768 | pub item_substs: NodeMap<ItemSubsts<'tcx>>, | |
769 | ||
770 | pub adjustments: NodeMap<ty::AutoAdjustment<'tcx>>, | |
771 | ||
772 | pub method_map: MethodMap<'tcx>, | |
773 | ||
774 | /// Borrows | |
775 | pub upvar_capture_map: UpvarCaptureMap, | |
776 | ||
777 | /// Records the type of each closure. The def ID is the ID of the | |
778 | /// expression defining the closure. | |
779 | pub closure_tys: DefIdMap<ClosureTy<'tcx>>, | |
780 | ||
781 | /// Records the type of each closure. The def ID is the ID of the | |
782 | /// expression defining the closure. | |
783 | pub closure_kinds: DefIdMap<ClosureKind>, | |
784 | } | |
785 | ||
786 | impl<'tcx> Tables<'tcx> { | |
787 | pub fn empty() -> Tables<'tcx> { | |
788 | Tables { | |
789 | node_types: FnvHashMap(), | |
790 | item_substs: NodeMap(), | |
791 | adjustments: NodeMap(), | |
792 | method_map: FnvHashMap(), | |
793 | upvar_capture_map: FnvHashMap(), | |
794 | closure_tys: DefIdMap(), | |
795 | closure_kinds: DefIdMap(), | |
796 | } | |
797 | } | |
798 | } | |
799 | ||
800 | /// The data structure to keep track of all the information that typechecker | |
801 | /// generates so that so that it can be reused and doesn't have to be redone | |
802 | /// later on. | |
803 | pub struct ctxt<'tcx> { | |
804 | /// The arenas that types etc are allocated from. | |
805 | arenas: &'tcx CtxtArenas<'tcx>, | |
806 | ||
807 | /// Specifically use a speedy hash algorithm for this hash map, it's used | |
808 | /// quite often. | |
1a4d82fc JJ |
809 | // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can |
810 | // queried from a HashSet. | |
811 | interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>, | |
812 | ||
813 | // FIXME as above, use a hashset if equivalent elements can be queried. | |
814 | substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>, | |
815 | bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>, | |
816 | region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>, | |
62682a34 | 817 | stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>, |
1a4d82fc JJ |
818 | |
819 | /// Common types, pre-interned for your convenience. | |
820 | pub types: CommonTypes<'tcx>, | |
821 | ||
822 | pub sess: Session, | |
823 | pub def_map: DefMap, | |
824 | ||
825 | pub named_region_map: resolve_lifetime::NamedRegionMap, | |
826 | ||
bd371182 AL |
827 | pub region_maps: RegionMaps, |
828 | ||
829 | // For each fn declared in the local crate, type check stores the | |
830 | // free-region relationships that were deduced from its where | |
831 | // clauses and parameter types. These are then read-again by | |
832 | // borrowck. (They are not used during trans, and hence are not | |
833 | // serialized or needed for cross-crate fns.) | |
834 | free_region_maps: RefCell<NodeMap<FreeRegionMap>>, | |
c1a9b12d | 835 | // FIXME: jroesch make this a refcell |
1a4d82fc | 836 | |
c1a9b12d | 837 | pub tables: RefCell<Tables<'tcx>>, |
1a4d82fc JJ |
838 | |
839 | /// Maps from a trait item to the trait item "descriptor" | |
840 | pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem<'tcx>>>, | |
841 | ||
842 | /// Maps from a trait def-id to a list of the def-ids of its trait items | |
843 | pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItemId>>>>, | |
844 | ||
845 | /// A cache for the trait_items() routine | |
846 | pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>, | |
847 | ||
62682a34 | 848 | pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>, |
d9579d0f | 849 | pub trait_defs: RefCell<DefIdMap<&'tcx TraitDef<'tcx>>>, |
1a4d82fc | 850 | |
85aaf69f SL |
851 | /// Maps from the def-id of an item (trait/struct/enum/fn) to its |
852 | /// associated predicates. | |
853 | pub predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>, | |
854 | ||
c34b1796 AL |
855 | /// Maps from the def-id of a trait to the list of |
856 | /// super-predicates. This is a subset of the full list of | |
857 | /// predicates. We store these in a separate map because we must | |
858 | /// evaluate them even during type conversion, often before the | |
859 | /// full predicates are available (note that supertraits have | |
860 | /// additional acyclicity requirements). | |
861 | pub super_predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>, | |
862 | ||
1a4d82fc | 863 | pub map: ast_map::Map<'tcx>, |
1a4d82fc JJ |
864 | pub freevars: RefCell<FreevarMap>, |
865 | pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>, | |
c1a9b12d | 866 | pub rcache: RefCell<FnvHashMap<CReaderCacheKey, Ty<'tcx>>>, |
1a4d82fc | 867 | pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>, |
c34b1796 | 868 | pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>, |
1a4d82fc JJ |
869 | pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>, |
870 | pub ty_param_defs: RefCell<NodeMap<TypeParameterDef<'tcx>>>, | |
1a4d82fc JJ |
871 | pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>, |
872 | pub lang_items: middle::lang_items::LanguageItems, | |
873 | /// A mapping of fake provided method def_ids to the default implementation | |
874 | pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>, | |
c1a9b12d | 875 | pub struct_fields: RefCell<DefIdMap<Rc<Vec<FieldTy>>>>, |
1a4d82fc JJ |
876 | |
877 | /// Maps from def-id of a type or region parameter to its | |
878 | /// (inferred) variance. | |
879 | pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>, | |
880 | ||
881 | /// True if the variance has been computed yet; false otherwise. | |
882 | pub variance_computed: Cell<bool>, | |
883 | ||
884 | /// A mapping from the def ID of an enum or struct type to the def ID | |
885 | /// of the method that implements its destructor. If the type is not | |
886 | /// present in this map, it does not have a destructor. This map is | |
887 | /// populated during the coherence phase of typechecking. | |
888 | pub destructor_for_type: RefCell<DefIdMap<ast::DefId>>, | |
889 | ||
890 | /// A method will be in this list if and only if it is a destructor. | |
891 | pub destructors: RefCell<DefIdSet>, | |
892 | ||
1a4d82fc JJ |
893 | /// Maps a DefId of a type to a list of its inherent impls. |
894 | /// Contains implementations of methods that are inherent to a type. | |
895 | /// Methods in these implementations don't need to be exported. | |
896 | pub inherent_impls: RefCell<DefIdMap<Rc<Vec<ast::DefId>>>>, | |
897 | ||
898 | /// Maps a DefId of an impl to a list of its items. | |
899 | /// Note that this contains all of the impls that we know about, | |
900 | /// including ones in other crates. It's not clear that this is the best | |
901 | /// way to do it. | |
902 | pub impl_items: RefCell<DefIdMap<Vec<ImplOrTraitItemId>>>, | |
903 | ||
904 | /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not | |
905 | /// present in this set can be warned about. | |
906 | pub used_unsafe: RefCell<NodeSet>, | |
907 | ||
908 | /// Set of nodes which mark locals as mutable which end up getting used at | |
909 | /// some point. Local variable definitions not in this set can be warned | |
910 | /// about. | |
911 | pub used_mut_nodes: RefCell<NodeSet>, | |
912 | ||
913 | /// The set of external nominal types whose implementations have been read. | |
914 | /// This is used for lazy resolution of methods. | |
915 | pub populated_external_types: RefCell<DefIdSet>, | |
d9579d0f AL |
916 | /// The set of external primitive types whose implementations have been read. |
917 | /// FIXME(arielb1): why is this separate from populated_external_types? | |
c34b1796 AL |
918 | pub populated_external_primitive_impls: RefCell<DefIdSet>, |
919 | ||
62682a34 | 920 | /// These caches are used by const_eval when decoding external constants. |
1a4d82fc JJ |
921 | pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>, |
922 | pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>, | |
62682a34 | 923 | pub extern_const_fns: RefCell<DefIdMap<ast::NodeId>>, |
1a4d82fc | 924 | |
1a4d82fc JJ |
925 | pub dependency_formats: RefCell<dependency_format::Dependencies>, |
926 | ||
1a4d82fc JJ |
927 | pub node_lint_levels: RefCell<FnvHashMap<(ast::NodeId, lint::LintId), |
928 | lint::LevelSource>>, | |
929 | ||
930 | /// The types that must be asserted to be the same size for `transmute` | |
931 | /// to be valid. We gather up these restrictions in the intrinsicck pass | |
932 | /// and check them in trans. | |
933 | pub transmute_restrictions: RefCell<Vec<TransmuteRestriction<'tcx>>>, | |
934 | ||
935 | /// Maps any item's def-id to its stability index. | |
62682a34 | 936 | pub stability: RefCell<stability::Index<'tcx>>, |
1a4d82fc JJ |
937 | |
938 | /// Caches the results of trait selection. This cache is used | |
939 | /// for things that do not have to do with the parameters in scope. | |
940 | pub selection_cache: traits::SelectionCache<'tcx>, | |
941 | ||
62682a34 SL |
942 | /// A set of predicates that have been fulfilled *somewhere*. |
943 | /// This is used to avoid duplicate work. Predicates are only | |
944 | /// added to this set when they mention only "global" names | |
945 | /// (i.e., no type or lifetime parameters). | |
946 | pub fulfilled_predicates: RefCell<traits::FulfilledPredicates<'tcx>>, | |
947 | ||
1a4d82fc JJ |
948 | /// Caches the representation hints for struct definitions. |
949 | pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>, | |
950 | ||
85aaf69f SL |
951 | /// Maps Expr NodeId's to their constant qualification. |
952 | pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>, | |
d9579d0f AL |
953 | |
954 | /// Caches CoerceUnsized kinds for impls on custom types. | |
955 | pub custom_coerce_unsized_kinds: RefCell<DefIdMap<CustomCoerceUnsized>>, | |
62682a34 SL |
956 | |
957 | /// Maps a cast expression to its kind. This is keyed on the | |
958 | /// *from* expression of the cast, not the cast itself. | |
959 | pub cast_kinds: RefCell<NodeMap<cast::CastKind>>, | |
c1a9b12d SL |
960 | |
961 | /// Maps Fn items to a collection of fragment infos. | |
962 | /// | |
963 | /// The main goal is to identify data (each of which may be moved | |
964 | /// or assigned) whose subparts are not moved nor assigned | |
965 | /// (i.e. their state is *unfragmented*) and corresponding ast | |
966 | /// nodes where the path to that data is moved or assigned. | |
967 | /// | |
968 | /// In the long term, unfragmented values will have their | |
969 | /// destructor entirely driven by a single stack-local drop-flag, | |
970 | /// and their parents, the collections of the unfragmented values | |
971 | /// (or more simply, "fragmented values"), are mapped to the | |
972 | /// corresponding collections of stack-local drop-flags. | |
973 | /// | |
974 | /// (However, in the short term that is not the case; e.g. some | |
975 | /// unfragmented paths still need to be zeroed, namely when they | |
976 | /// reference parent data from an outer scope that was not | |
977 | /// entirely moved, and therefore that needs to be zeroed so that | |
978 | /// we do not get double-drop when we hit the end of the parent | |
979 | /// scope.) | |
980 | /// | |
981 | /// Also: currently the table solely holds keys for node-ids of | |
982 | /// unfragmented values (see `FragmentInfo` enum definition), but | |
983 | /// longer-term we will need to also store mappings from | |
984 | /// fragmented data to the set of unfragmented pieces that | |
985 | /// constitute it. | |
986 | pub fragment_infos: RefCell<DefIdMap<Vec<FragmentInfo>>>, | |
987 | } | |
988 | ||
989 | /// Describes the fragment-state associated with a NodeId. | |
990 | /// | |
991 | /// Currently only unfragmented paths have entries in the table, | |
992 | /// but longer-term this enum is expected to expand to also | |
993 | /// include data for fragmented paths. | |
994 | #[derive(Copy, Clone, Debug)] | |
995 | pub enum FragmentInfo { | |
996 | Moved { var: NodeId, move_expr: NodeId }, | |
997 | Assigned { var: NodeId, assign_expr: NodeId, assignee_id: NodeId }, | |
1a4d82fc JJ |
998 | } |
999 | ||
c34b1796 | 1000 | impl<'tcx> ctxt<'tcx> { |
c1a9b12d SL |
1001 | pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> { |
1002 | fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<Ty<'tcx>> { | |
1003 | &tables.node_types | |
1004 | } | |
1005 | ||
1006 | Ref::map(self.tables.borrow(), projection) | |
1007 | } | |
1008 | ||
c34b1796 | 1009 | pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) { |
c1a9b12d | 1010 | self.tables.borrow_mut().node_types.insert(id, ty); |
c34b1796 | 1011 | } |
bd371182 | 1012 | |
d9579d0f AL |
1013 | pub fn intern_trait_def(&self, def: TraitDef<'tcx>) -> &'tcx TraitDef<'tcx> { |
1014 | let did = def.trait_ref.def_id; | |
1015 | let interned = self.arenas.trait_defs.alloc(def); | |
1016 | self.trait_defs.borrow_mut().insert(did, interned); | |
1017 | interned | |
1018 | } | |
1019 | ||
62682a34 SL |
1020 | pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability { |
1021 | if let Some(st) = self.stability_interner.borrow().get(&stab) { | |
1022 | return st; | |
1023 | } | |
1024 | ||
1025 | let interned = self.arenas.stability.alloc(stab); | |
1026 | self.stability_interner.borrow_mut().insert(interned, interned); | |
1027 | interned | |
1028 | } | |
1029 | ||
bd371182 AL |
1030 | pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) { |
1031 | self.free_region_maps.borrow_mut() | |
1032 | .insert(id, map); | |
1033 | } | |
1034 | ||
1035 | pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap { | |
1036 | self.free_region_maps.borrow()[&id].clone() | |
1037 | } | |
62682a34 SL |
1038 | |
1039 | pub fn lift<T: ?Sized + Lift<'tcx>>(&self, value: &T) -> Option<T::Lifted> { | |
1040 | value.lift_to_tcx(self) | |
1041 | } | |
1042 | } | |
1043 | ||
1044 | /// A trait implemented for all X<'a> types which can be safely and | |
1045 | /// efficiently converted to X<'tcx> as long as they are part of the | |
1046 | /// provided ty::ctxt<'tcx>. | |
1047 | /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx> | |
1048 | /// by looking them up in their respective interners. | |
1049 | /// None is returned if the value or one of the components is not part | |
1050 | /// of the provided context. | |
1051 | /// For Ty, None can be returned if either the type interner doesn't | |
1052 | /// contain the TypeVariants key or if the address of the interned | |
1053 | /// pointer differs. The latter case is possible if a primitive type, | |
1054 | /// e.g. `()` or `u8`, was interned in a different context. | |
1055 | pub trait Lift<'tcx> { | |
1056 | type Lifted; | |
1057 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted>; | |
1058 | } | |
1059 | ||
1060 | impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) { | |
1061 | type Lifted = (A::Lifted, B::Lifted); | |
1062 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> { | |
1063 | tcx.lift(&self.0).and_then(|a| tcx.lift(&self.1).map(|b| (a, b))) | |
1064 | } | |
1065 | } | |
1066 | ||
1067 | impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] { | |
1068 | type Lifted = Vec<T::Lifted>; | |
1069 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> { | |
1070 | let mut result = Vec::with_capacity(self.len()); | |
1071 | for x in self { | |
1072 | if let Some(value) = tcx.lift(x) { | |
1073 | result.push(value); | |
1074 | } else { | |
1075 | return None; | |
1076 | } | |
1077 | } | |
1078 | Some(result) | |
1079 | } | |
1080 | } | |
1081 | ||
1082 | impl<'tcx> Lift<'tcx> for Region { | |
1083 | type Lifted = Self; | |
1084 | fn lift_to_tcx(&self, _: &ctxt<'tcx>) -> Option<Region> { | |
1085 | Some(*self) | |
1086 | } | |
1087 | } | |
1088 | ||
1089 | impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { | |
1090 | type Lifted = Ty<'tcx>; | |
1091 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Ty<'tcx>> { | |
1092 | if let Some(&ty) = tcx.interner.borrow().get(&self.sty) { | |
1093 | if *self as *const _ == ty as *const _ { | |
1094 | return Some(ty); | |
1095 | } | |
1096 | } | |
1097 | None | |
1098 | } | |
1099 | } | |
1100 | ||
1101 | impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { | |
1102 | type Lifted = &'tcx Substs<'tcx>; | |
1103 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<&'tcx Substs<'tcx>> { | |
1104 | if let Some(&substs) = tcx.substs_interner.borrow().get(*self) { | |
1105 | if *self as *const _ == substs as *const _ { | |
1106 | return Some(substs); | |
1107 | } | |
1108 | } | |
1109 | None | |
1110 | } | |
1111 | } | |
1112 | ||
1113 | impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> { | |
1114 | type Lifted = TraitRef<'tcx>; | |
1115 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<TraitRef<'tcx>> { | |
1116 | tcx.lift(&self.substs).map(|substs| TraitRef { | |
1117 | def_id: self.def_id, | |
1118 | substs: substs | |
1119 | }) | |
1120 | } | |
1121 | } | |
1122 | ||
1123 | impl<'a, 'tcx> Lift<'tcx> for TraitPredicate<'a> { | |
1124 | type Lifted = TraitPredicate<'tcx>; | |
1125 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<TraitPredicate<'tcx>> { | |
1126 | tcx.lift(&self.trait_ref).map(|trait_ref| TraitPredicate { | |
1127 | trait_ref: trait_ref | |
1128 | }) | |
1129 | } | |
1130 | } | |
1131 | ||
1132 | impl<'a, 'tcx> Lift<'tcx> for EquatePredicate<'a> { | |
1133 | type Lifted = EquatePredicate<'tcx>; | |
1134 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<EquatePredicate<'tcx>> { | |
1135 | tcx.lift(&(self.0, self.1)).map(|(a, b)| EquatePredicate(a, b)) | |
1136 | } | |
1137 | } | |
1138 | ||
1139 | impl<'tcx, A: Copy+Lift<'tcx>, B: Copy+Lift<'tcx>> Lift<'tcx> for OutlivesPredicate<A, B> { | |
1140 | type Lifted = OutlivesPredicate<A::Lifted, B::Lifted>; | |
1141 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> { | |
1142 | tcx.lift(&(self.0, self.1)).map(|(a, b)| OutlivesPredicate(a, b)) | |
1143 | } | |
1144 | } | |
1145 | ||
1146 | impl<'a, 'tcx> Lift<'tcx> for ProjectionPredicate<'a> { | |
1147 | type Lifted = ProjectionPredicate<'tcx>; | |
1148 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<ProjectionPredicate<'tcx>> { | |
1149 | tcx.lift(&(self.projection_ty.trait_ref, self.ty)).map(|(trait_ref, ty)| { | |
1150 | ProjectionPredicate { | |
1151 | projection_ty: ProjectionTy { | |
1152 | trait_ref: trait_ref, | |
1153 | item_name: self.projection_ty.item_name | |
1154 | }, | |
1155 | ty: ty | |
1156 | } | |
1157 | }) | |
1158 | } | |
1159 | } | |
1160 | ||
1161 | impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Binder<T> { | |
1162 | type Lifted = Binder<T::Lifted>; | |
1163 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> { | |
1164 | tcx.lift(&self.0).map(|x| Binder(x)) | |
1165 | } | |
1166 | } | |
1167 | ||
1168 | pub mod tls { | |
1169 | use ast_map; | |
1170 | use middle::ty; | |
1171 | use session::Session; | |
1172 | ||
1173 | use std::fmt; | |
1174 | use syntax::ast; | |
1175 | use syntax::codemap; | |
1176 | ||
1177 | /// Marker type used for the scoped TLS slot. | |
1178 | /// The type context cannot be used directly because the scoped TLS | |
1179 | /// in libstd doesn't allow types generic over lifetimes. | |
1180 | struct ThreadLocalTyCx; | |
1181 | ||
1182 | scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx); | |
1183 | ||
1184 | fn def_id_debug(def_id: ast::DefId, f: &mut fmt::Formatter) -> fmt::Result { | |
1185 | // Unfortunately, there seems to be no way to attempt to print | |
1186 | // a path for a def-id, so I'll just make a best effort for now | |
1187 | // and otherwise fallback to just printing the crate/node pair | |
1188 | with(|tcx| { | |
1189 | if def_id.krate == ast::LOCAL_CRATE { | |
1190 | match tcx.map.find(def_id.node) { | |
1191 | Some(ast_map::NodeItem(..)) | | |
1192 | Some(ast_map::NodeForeignItem(..)) | | |
1193 | Some(ast_map::NodeImplItem(..)) | | |
1194 | Some(ast_map::NodeTraitItem(..)) | | |
1195 | Some(ast_map::NodeVariant(..)) | | |
1196 | Some(ast_map::NodeStructCtor(..)) => { | |
c1a9b12d | 1197 | return write!(f, "{}", tcx.item_path_str(def_id)); |
62682a34 SL |
1198 | } |
1199 | _ => {} | |
1200 | } | |
1201 | } | |
1202 | Ok(()) | |
1203 | }) | |
1204 | } | |
1205 | ||
1206 | fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result { | |
1207 | with(|tcx| { | |
1208 | write!(f, "{}", tcx.sess.codemap().span_to_string(span)) | |
1209 | }) | |
1210 | } | |
1211 | ||
1212 | pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F) | |
1213 | -> (Session, R) { | |
1214 | let result = ast::DEF_ID_DEBUG.with(|def_id_dbg| { | |
1215 | codemap::SPAN_DEBUG.with(|span_dbg| { | |
1216 | let original_def_id_debug = def_id_dbg.get(); | |
1217 | def_id_dbg.set(def_id_debug); | |
1218 | let original_span_debug = span_dbg.get(); | |
1219 | span_dbg.set(span_debug); | |
1220 | let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx; | |
1221 | let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx)); | |
1222 | def_id_dbg.set(original_def_id_debug); | |
1223 | span_dbg.set(original_span_debug); | |
1224 | result | |
1225 | }) | |
1226 | }); | |
1227 | (tcx.sess, result) | |
1228 | } | |
1229 | ||
1230 | pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R { | |
1231 | TLS_TCX.with(|tcx| f(unsafe { &*(tcx as *const _ as *const ty::ctxt) })) | |
1232 | } | |
c34b1796 AL |
1233 | } |
1234 | ||
1a4d82fc JJ |
1235 | // Flags that we track on types. These flags are propagated upwards |
1236 | // through the type during type construction, so that we can quickly | |
1237 | // check whether the type has various kinds of types in it without | |
1238 | // recursing over the type itself. | |
1239 | bitflags! { | |
1240 | flags TypeFlags: u32 { | |
62682a34 SL |
1241 | const HAS_PARAMS = 1 << 0, |
1242 | const HAS_SELF = 1 << 1, | |
1243 | const HAS_TY_INFER = 1 << 2, | |
1244 | const HAS_RE_INFER = 1 << 3, | |
1245 | const HAS_RE_EARLY_BOUND = 1 << 4, | |
1246 | const HAS_FREE_REGIONS = 1 << 5, | |
1247 | const HAS_TY_ERR = 1 << 6, | |
1248 | const HAS_PROJECTION = 1 << 7, | |
1249 | const HAS_TY_CLOSURE = 1 << 8, | |
1250 | ||
1251 | // true if there are "names" of types and regions and so forth | |
1252 | // that are local to a particular fn | |
1253 | const HAS_LOCAL_NAMES = 1 << 9, | |
1254 | ||
1255 | const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | | |
1256 | TypeFlags::HAS_SELF.bits | | |
1257 | TypeFlags::HAS_RE_EARLY_BOUND.bits, | |
1258 | ||
1259 | // Flags representing the nominal content of a type, | |
1260 | // computed by FlagsComputation. If you add a new nominal | |
1261 | // flag, it should be added here too. | |
1262 | const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits | | |
d9579d0f | 1263 | TypeFlags::HAS_SELF.bits | |
62682a34 SL |
1264 | TypeFlags::HAS_TY_INFER.bits | |
1265 | TypeFlags::HAS_RE_INFER.bits | | |
1266 | TypeFlags::HAS_RE_EARLY_BOUND.bits | | |
1267 | TypeFlags::HAS_FREE_REGIONS.bits | | |
1268 | TypeFlags::HAS_TY_ERR.bits | | |
1269 | TypeFlags::HAS_PROJECTION.bits | | |
1270 | TypeFlags::HAS_TY_CLOSURE.bits | | |
1271 | TypeFlags::HAS_LOCAL_NAMES.bits, | |
1272 | ||
1273 | // Caches for type_is_sized, type_moves_by_default | |
1274 | const SIZEDNESS_CACHED = 1 << 16, | |
1275 | const IS_SIZED = 1 << 17, | |
1276 | const MOVENESS_CACHED = 1 << 18, | |
1277 | const MOVES_BY_DEFAULT = 1 << 19, | |
1a4d82fc JJ |
1278 | } |
1279 | } | |
1280 | ||
1281 | macro_rules! sty_debug_print { | |
1282 | ($ctxt: expr, $($variant: ident),*) => {{ | |
1283 | // curious inner module to allow variant names to be used as | |
1284 | // variable names. | |
62682a34 | 1285 | #[allow(non_snake_case)] |
1a4d82fc JJ |
1286 | mod inner { |
1287 | use middle::ty; | |
c34b1796 | 1288 | #[derive(Copy, Clone)] |
1a4d82fc | 1289 | struct DebugStat { |
c34b1796 AL |
1290 | total: usize, |
1291 | region_infer: usize, | |
1292 | ty_infer: usize, | |
1293 | both_infer: usize, | |
1a4d82fc | 1294 | } |
223e47cc | 1295 | |
1a4d82fc JJ |
1296 | pub fn go(tcx: &ty::ctxt) { |
1297 | let mut total = DebugStat { | |
1298 | total: 0, | |
1299 | region_infer: 0, ty_infer: 0, both_infer: 0, | |
1300 | }; | |
1301 | $(let mut $variant = total;)* | |
1302 | ||
1303 | ||
62682a34 | 1304 | for (_, t) in tcx.interner.borrow().iter() { |
1a4d82fc | 1305 | let variant = match t.sty { |
62682a34 SL |
1306 | ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | |
1307 | ty::TyFloat(..) | ty::TyStr => continue, | |
1308 | ty::TyError => /* unimportant */ continue, | |
1a4d82fc JJ |
1309 | $(ty::$variant(..) => &mut $variant,)* |
1310 | }; | |
62682a34 SL |
1311 | let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER); |
1312 | let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER); | |
1a4d82fc JJ |
1313 | |
1314 | variant.total += 1; | |
1315 | total.total += 1; | |
1316 | if region { total.region_infer += 1; variant.region_infer += 1 } | |
1317 | if ty { total.ty_infer += 1; variant.ty_infer += 1 } | |
1318 | if region && ty { total.both_infer += 1; variant.both_infer += 1 } | |
1319 | } | |
1320 | println!("Ty interner total ty region both"); | |
1321 | $(println!(" {:18}: {uses:6} {usespc:4.1}%, \ | |
1322 | {ty:4.1}% {region:5.1}% {both:4.1}%", | |
1323 | stringify!($variant), | |
1324 | uses = $variant.total, | |
1325 | usespc = $variant.total as f64 * 100.0 / total.total as f64, | |
1326 | ty = $variant.ty_infer as f64 * 100.0 / total.total as f64, | |
1327 | region = $variant.region_infer as f64 * 100.0 / total.total as f64, | |
1328 | both = $variant.both_infer as f64 * 100.0 / total.total as f64); | |
1329 | )* | |
1330 | println!(" total {uses:6} \ | |
1331 | {ty:4.1}% {region:5.1}% {both:4.1}%", | |
1332 | uses = total.total, | |
1333 | ty = total.ty_infer as f64 * 100.0 / total.total as f64, | |
1334 | region = total.region_infer as f64 * 100.0 / total.total as f64, | |
1335 | both = total.both_infer as f64 * 100.0 / total.total as f64) | |
1336 | } | |
1337 | } | |
223e47cc | 1338 | |
1a4d82fc JJ |
1339 | inner::go($ctxt) |
1340 | }} | |
223e47cc LB |
1341 | } |
1342 | ||
1a4d82fc JJ |
1343 | impl<'tcx> ctxt<'tcx> { |
1344 | pub fn print_debug_stats(&self) { | |
1345 | sty_debug_print!( | |
1346 | self, | |
62682a34 SL |
1347 | TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait, |
1348 | TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection); | |
1a4d82fc JJ |
1349 | |
1350 | println!("Substs interner: #{}", self.substs_interner.borrow().len()); | |
1351 | println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len()); | |
1352 | println!("Region interner: #{}", self.region_interner.borrow().len()); | |
62682a34 | 1353 | println!("Stability interner: #{}", self.stability_interner.borrow().len()); |
1a4d82fc | 1354 | } |
223e47cc LB |
1355 | } |
1356 | ||
1a4d82fc | 1357 | pub struct TyS<'tcx> { |
62682a34 SL |
1358 | pub sty: TypeVariants<'tcx>, |
1359 | pub flags: Cell<TypeFlags>, | |
970d7e83 | 1360 | |
1a4d82fc JJ |
1361 | // the maximal depth of any bound regions appearing in this type. |
1362 | region_depth: u32, | |
970d7e83 LB |
1363 | } |
1364 | ||
85aaf69f | 1365 | impl fmt::Debug for TypeFlags { |
1a4d82fc JJ |
1366 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1367 | write!(f, "{}", self.bits) | |
1368 | } | |
970d7e83 LB |
1369 | } |
1370 | ||
1a4d82fc | 1371 | impl<'tcx> PartialEq for TyS<'tcx> { |
d9579d0f | 1372 | #[inline] |
1a4d82fc | 1373 | fn eq(&self, other: &TyS<'tcx>) -> bool { |
85aaf69f SL |
1374 | // (self as *const _) == (other as *const _) |
1375 | (self as *const TyS<'tcx>) == (other as *const TyS<'tcx>) | |
1a4d82fc | 1376 | } |
970d7e83 | 1377 | } |
1a4d82fc | 1378 | impl<'tcx> Eq for TyS<'tcx> {} |
970d7e83 | 1379 | |
85aaf69f SL |
1380 | impl<'tcx> Hash for TyS<'tcx> { |
1381 | fn hash<H: Hasher>(&self, s: &mut H) { | |
c34b1796 | 1382 | (self as *const TyS).hash(s) |
970d7e83 LB |
1383 | } |
1384 | } | |
1385 | ||
1a4d82fc | 1386 | pub type Ty<'tcx> = &'tcx TyS<'tcx>; |
223e47cc | 1387 | |
1a4d82fc JJ |
1388 | /// An entry in the type interner. |
1389 | pub struct InternedTy<'tcx> { | |
1390 | ty: Ty<'tcx> | |
223e47cc LB |
1391 | } |
1392 | ||
1a4d82fc JJ |
1393 | // NB: An InternedTy compares and hashes as a sty. |
1394 | impl<'tcx> PartialEq for InternedTy<'tcx> { | |
1395 | fn eq(&self, other: &InternedTy<'tcx>) -> bool { | |
1396 | self.ty.sty == other.ty.sty | |
1397 | } | |
223e47cc LB |
1398 | } |
1399 | ||
1a4d82fc | 1400 | impl<'tcx> Eq for InternedTy<'tcx> {} |
223e47cc | 1401 | |
85aaf69f SL |
1402 | impl<'tcx> Hash for InternedTy<'tcx> { |
1403 | fn hash<H: Hasher>(&self, s: &mut H) { | |
1404 | self.ty.sty.hash(s) | |
1405 | } | |
1406 | } | |
223e47cc | 1407 | |
62682a34 SL |
1408 | impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> { |
1409 | fn borrow<'a>(&'a self) -> &'a TypeVariants<'tcx> { | |
85aaf69f | 1410 | &self.ty.sty |
1a4d82fc | 1411 | } |
223e47cc LB |
1412 | } |
1413 | ||
85aaf69f | 1414 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
1415 | pub struct BareFnTy<'tcx> { |
1416 | pub unsafety: ast::Unsafety, | |
1417 | pub abi: abi::Abi, | |
1418 | pub sig: PolyFnSig<'tcx>, | |
223e47cc LB |
1419 | } |
1420 | ||
62682a34 | 1421 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
1422 | pub struct ClosureTy<'tcx> { |
1423 | pub unsafety: ast::Unsafety, | |
1a4d82fc | 1424 | pub abi: abi::Abi, |
85aaf69f | 1425 | pub sig: PolyFnSig<'tcx>, |
223e47cc LB |
1426 | } |
1427 | ||
85aaf69f | 1428 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
1429 | pub enum FnOutput<'tcx> { |
1430 | FnConverging(Ty<'tcx>), | |
1431 | FnDiverging | |
223e47cc LB |
1432 | } |
1433 | ||
1a4d82fc JJ |
1434 | impl<'tcx> FnOutput<'tcx> { |
1435 | pub fn diverges(&self) -> bool { | |
1436 | *self == FnDiverging | |
223e47cc | 1437 | } |
223e47cc | 1438 | |
1a4d82fc JJ |
1439 | pub fn unwrap(self) -> Ty<'tcx> { |
1440 | match self { | |
1441 | ty::FnConverging(t) => t, | |
1442 | ty::FnDiverging => unreachable!() | |
223e47cc LB |
1443 | } |
1444 | } | |
9346a6ac AL |
1445 | |
1446 | pub fn unwrap_or(self, def: Ty<'tcx>) -> Ty<'tcx> { | |
1447 | match self { | |
1448 | ty::FnConverging(t) => t, | |
1449 | ty::FnDiverging => def | |
1450 | } | |
1451 | } | |
223e47cc LB |
1452 | } |
1453 | ||
1a4d82fc JJ |
1454 | pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>; |
1455 | ||
1456 | impl<'tcx> PolyFnOutput<'tcx> { | |
1457 | pub fn diverges(&self) -> bool { | |
1458 | self.0.diverges() | |
223e47cc LB |
1459 | } |
1460 | } | |
1461 | ||
1a4d82fc JJ |
1462 | /// Signature of a function type, which I have arbitrarily |
1463 | /// decided to use to refer to the input/output types. | |
1464 | /// | |
1465 | /// - `inputs` is the list of arguments and their modes. | |
1466 | /// - `output` is the return type. | |
1467 | /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns) | |
1468 | #[derive(Clone, PartialEq, Eq, Hash)] | |
1469 | pub struct FnSig<'tcx> { | |
1470 | pub inputs: Vec<Ty<'tcx>>, | |
1471 | pub output: FnOutput<'tcx>, | |
1472 | pub variadic: bool | |
223e47cc LB |
1473 | } |
1474 | ||
1a4d82fc | 1475 | pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>; |
223e47cc | 1476 | |
1a4d82fc JJ |
1477 | impl<'tcx> PolyFnSig<'tcx> { |
1478 | pub fn inputs(&self) -> ty::Binder<Vec<Ty<'tcx>>> { | |
c34b1796 | 1479 | self.map_bound_ref(|fn_sig| fn_sig.inputs.clone()) |
223e47cc | 1480 | } |
c34b1796 AL |
1481 | pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> { |
1482 | self.map_bound_ref(|fn_sig| fn_sig.inputs[index]) | |
1a4d82fc JJ |
1483 | } |
1484 | pub fn output(&self) -> ty::Binder<FnOutput<'tcx>> { | |
c34b1796 | 1485 | self.map_bound_ref(|fn_sig| fn_sig.output.clone()) |
1a4d82fc JJ |
1486 | } |
1487 | pub fn variadic(&self) -> bool { | |
c34b1796 | 1488 | self.skip_binder().variadic |
1a4d82fc JJ |
1489 | } |
1490 | } | |
1491 | ||
62682a34 | 1492 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
1493 | pub struct ParamTy { |
1494 | pub space: subst::ParamSpace, | |
1495 | pub idx: u32, | |
1496 | pub name: ast::Name, | |
223e47cc LB |
1497 | } |
1498 | ||
1a4d82fc JJ |
1499 | /// A [De Bruijn index][dbi] is a standard means of representing |
1500 | /// regions (and perhaps later types) in a higher-ranked setting. In | |
1501 | /// particular, imagine a type like this: | |
1502 | /// | |
c34b1796 | 1503 | /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) |
1a4d82fc JJ |
1504 | /// ^ ^ | | | |
1505 | /// | | | | | | |
1506 | /// | +------------+ 1 | | | |
1507 | /// | | | | |
1508 | /// +--------------------------------+ 2 | | |
1509 | /// | | | |
1510 | /// +------------------------------------------+ 1 | |
223e47cc | 1511 | /// |
1a4d82fc JJ |
1512 | /// In this type, there are two binders (the outer fn and the inner |
1513 | /// fn). We need to be able to determine, for any given region, which | |
1514 | /// fn type it is bound by, the inner or the outer one. There are | |
1515 | /// various ways you can do this, but a De Bruijn index is one of the | |
1516 | /// more convenient and has some nice properties. The basic idea is to | |
1517 | /// count the number of binders, inside out. Some examples should help | |
1518 | /// clarify what I mean. | |
223e47cc | 1519 | /// |
c34b1796 | 1520 | /// Let's start with the reference type `&'b isize` that is the first |
1a4d82fc JJ |
1521 | /// argument to the inner function. This region `'b` is assigned a De |
1522 | /// Bruijn index of 1, meaning "the innermost binder" (in this case, a | |
1523 | /// fn). The region `'a` that appears in the second argument type (`&'a | |
c34b1796 | 1524 | /// isize`) would then be assigned a De Bruijn index of 2, meaning "the |
1a4d82fc JJ |
1525 | /// second-innermost binder". (These indices are written on the arrays |
1526 | /// in the diagram). | |
223e47cc | 1527 | /// |
1a4d82fc JJ |
1528 | /// What is interesting is that De Bruijn index attached to a particular |
1529 | /// variable will vary depending on where it appears. For example, | |
1530 | /// the final type `&'a char` also refers to the region `'a` declared on | |
1531 | /// the outermost fn. But this time, this reference is not nested within | |
1532 | /// any other binders (i.e., it is not an argument to the inner fn, but | |
1533 | /// rather the outer one). Therefore, in this case, it is assigned a | |
1534 | /// De Bruijn index of 1, because the innermost binder in that location | |
1535 | /// is the outer fn. | |
1536 | /// | |
1537 | /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index | |
85aaf69f | 1538 | #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)] |
1a4d82fc JJ |
1539 | pub struct DebruijnIndex { |
1540 | // We maintain the invariant that this is never 0. So 1 indicates | |
1541 | // the innermost binder. To ensure this, create with `DebruijnIndex::new`. | |
1542 | pub depth: u32, | |
223e47cc LB |
1543 | } |
1544 | ||
1a4d82fc | 1545 | /// Representation of regions: |
62682a34 | 1546 | #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Copy)] |
1a4d82fc JJ |
1547 | pub enum Region { |
1548 | // Region bound in a type or fn declaration which will be | |
1549 | // substituted 'early' -- that is, at the same time when type | |
1550 | // parameters are substituted. | |
9346a6ac | 1551 | ReEarlyBound(EarlyBoundRegion), |
1a4d82fc JJ |
1552 | |
1553 | // Region bound in a function scope, which will be substituted when the | |
1554 | // function is called. | |
1555 | ReLateBound(DebruijnIndex, BoundRegion), | |
970d7e83 | 1556 | |
1a4d82fc JJ |
1557 | /// When checking a function body, the types of all arguments and so forth |
1558 | /// that refer to bound region parameters are modified to refer to free | |
1559 | /// region parameters. | |
1560 | ReFree(FreeRegion), | |
223e47cc | 1561 | |
85aaf69f SL |
1562 | /// A concrete region naming some statically determined extent |
1563 | /// (e.g. an expression or sequence of statements) within the | |
1564 | /// current function. | |
1a4d82fc | 1565 | ReScope(region::CodeExtent), |
223e47cc | 1566 | |
1a4d82fc JJ |
1567 | /// Static data that has an "infinite" lifetime. Top in the region lattice. |
1568 | ReStatic, | |
223e47cc | 1569 | |
1a4d82fc JJ |
1570 | /// A region variable. Should not exist after typeck. |
1571 | ReInfer(InferRegion), | |
970d7e83 | 1572 | |
1a4d82fc JJ |
1573 | /// Empty lifetime is for data that is never accessed. |
1574 | /// Bottom in the region lattice. We treat ReEmpty somewhat | |
1575 | /// specially; at least right now, we do not generate instances of | |
1576 | /// it during the GLB computations, but rather | |
1577 | /// generate an error instead. This is to improve error messages. | |
1578 | /// The only way to get an instance of ReEmpty is to have a region | |
1579 | /// variable with no constraints. | |
1580 | ReEmpty, | |
1581 | } | |
1582 | ||
9346a6ac AL |
1583 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] |
1584 | pub struct EarlyBoundRegion { | |
1585 | pub param_id: ast::NodeId, | |
1586 | pub space: subst::ParamSpace, | |
1587 | pub index: u32, | |
1588 | pub name: ast::Name, | |
1589 | } | |
1590 | ||
1a4d82fc JJ |
1591 | /// Upvars do not get their own node-id. Instead, we use the pair of |
1592 | /// the original var id (that is, the root variable that is referenced | |
1593 | /// by the upvar) and the id of the closure expression. | |
62682a34 | 1594 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
1595 | pub struct UpvarId { |
1596 | pub var_id: ast::NodeId, | |
1597 | pub closure_expr_id: ast::NodeId, | |
1598 | } | |
1599 | ||
85aaf69f | 1600 | #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)] |
1a4d82fc JJ |
1601 | pub enum BorrowKind { |
1602 | /// Data must be immutable and is aliasable. | |
1603 | ImmBorrow, | |
1604 | ||
1605 | /// Data must be immutable but not aliasable. This kind of borrow | |
1606 | /// cannot currently be expressed by the user and is used only in | |
1607 | /// implicit closure bindings. It is needed when you the closure | |
1608 | /// is borrowing or mutating a mutable referent, e.g.: | |
1609 | /// | |
c34b1796 | 1610 | /// let x: &mut isize = ...; |
1a4d82fc JJ |
1611 | /// let y = || *x += 5; |
1612 | /// | |
1613 | /// If we were to try to translate this closure into a more explicit | |
1614 | /// form, we'd encounter an error with the code as written: | |
1615 | /// | |
c34b1796 AL |
1616 | /// struct Env { x: & &mut isize } |
1617 | /// let x: &mut isize = ...; | |
1a4d82fc JJ |
1618 | /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn |
1619 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } | |
1620 | /// | |
1621 | /// This is then illegal because you cannot mutate a `&mut` found | |
1622 | /// in an aliasable location. To solve, you'd have to translate with | |
1623 | /// an `&mut` borrow: | |
1624 | /// | |
c34b1796 AL |
1625 | /// struct Env { x: & &mut isize } |
1626 | /// let x: &mut isize = ...; | |
1a4d82fc JJ |
1627 | /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x |
1628 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } | |
1629 | /// | |
1630 | /// Now the assignment to `**env.x` is legal, but creating a | |
1631 | /// mutable pointer to `x` is not because `x` is not mutable. We | |
1632 | /// could fix this by declaring `x` as `let mut x`. This is ok in | |
1633 | /// user code, if awkward, but extra weird for closures, since the | |
1634 | /// borrow is hidden. | |
1635 | /// | |
1636 | /// So we introduce a "unique imm" borrow -- the referent is | |
1637 | /// immutable, but not aliasable. This solves the problem. For | |
1638 | /// simplicity, we don't give users the way to express this | |
1639 | /// borrow, it's just used when translating closures. | |
1640 | UniqueImmBorrow, | |
1641 | ||
1642 | /// Data is mutable and not aliasable. | |
1643 | MutBorrow | |
1644 | } | |
1645 | ||
85aaf69f SL |
1646 | /// Information describing the capture of an upvar. This is computed |
1647 | /// during `typeck`, specifically by `regionck`. | |
1648 | #[derive(PartialEq, Clone, RustcEncodable, RustcDecodable, Debug, Copy)] | |
1649 | pub enum UpvarCapture { | |
1650 | /// Upvar is captured by value. This is always true when the | |
1651 | /// closure is labeled `move`, but can also be true in other cases | |
1652 | /// depending on inference. | |
1653 | ByValue, | |
1654 | ||
1655 | /// Upvar is captured by reference. | |
1656 | ByRef(UpvarBorrow), | |
1657 | } | |
1658 | ||
62682a34 | 1659 | #[derive(PartialEq, Clone, RustcEncodable, RustcDecodable, Copy)] |
1a4d82fc | 1660 | pub struct UpvarBorrow { |
85aaf69f SL |
1661 | /// The kind of borrow: by-ref upvars have access to shared |
1662 | /// immutable borrows, which are not part of the normal language | |
1663 | /// syntax. | |
1a4d82fc | 1664 | pub kind: BorrowKind, |
85aaf69f SL |
1665 | |
1666 | /// Region of the resulting reference. | |
1a4d82fc JJ |
1667 | pub region: ty::Region, |
1668 | } | |
1669 | ||
85aaf69f | 1670 | pub type UpvarCaptureMap = FnvHashMap<UpvarId, UpvarCapture>; |
223e47cc | 1671 | |
c1a9b12d SL |
1672 | #[derive(Copy, Clone)] |
1673 | pub struct ClosureUpvar<'tcx> { | |
1674 | pub def: def::Def, | |
1675 | pub span: Span, | |
1676 | pub ty: Ty<'tcx>, | |
1677 | } | |
62682a34 | 1678 | |
c1a9b12d | 1679 | impl Region { |
1a4d82fc JJ |
1680 | pub fn is_bound(&self) -> bool { |
1681 | match *self { | |
1682 | ty::ReEarlyBound(..) => true, | |
1683 | ty::ReLateBound(..) => true, | |
1684 | _ => false | |
223e47cc LB |
1685 | } |
1686 | } | |
223e47cc | 1687 | |
1a4d82fc JJ |
1688 | pub fn escapes_depth(&self, depth: u32) -> bool { |
1689 | match *self { | |
1690 | ty::ReLateBound(debruijn, _) => debruijn.depth > depth, | |
1691 | _ => false, | |
1692 | } | |
970d7e83 | 1693 | } |
c1a9b12d SL |
1694 | |
1695 | /// Returns the depth of `self` from the (1-based) binding level `depth` | |
1696 | pub fn from_depth(&self, depth: u32) -> Region { | |
1697 | match *self { | |
1698 | ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex { | |
1699 | depth: debruijn.depth - (depth - 1) | |
1700 | }, r), | |
1701 | r => r | |
1702 | } | |
1703 | } | |
970d7e83 LB |
1704 | } |
1705 | ||
1a4d82fc | 1706 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, |
62682a34 | 1707 | RustcEncodable, RustcDecodable, Copy)] |
1a4d82fc JJ |
1708 | /// A "free" region `fr` can be interpreted as "some region |
1709 | /// at least as big as the scope `fr.scope`". | |
1710 | pub struct FreeRegion { | |
85aaf69f | 1711 | pub scope: region::DestructionScopeData, |
1a4d82fc | 1712 | pub bound_region: BoundRegion |
223e47cc LB |
1713 | } |
1714 | ||
1a4d82fc | 1715 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, |
62682a34 | 1716 | RustcEncodable, RustcDecodable, Copy, Debug)] |
1a4d82fc JJ |
1717 | pub enum BoundRegion { |
1718 | /// An anonymous region parameter for a given fn (&T) | |
1719 | BrAnon(u32), | |
223e47cc | 1720 | |
1a4d82fc JJ |
1721 | /// Named region parameters for functions (a in &'a T) |
1722 | /// | |
1723 | /// The def-id is needed to distinguish free regions in | |
1724 | /// the event of shadowing. | |
1725 | BrNamed(ast::DefId, ast::Name), | |
223e47cc | 1726 | |
1a4d82fc JJ |
1727 | /// Fresh bound identifiers created during GLB computations. |
1728 | BrFresh(u32), | |
223e47cc | 1729 | |
1a4d82fc JJ |
1730 | // Anonymous region for the implicit env pointer parameter |
1731 | // to a closure | |
1732 | BrEnv | |
1733 | } | |
223e47cc | 1734 | |
1a4d82fc JJ |
1735 | // NB: If you change this, you'll probably want to change the corresponding |
1736 | // AST structure in libsyntax/ast.rs as well. | |
85aaf69f | 1737 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
62682a34 SL |
1738 | pub enum TypeVariants<'tcx> { |
1739 | /// The primitive boolean type. Written as `bool`. | |
1740 | TyBool, | |
1741 | ||
1742 | /// The primitive character type; holds a Unicode scalar value | |
1743 | /// (a non-surrogate code point). Written as `char`. | |
1744 | TyChar, | |
1745 | ||
1746 | /// A primitive signed integer type. For example, `i32`. | |
1747 | TyInt(ast::IntTy), | |
1748 | ||
1749 | /// A primitive unsigned integer type. For example, `u32`. | |
1750 | TyUint(ast::UintTy), | |
1751 | ||
1752 | /// A primitive floating-point type. For example, `f64`. | |
1753 | TyFloat(ast::FloatTy), | |
1754 | ||
1755 | /// An enumerated type, defined with `enum`. | |
1756 | /// | |
1757 | /// Substs here, possibly against intuition, *may* contain `TyParam`s. | |
1a4d82fc | 1758 | /// That is, even after substitution it is possible that there are type |
62682a34 SL |
1759 | /// variables. This happens when the `TyEnum` corresponds to an enum |
1760 | /// definition and not a concrete use of it. To get the correct `TyEnum` | |
1a4d82fc | 1761 | /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in |
62682a34 | 1762 | /// the `ast_ty_to_ty_cache`. This is probably true for `TyStruct` as |
c34b1796 | 1763 | /// well. |
62682a34 | 1764 | TyEnum(DefId, &'tcx Substs<'tcx>), |
1a4d82fc | 1765 | |
62682a34 SL |
1766 | /// A structure type, defined with `struct`. |
1767 | /// | |
1768 | /// See warning about substitutions for enumerated types. | |
1769 | TyStruct(DefId, &'tcx Substs<'tcx>), | |
1a4d82fc | 1770 | |
62682a34 SL |
1771 | /// `Box<T>`; this is nominally a struct in the documentation, but is |
1772 | /// special-cased internally. For example, it is possible to implicitly | |
1773 | /// move the contents of a box out of that box, and methods of any type | |
1774 | /// can have type `Box<Self>`. | |
1775 | TyBox(Ty<'tcx>), | |
1a4d82fc | 1776 | |
62682a34 SL |
1777 | /// The pointee of a string slice. Written as `str`. |
1778 | TyStr, | |
1a4d82fc | 1779 | |
62682a34 SL |
1780 | /// An array with the given length. Written as `[T; n]`. |
1781 | TyArray(Ty<'tcx>, usize), | |
1a4d82fc | 1782 | |
62682a34 SL |
1783 | /// The pointee of an array slice. Written as `[T]`. |
1784 | TySlice(Ty<'tcx>), | |
1a4d82fc | 1785 | |
62682a34 | 1786 | /// A raw pointer. Written as `*mut T` or `*const T` |
c1a9b12d | 1787 | TyRawPtr(TypeAndMut<'tcx>), |
62682a34 SL |
1788 | |
1789 | /// A reference; a pointer with an associated lifetime. Written as | |
1790 | /// `&a mut T` or `&'a T`. | |
c1a9b12d | 1791 | TyRef(&'tcx Region, TypeAndMut<'tcx>), |
62682a34 SL |
1792 | |
1793 | /// If the def-id is Some(_), then this is the type of a specific | |
1794 | /// fn item. Otherwise, if None(_), it a fn pointer type. | |
1795 | /// | |
1796 | /// FIXME: Conflating function pointers and the type of a | |
1797 | /// function is probably a terrible idea; a function pointer is a | |
1798 | /// value with a specific type, but a function can be polymorphic | |
1799 | /// or dynamically dispatched. | |
1800 | TyBareFn(Option<DefId>, &'tcx BareFnTy<'tcx>), | |
1801 | ||
1802 | /// A trait, defined with `trait`. | |
1803 | TyTrait(Box<TraitTy<'tcx>>), | |
1804 | ||
1805 | /// The anonymous type of a closure. Used to represent the type of | |
1806 | /// `|a| a`. | |
c1a9b12d | 1807 | TyClosure(DefId, Box<ClosureSubsts<'tcx>>), |
62682a34 SL |
1808 | |
1809 | /// A tuple type. For example, `(i32, bool)`. | |
1810 | TyTuple(Vec<Ty<'tcx>>), | |
1811 | ||
1812 | /// The projection of an associated type. For example, | |
1813 | /// `<T as Trait<..>>::N`. | |
1814 | TyProjection(ProjectionTy<'tcx>), | |
1815 | ||
1816 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | |
1817 | TyParam(ParamTy), | |
1818 | ||
1819 | /// A type variable used during type-checking. | |
1820 | TyInfer(InferTy), | |
1821 | ||
1822 | /// A placeholder for a type which could not be computed; this is | |
1823 | /// propagated to avoid useless error messages. | |
1824 | TyError, | |
1a4d82fc | 1825 | } |
223e47cc | 1826 | |
c1a9b12d SL |
1827 | /// A closure can be modeled as a struct that looks like: |
1828 | /// | |
1829 | /// struct Closure<'l0...'li, T0...Tj, U0...Uk> { | |
1830 | /// upvar0: U0, | |
1831 | /// ... | |
1832 | /// upvark: Uk | |
1833 | /// } | |
1834 | /// | |
1835 | /// where 'l0...'li and T0...Tj are the lifetime and type parameters | |
1836 | /// in scope on the function that defined the closure, and U0...Uk are | |
1837 | /// type parameters representing the types of its upvars (borrowed, if | |
1838 | /// appropriate). | |
1839 | /// | |
1840 | /// So, for example, given this function: | |
1841 | /// | |
1842 | /// fn foo<'a, T>(data: &'a mut T) { | |
1843 | /// do(|| data.count += 1) | |
1844 | /// } | |
1845 | /// | |
1846 | /// the type of the closure would be something like: | |
1847 | /// | |
1848 | /// struct Closure<'a, T, U0> { | |
1849 | /// data: U0 | |
1850 | /// } | |
1851 | /// | |
1852 | /// Note that the type of the upvar is not specified in the struct. | |
1853 | /// You may wonder how the impl would then be able to use the upvar, | |
1854 | /// if it doesn't know it's type? The answer is that the impl is | |
1855 | /// (conceptually) not fully generic over Closure but rather tied to | |
1856 | /// instances with the expected upvar types: | |
1857 | /// | |
1858 | /// impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> { | |
1859 | /// ... | |
1860 | /// } | |
1861 | /// | |
1862 | /// You can see that the *impl* fully specified the type of the upvar | |
1863 | /// and thus knows full well that `data` has type `&'b mut &'a mut T`. | |
1864 | /// (Here, I am assuming that `data` is mut-borrowed.) | |
1865 | /// | |
1866 | /// Now, the last question you may ask is: Why include the upvar types | |
1867 | /// as extra type parameters? The reason for this design is that the | |
1868 | /// upvar types can reference lifetimes that are internal to the | |
1869 | /// creating function. In my example above, for example, the lifetime | |
1870 | /// `'b` represents the extent of the closure itself; this is some | |
1871 | /// subset of `foo`, probably just the extent of the call to the to | |
1872 | /// `do()`. If we just had the lifetime/type parameters from the | |
1873 | /// enclosing function, we couldn't name this lifetime `'b`. Note that | |
1874 | /// there can also be lifetimes in the types of the upvars themselves, | |
1875 | /// if one of them happens to be a reference to something that the | |
1876 | /// creating fn owns. | |
1877 | /// | |
1878 | /// OK, you say, so why not create a more minimal set of parameters | |
1879 | /// that just includes the extra lifetime parameters? The answer is | |
1880 | /// primarily that it would be hard --- we don't know at the time when | |
1881 | /// we create the closure type what the full types of the upvars are, | |
1882 | /// nor do we know which are borrowed and which are not. In this | |
1883 | /// design, we can just supply a fresh type parameter and figure that | |
1884 | /// out later. | |
1885 | /// | |
1886 | /// All right, you say, but why include the type parameters from the | |
1887 | /// original function then? The answer is that trans may need them | |
1888 | /// when monomorphizing, and they may not appear in the upvars. A | |
1889 | /// closure could capture no variables but still make use of some | |
1890 | /// in-scope type parameter with a bound (e.g., if our example above | |
1891 | /// had an extra `U: Default`, and the closure called `U::default()`). | |
1892 | /// | |
1893 | /// There is another reason. This design (implicitly) prohibits | |
1894 | /// closures from capturing themselves (except via a trait | |
1895 | /// object). This simplifies closure inference considerably, since it | |
1896 | /// means that when we infer the kind of a closure or its upvars, we | |
1897 | /// don't have to handle cycles where the decisions we make for | |
1898 | /// closure C wind up influencing the decisions we ought to make for | |
1899 | /// closure C (which would then require fixed point iteration to | |
1900 | /// handle). Plus it fixes an ICE. :P | |
1901 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | |
1902 | pub struct ClosureSubsts<'tcx> { | |
1903 | /// Lifetime and type parameters from the enclosing function. | |
1904 | /// These are separated out because trans wants to pass them around | |
1905 | /// when monomorphizing. | |
1906 | pub func_substs: &'tcx Substs<'tcx>, | |
1907 | ||
1908 | /// The types of the upvars. The list parallels the freevars and | |
1909 | /// `upvar_borrows` lists. These are kept distinct so that we can | |
1910 | /// easily index into them. | |
1911 | pub upvar_tys: Vec<Ty<'tcx>> | |
1912 | } | |
1913 | ||
62682a34 SL |
1914 | #[derive(Clone, PartialEq, Eq, Hash)] |
1915 | pub struct TraitTy<'tcx> { | |
1a4d82fc JJ |
1916 | pub principal: ty::PolyTraitRef<'tcx>, |
1917 | pub bounds: ExistentialBounds<'tcx>, | |
1918 | } | |
223e47cc | 1919 | |
62682a34 | 1920 | impl<'tcx> TraitTy<'tcx> { |
1a4d82fc JJ |
1921 | pub fn principal_def_id(&self) -> ast::DefId { |
1922 | self.principal.0.def_id | |
1923 | } | |
223e47cc | 1924 | |
1a4d82fc JJ |
1925 | /// Object types don't have a self-type specified. Therefore, when |
1926 | /// we convert the principal trait-ref into a normal trait-ref, | |
1927 | /// you must give *some* self-type. A common choice is `mk_err()` | |
1928 | /// or some skolemized type. | |
1929 | pub fn principal_trait_ref_with_self_ty(&self, | |
1930 | tcx: &ctxt<'tcx>, | |
1931 | self_ty: Ty<'tcx>) | |
1932 | -> ty::PolyTraitRef<'tcx> | |
1933 | { | |
1934 | // otherwise the escaping regions would be captured by the binder | |
1935 | assert!(!self_ty.has_escaping_regions()); | |
223e47cc | 1936 | |
d9579d0f | 1937 | ty::Binder(TraitRef { |
1a4d82fc JJ |
1938 | def_id: self.principal.0.def_id, |
1939 | substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)), | |
d9579d0f | 1940 | }) |
1a4d82fc | 1941 | } |
223e47cc | 1942 | |
1a4d82fc JJ |
1943 | pub fn projection_bounds_with_self_ty(&self, |
1944 | tcx: &ctxt<'tcx>, | |
1945 | self_ty: Ty<'tcx>) | |
1946 | -> Vec<ty::PolyProjectionPredicate<'tcx>> | |
1947 | { | |
1948 | // otherwise the escaping regions would be captured by the binders | |
1949 | assert!(!self_ty.has_escaping_regions()); | |
1950 | ||
1951 | self.bounds.projection_bounds.iter() | |
1952 | .map(|in_poly_projection_predicate| { | |
1953 | let in_projection_ty = &in_poly_projection_predicate.0.projection_ty; | |
1954 | let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty)); | |
d9579d0f AL |
1955 | let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id, |
1956 | substs); | |
1a4d82fc JJ |
1957 | let projection_ty = ty::ProjectionTy { |
1958 | trait_ref: trait_ref, | |
1959 | item_name: in_projection_ty.item_name | |
1960 | }; | |
1961 | ty::Binder(ty::ProjectionPredicate { | |
1962 | projection_ty: projection_ty, | |
1963 | ty: in_poly_projection_predicate.0.ty | |
1964 | }) | |
1965 | }) | |
1966 | .collect() | |
1967 | } | |
1968 | } | |
223e47cc | 1969 | |
1a4d82fc JJ |
1970 | /// A complete reference to a trait. These take numerous guises in syntax, |
1971 | /// but perhaps the most recognizable form is in a where clause: | |
1972 | /// | |
1973 | /// T : Foo<U> | |
1974 | /// | |
1975 | /// This would be represented by a trait-reference where the def-id is the | |
1976 | /// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the | |
1977 | /// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`. | |
1978 | /// | |
1979 | /// Trait references also appear in object types like `Foo<U>`, but in | |
1980 | /// that case the `Self` parameter is absent from the substitutions. | |
1981 | /// | |
1982 | /// Note that a `TraitRef` introduces a level of region binding, to | |
1983 | /// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a | |
1984 | /// U>` or higher-ranked object types. | |
62682a34 | 1985 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
1986 | pub struct TraitRef<'tcx> { |
1987 | pub def_id: DefId, | |
1988 | pub substs: &'tcx Substs<'tcx>, | |
1989 | } | |
223e47cc | 1990 | |
d9579d0f | 1991 | pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>; |
223e47cc | 1992 | |
1a4d82fc JJ |
1993 | impl<'tcx> PolyTraitRef<'tcx> { |
1994 | pub fn self_ty(&self) -> Ty<'tcx> { | |
1995 | self.0.self_ty() | |
1996 | } | |
223e47cc | 1997 | |
1a4d82fc JJ |
1998 | pub fn def_id(&self) -> ast::DefId { |
1999 | self.0.def_id | |
2000 | } | |
223e47cc | 2001 | |
1a4d82fc JJ |
2002 | pub fn substs(&self) -> &'tcx Substs<'tcx> { |
2003 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> | |
2004 | self.0.substs | |
970d7e83 | 2005 | } |
223e47cc | 2006 | |
1a4d82fc JJ |
2007 | pub fn input_types(&self) -> &[Ty<'tcx>] { |
2008 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> | |
2009 | self.0.input_types() | |
970d7e83 | 2010 | } |
223e47cc | 2011 | |
1a4d82fc JJ |
2012 | pub fn to_poly_trait_predicate(&self) -> PolyTraitPredicate<'tcx> { |
2013 | // Note that we preserve binding levels | |
2014 | Binder(TraitPredicate { trait_ref: self.0.clone() }) | |
970d7e83 | 2015 | } |
223e47cc LB |
2016 | } |
2017 | ||
1a4d82fc | 2018 | /// Binder is a binder for higher-ranked lifetimes. It is part of the |
c34b1796 | 2019 | /// compiler's representation for things like `for<'a> Fn(&'a isize)` |
1a4d82fc JJ |
2020 | /// (which would be represented by the type `PolyTraitRef == |
2021 | /// Binder<TraitRef>`). Note that when we skolemize, instantiate, | |
85aaf69f | 2022 | /// erase, or otherwise "discharge" these bound regions, we change the |
1a4d82fc JJ |
2023 | /// type from `Binder<T>` to just `T` (see |
2024 | /// e.g. `liberate_late_bound_regions`). | |
c1a9b12d | 2025 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc | 2026 | pub struct Binder<T>(pub T); |
223e47cc | 2027 | |
c34b1796 AL |
2028 | impl<T> Binder<T> { |
2029 | /// Skips the binder and returns the "bound" value. This is a | |
2030 | /// risky thing to do because it's easy to get confused about | |
2031 | /// debruijn indices and the like. It is usually better to | |
2032 | /// discharge the binder using `no_late_bound_regions` or | |
2033 | /// `replace_late_bound_regions` or something like | |
2034 | /// that. `skip_binder` is only valid when you are either | |
2035 | /// extracting data that has nothing to do with bound regions, you | |
2036 | /// are doing some sort of test that does not involve bound | |
2037 | /// regions, or you are being very careful about your depth | |
2038 | /// accounting. | |
2039 | /// | |
2040 | /// Some examples where `skip_binder` is reasonable: | |
2041 | /// - extracting the def-id from a PolyTraitRef; | |
2042 | /// - comparing the self type of a PolyTraitRef to see if it is equal to | |
2043 | /// a type parameter `X`, since the type `X` does not reference any regions | |
2044 | pub fn skip_binder(&self) -> &T { | |
2045 | &self.0 | |
2046 | } | |
2047 | ||
2048 | pub fn as_ref(&self) -> Binder<&T> { | |
2049 | ty::Binder(&self.0) | |
2050 | } | |
2051 | ||
2052 | pub fn map_bound_ref<F,U>(&self, f: F) -> Binder<U> | |
2053 | where F: FnOnce(&T) -> U | |
2054 | { | |
2055 | self.as_ref().map_bound(f) | |
2056 | } | |
2057 | ||
2058 | pub fn map_bound<F,U>(self, f: F) -> Binder<U> | |
2059 | where F: FnOnce(T) -> U | |
2060 | { | |
2061 | ty::Binder(f(self.0)) | |
2062 | } | |
2063 | } | |
2064 | ||
1a4d82fc JJ |
2065 | #[derive(Clone, Copy, PartialEq)] |
2066 | pub enum IntVarValue { | |
2067 | IntType(ast::IntTy), | |
2068 | UintType(ast::UintTy), | |
223e47cc LB |
2069 | } |
2070 | ||
85aaf69f | 2071 | #[derive(Clone, Copy, Debug)] |
c1a9b12d | 2072 | pub struct ExpectedFound<T> { |
1a4d82fc JJ |
2073 | pub expected: T, |
2074 | pub found: T | |
223e47cc LB |
2075 | } |
2076 | ||
1a4d82fc | 2077 | // Data structures used in type unification |
c1a9b12d SL |
2078 | #[derive(Clone, Debug)] |
2079 | pub enum TypeError<'tcx> { | |
2080 | Mismatch, | |
2081 | UnsafetyMismatch(ExpectedFound<ast::Unsafety>), | |
2082 | AbiMismatch(ExpectedFound<abi::Abi>), | |
2083 | Mutability, | |
2084 | BoxMutability, | |
2085 | PtrMutability, | |
2086 | RefMutability, | |
2087 | VecMutability, | |
2088 | TupleSize(ExpectedFound<usize>), | |
2089 | FixedArraySize(ExpectedFound<usize>), | |
2090 | TyParamSize(ExpectedFound<usize>), | |
2091 | ArgCount, | |
2092 | RegionsDoesNotOutlive(Region, Region), | |
2093 | RegionsNotSame(Region, Region), | |
2094 | RegionsNoOverlap(Region, Region), | |
2095 | RegionsInsufficientlyPolymorphic(BoundRegion, Region), | |
2096 | RegionsOverlyPolymorphic(BoundRegion, Region), | |
2097 | Sorts(ExpectedFound<Ty<'tcx>>), | |
2098 | IntegerAsChar, | |
2099 | IntMismatch(ExpectedFound<IntVarValue>), | |
2100 | FloatMismatch(ExpectedFound<ast::FloatTy>), | |
2101 | Traits(ExpectedFound<ast::DefId>), | |
2102 | BuiltinBoundsMismatch(ExpectedFound<BuiltinBounds>), | |
2103 | VariadicMismatch(ExpectedFound<bool>), | |
2104 | CyclicTy, | |
2105 | ConvergenceMismatch(ExpectedFound<bool>), | |
2106 | ProjectionNameMismatched(ExpectedFound<ast::Name>), | |
2107 | ProjectionBoundsLength(ExpectedFound<usize>), | |
2108 | TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>) | |
1a4d82fc JJ |
2109 | } |
2110 | ||
1a4d82fc | 2111 | /// Bounds suitable for an existentially quantified type parameter |
62682a34 SL |
2112 | /// such as those that appear in object types or closure types. |
2113 | #[derive(PartialEq, Eq, Hash, Clone)] | |
1a4d82fc JJ |
2114 | pub struct ExistentialBounds<'tcx> { |
2115 | pub region_bound: ty::Region, | |
2116 | pub builtin_bounds: BuiltinBounds, | |
2117 | pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>, | |
223e47cc LB |
2118 | } |
2119 | ||
62682a34 SL |
2120 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
2121 | pub struct BuiltinBounds(EnumSet<BuiltinBound>); | |
223e47cc | 2122 | |
62682a34 SL |
2123 | impl BuiltinBounds { |
2124 | pub fn empty() -> BuiltinBounds { | |
2125 | BuiltinBounds(EnumSet::new()) | |
2126 | } | |
2127 | ||
2128 | pub fn iter(&self) -> enum_set::Iter<BuiltinBound> { | |
2129 | self.into_iter() | |
2130 | } | |
2131 | ||
2132 | pub fn to_predicates<'tcx>(&self, | |
2133 | tcx: &ty::ctxt<'tcx>, | |
2134 | self_ty: Ty<'tcx>) -> Vec<Predicate<'tcx>> { | |
2135 | self.iter().filter_map(|builtin_bound| | |
2136 | match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, self_ty) { | |
c1a9b12d | 2137 | Ok(trait_ref) => Some(trait_ref.to_predicate()), |
62682a34 SL |
2138 | Err(ErrorReported) => { None } |
2139 | } | |
2140 | ).collect() | |
2141 | } | |
2142 | } | |
2143 | ||
2144 | impl ops::Deref for BuiltinBounds { | |
2145 | type Target = EnumSet<BuiltinBound>; | |
2146 | fn deref(&self) -> &Self::Target { &self.0 } | |
2147 | } | |
2148 | ||
2149 | impl ops::DerefMut for BuiltinBounds { | |
2150 | fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } | |
223e47cc LB |
2151 | } |
2152 | ||
62682a34 SL |
2153 | impl<'a> IntoIterator for &'a BuiltinBounds { |
2154 | type Item = BuiltinBound; | |
2155 | type IntoIter = enum_set::Iter<BuiltinBound>; | |
2156 | fn into_iter(self) -> Self::IntoIter { | |
2157 | (**self).into_iter() | |
2158 | } | |
223e47cc LB |
2159 | } |
2160 | ||
62682a34 SL |
2161 | #[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, |
2162 | Debug, Copy)] | |
2163 | #[repr(usize)] | |
2164 | pub enum BuiltinBound { | |
2165 | Send, | |
2166 | Sized, | |
2167 | Copy, | |
2168 | Sync, | |
223e47cc LB |
2169 | } |
2170 | ||
1a4d82fc | 2171 | impl CLike for BuiltinBound { |
c34b1796 AL |
2172 | fn to_usize(&self) -> usize { |
2173 | *self as usize | |
1a4d82fc | 2174 | } |
c34b1796 | 2175 | fn from_usize(v: usize) -> BuiltinBound { |
1a4d82fc JJ |
2176 | unsafe { mem::transmute(v) } |
2177 | } | |
223e47cc LB |
2178 | } |
2179 | ||
1a4d82fc JJ |
2180 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
2181 | pub struct TyVid { | |
2182 | pub index: u32 | |
223e47cc | 2183 | } |
223e47cc | 2184 | |
1a4d82fc JJ |
2185 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
2186 | pub struct IntVid { | |
2187 | pub index: u32 | |
223e47cc LB |
2188 | } |
2189 | ||
1a4d82fc JJ |
2190 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
2191 | pub struct FloatVid { | |
2192 | pub index: u32 | |
223e47cc LB |
2193 | } |
2194 | ||
1a4d82fc JJ |
2195 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] |
2196 | pub struct RegionVid { | |
2197 | pub index: u32 | |
223e47cc LB |
2198 | } |
2199 | ||
1a4d82fc JJ |
2200 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
2201 | pub enum InferTy { | |
2202 | TyVar(TyVid), | |
2203 | IntVar(IntVid), | |
2204 | FloatVar(FloatVid), | |
223e47cc | 2205 | |
1a4d82fc JJ |
2206 | /// A `FreshTy` is one that is generated as a replacement for an |
2207 | /// unbound type variable. This is convenient for caching etc. See | |
2208 | /// `middle::infer::freshen` for more details. | |
2209 | FreshTy(u32), | |
1a4d82fc | 2210 | FreshIntTy(u32), |
d9579d0f | 2211 | FreshFloatTy(u32) |
223e47cc LB |
2212 | } |
2213 | ||
85aaf69f | 2214 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] |
1a4d82fc JJ |
2215 | pub enum UnconstrainedNumeric { |
2216 | UnconstrainedFloat, | |
2217 | UnconstrainedInt, | |
2218 | Neither, | |
2219 | } | |
223e47cc | 2220 | |
223e47cc | 2221 | |
85aaf69f | 2222 | #[derive(Clone, RustcEncodable, RustcDecodable, Eq, Hash, Debug, Copy)] |
1a4d82fc JJ |
2223 | pub enum InferRegion { |
2224 | ReVar(RegionVid), | |
2225 | ReSkolemized(u32, BoundRegion) | |
2226 | } | |
223e47cc | 2227 | |
1a4d82fc JJ |
2228 | impl cmp::PartialEq for InferRegion { |
2229 | fn eq(&self, other: &InferRegion) -> bool { | |
2230 | match ((*self), *other) { | |
2231 | (ReVar(rva), ReVar(rvb)) => { | |
2232 | rva == rvb | |
2233 | } | |
2234 | (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => { | |
2235 | rva == rvb | |
2236 | } | |
2237 | _ => false | |
2238 | } | |
2239 | } | |
2240 | fn ne(&self, other: &InferRegion) -> bool { | |
2241 | !((*self) == (*other)) | |
2242 | } | |
2243 | } | |
223e47cc | 2244 | |
85aaf69f | 2245 | impl fmt::Debug for TyVid { |
62682a34 | 2246 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1a4d82fc JJ |
2247 | write!(f, "_#{}t", self.index) |
2248 | } | |
223e47cc LB |
2249 | } |
2250 | ||
85aaf69f | 2251 | impl fmt::Debug for IntVid { |
1a4d82fc JJ |
2252 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2253 | write!(f, "_#{}i", self.index) | |
2254 | } | |
2255 | } | |
223e47cc | 2256 | |
85aaf69f | 2257 | impl fmt::Debug for FloatVid { |
1a4d82fc JJ |
2258 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2259 | write!(f, "_#{}f", self.index) | |
2260 | } | |
223e47cc LB |
2261 | } |
2262 | ||
85aaf69f | 2263 | impl fmt::Debug for RegionVid { |
1a4d82fc JJ |
2264 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2265 | write!(f, "'_#{}r", self.index) | |
2266 | } | |
2267 | } | |
223e47cc | 2268 | |
85aaf69f | 2269 | impl<'tcx> fmt::Debug for FnSig<'tcx> { |
1a4d82fc JJ |
2270 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2271 | write!(f, "({:?}; variadic: {})->{:?}", self.inputs, self.variadic, self.output) | |
2272 | } | |
223e47cc LB |
2273 | } |
2274 | ||
85aaf69f | 2275 | impl fmt::Debug for InferTy { |
1a4d82fc JJ |
2276 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2277 | match *self { | |
2278 | TyVar(ref v) => v.fmt(f), | |
2279 | IntVar(ref v) => v.fmt(f), | |
2280 | FloatVar(ref v) => v.fmt(f), | |
2281 | FreshTy(v) => write!(f, "FreshTy({:?})", v), | |
2282 | FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), | |
d9579d0f | 2283 | FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v) |
1a4d82fc | 2284 | } |
970d7e83 | 2285 | } |
1a4d82fc JJ |
2286 | } |
2287 | ||
85aaf69f | 2288 | impl fmt::Debug for IntVarValue { |
1a4d82fc JJ |
2289 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2290 | match *self { | |
2291 | IntType(ref v) => v.fmt(f), | |
2292 | UintType(ref v) => v.fmt(f), | |
2293 | } | |
223e47cc LB |
2294 | } |
2295 | } | |
2296 | ||
85aaf69f SL |
2297 | /// Default region to use for the bound of objects that are |
2298 | /// supplied as the value for this type parameter. This is derived | |
2299 | /// from `T:'a` annotations appearing in the type definition. If | |
2300 | /// this is `None`, then the default is inherited from the | |
2301 | /// surrounding context. See RFC #599 for details. | |
62682a34 | 2302 | #[derive(Copy, Clone)] |
85aaf69f SL |
2303 | pub enum ObjectLifetimeDefault { |
2304 | /// Require an explicit annotation. Occurs when multiple | |
2305 | /// `T:'a` constraints are found. | |
2306 | Ambiguous, | |
2307 | ||
62682a34 SL |
2308 | /// Use the base default, typically 'static, but in a fn body it is a fresh variable |
2309 | BaseDefault, | |
2310 | ||
85aaf69f SL |
2311 | /// Use the given region as the default. |
2312 | Specific(Region), | |
2313 | } | |
2314 | ||
62682a34 | 2315 | #[derive(Clone)] |
1a4d82fc JJ |
2316 | pub struct TypeParameterDef<'tcx> { |
2317 | pub name: ast::Name, | |
2318 | pub def_id: ast::DefId, | |
2319 | pub space: subst::ParamSpace, | |
2320 | pub index: u32, | |
c1a9b12d | 2321 | pub default_def_id: DefId, // for use in error reporing about defaults |
1a4d82fc | 2322 | pub default: Option<Ty<'tcx>>, |
62682a34 | 2323 | pub object_lifetime_default: ObjectLifetimeDefault, |
223e47cc LB |
2324 | } |
2325 | ||
85aaf69f | 2326 | #[derive(RustcEncodable, RustcDecodable, Clone, Debug)] |
1a4d82fc JJ |
2327 | pub struct RegionParameterDef { |
2328 | pub name: ast::Name, | |
2329 | pub def_id: ast::DefId, | |
2330 | pub space: subst::ParamSpace, | |
2331 | pub index: u32, | |
2332 | pub bounds: Vec<ty::Region>, | |
2333 | } | |
223e47cc | 2334 | |
1a4d82fc JJ |
2335 | impl RegionParameterDef { |
2336 | pub fn to_early_bound_region(&self) -> ty::Region { | |
9346a6ac AL |
2337 | ty::ReEarlyBound(ty::EarlyBoundRegion { |
2338 | param_id: self.def_id.node, | |
2339 | space: self.space, | |
2340 | index: self.index, | |
2341 | name: self.name, | |
2342 | }) | |
223e47cc | 2343 | } |
c34b1796 AL |
2344 | pub fn to_bound_region(&self) -> ty::BoundRegion { |
2345 | ty::BoundRegion::BrNamed(self.def_id, self.name) | |
2346 | } | |
223e47cc LB |
2347 | } |
2348 | ||
1a4d82fc JJ |
2349 | /// Information about the formal type/lifetime parameters associated |
2350 | /// with an item or method. Analogous to ast::Generics. | |
85aaf69f | 2351 | #[derive(Clone, Debug)] |
1a4d82fc JJ |
2352 | pub struct Generics<'tcx> { |
2353 | pub types: VecPerParamSpace<TypeParameterDef<'tcx>>, | |
2354 | pub regions: VecPerParamSpace<RegionParameterDef>, | |
970d7e83 LB |
2355 | } |
2356 | ||
1a4d82fc JJ |
2357 | impl<'tcx> Generics<'tcx> { |
2358 | pub fn empty() -> Generics<'tcx> { | |
2359 | Generics { | |
2360 | types: VecPerParamSpace::empty(), | |
2361 | regions: VecPerParamSpace::empty(), | |
1a4d82fc | 2362 | } |
223e47cc LB |
2363 | } |
2364 | ||
85aaf69f SL |
2365 | pub fn is_empty(&self) -> bool { |
2366 | self.types.is_empty() && self.regions.is_empty() | |
2367 | } | |
2368 | ||
1a4d82fc JJ |
2369 | pub fn has_type_params(&self, space: subst::ParamSpace) -> bool { |
2370 | !self.types.is_empty_in(space) | |
223e47cc | 2371 | } |
223e47cc | 2372 | |
1a4d82fc JJ |
2373 | pub fn has_region_params(&self, space: subst::ParamSpace) -> bool { |
2374 | !self.regions.is_empty_in(space) | |
223e47cc | 2375 | } |
85aaf69f | 2376 | } |
223e47cc | 2377 | |
85aaf69f | 2378 | /// Bounds on generics. |
62682a34 | 2379 | #[derive(Clone)] |
85aaf69f SL |
2380 | pub struct GenericPredicates<'tcx> { |
2381 | pub predicates: VecPerParamSpace<Predicate<'tcx>>, | |
2382 | } | |
2383 | ||
2384 | impl<'tcx> GenericPredicates<'tcx> { | |
2385 | pub fn empty() -> GenericPredicates<'tcx> { | |
2386 | GenericPredicates { | |
2387 | predicates: VecPerParamSpace::empty(), | |
2388 | } | |
1a4d82fc JJ |
2389 | } |
2390 | ||
c1a9b12d | 2391 | pub fn instantiate(&self, tcx: &ctxt<'tcx>, substs: &Substs<'tcx>) |
85aaf69f SL |
2392 | -> InstantiatedPredicates<'tcx> { |
2393 | InstantiatedPredicates { | |
1a4d82fc | 2394 | predicates: self.predicates.subst(tcx, substs), |
223e47cc LB |
2395 | } |
2396 | } | |
c34b1796 AL |
2397 | |
2398 | pub fn instantiate_supertrait(&self, | |
c1a9b12d | 2399 | tcx: &ctxt<'tcx>, |
c34b1796 AL |
2400 | poly_trait_ref: &ty::PolyTraitRef<'tcx>) |
2401 | -> InstantiatedPredicates<'tcx> | |
2402 | { | |
2403 | InstantiatedPredicates { | |
2404 | predicates: self.predicates.map(|pred| pred.subst_supertrait(tcx, poly_trait_ref)) | |
2405 | } | |
2406 | } | |
223e47cc LB |
2407 | } |
2408 | ||
62682a34 | 2409 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
2410 | pub enum Predicate<'tcx> { |
2411 | /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be | |
2412 | /// the `Self` type of the trait reference and `A`, `B`, and `C` | |
2413 | /// would be the parameters in the `TypeSpace`. | |
2414 | Trait(PolyTraitPredicate<'tcx>), | |
2415 | ||
2416 | /// where `T1 == T2`. | |
2417 | Equate(PolyEquatePredicate<'tcx>), | |
2418 | ||
2419 | /// where 'a : 'b | |
2420 | RegionOutlives(PolyRegionOutlivesPredicate), | |
2421 | ||
2422 | /// where T : 'a | |
2423 | TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), | |
223e47cc | 2424 | |
1a4d82fc JJ |
2425 | /// where <T as TraitRef>::Name == X, approximately. |
2426 | /// See `ProjectionPredicate` struct for details. | |
2427 | Projection(PolyProjectionPredicate<'tcx>), | |
223e47cc LB |
2428 | } |
2429 | ||
c34b1796 | 2430 | impl<'tcx> Predicate<'tcx> { |
d9579d0f | 2431 | /// Performs a substitution suitable for going from a |
c34b1796 AL |
2432 | /// poly-trait-ref to supertraits that must hold if that |
2433 | /// poly-trait-ref holds. This is slightly different from a normal | |
2434 | /// substitution in terms of what happens with bound regions. See | |
2435 | /// lengthy comment below for details. | |
2436 | pub fn subst_supertrait(&self, | |
c1a9b12d | 2437 | tcx: &ctxt<'tcx>, |
c34b1796 AL |
2438 | trait_ref: &ty::PolyTraitRef<'tcx>) |
2439 | -> ty::Predicate<'tcx> | |
2440 | { | |
2441 | // The interaction between HRTB and supertraits is not entirely | |
2442 | // obvious. Let me walk you (and myself) through an example. | |
2443 | // | |
2444 | // Let's start with an easy case. Consider two traits: | |
2445 | // | |
2446 | // trait Foo<'a> : Bar<'a,'a> { } | |
2447 | // trait Bar<'b,'c> { } | |
2448 | // | |
2449 | // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then | |
2450 | // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we | |
2451 | // knew that `Foo<'x>` (for any 'x) then we also know that | |
2452 | // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from | |
2453 | // normal substitution. | |
2454 | // | |
2455 | // In terms of why this is sound, the idea is that whenever there | |
2456 | // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` | |
2457 | // holds. So if there is an impl of `T:Foo<'a>` that applies to | |
2458 | // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all | |
2459 | // `'a`. | |
2460 | // | |
2461 | // Another example to be careful of is this: | |
2462 | // | |
2463 | // trait Foo1<'a> : for<'b> Bar1<'a,'b> { } | |
2464 | // trait Bar1<'b,'c> { } | |
2465 | // | |
2466 | // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know? | |
2467 | // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The | |
2468 | // reason is similar to the previous example: any impl of | |
2469 | // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So | |
2470 | // basically we would want to collapse the bound lifetimes from | |
2471 | // the input (`trait_ref`) and the supertraits. | |
2472 | // | |
2473 | // To achieve this in practice is fairly straightforward. Let's | |
2474 | // consider the more complicated scenario: | |
2475 | // | |
2476 | // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x` | |
2477 | // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`, | |
2478 | // where both `'x` and `'b` would have a DB index of 1. | |
2479 | // The substitution from the input trait-ref is therefore going to be | |
2480 | // `'a => 'x` (where `'x` has a DB index of 1). | |
2481 | // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an | |
2482 | // early-bound parameter and `'b' is a late-bound parameter with a | |
2483 | // DB index of 1. | |
2484 | // - If we replace `'a` with `'x` from the input, it too will have | |
2485 | // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` | |
2486 | // just as we wanted. | |
2487 | // | |
2488 | // There is only one catch. If we just apply the substitution `'a | |
2489 | // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will | |
2490 | // adjust the DB index because we substituting into a binder (it | |
2491 | // tries to be so smart...) resulting in `for<'x> for<'b> | |
2492 | // Bar1<'x,'b>` (we have no syntax for this, so use your | |
2493 | // imagination). Basically the 'x will have DB index of 2 and 'b | |
2494 | // will have DB index of 1. Not quite what we want. So we apply | |
2495 | // the substitution to the *contents* of the trait reference, | |
2496 | // rather than the trait reference itself (put another way, the | |
2497 | // substitution code expects equal binding levels in the values | |
2498 | // from the substitution and the value being substituted into, and | |
2499 | // this trick achieves that). | |
2500 | ||
2501 | let substs = &trait_ref.0.substs; | |
2502 | match *self { | |
2503 | Predicate::Trait(ty::Binder(ref data)) => | |
2504 | Predicate::Trait(ty::Binder(data.subst(tcx, substs))), | |
2505 | Predicate::Equate(ty::Binder(ref data)) => | |
2506 | Predicate::Equate(ty::Binder(data.subst(tcx, substs))), | |
2507 | Predicate::RegionOutlives(ty::Binder(ref data)) => | |
2508 | Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))), | |
2509 | Predicate::TypeOutlives(ty::Binder(ref data)) => | |
2510 | Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))), | |
2511 | Predicate::Projection(ty::Binder(ref data)) => | |
2512 | Predicate::Projection(ty::Binder(data.subst(tcx, substs))), | |
2513 | } | |
2514 | } | |
2515 | } | |
2516 | ||
62682a34 | 2517 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc | 2518 | pub struct TraitPredicate<'tcx> { |
d9579d0f | 2519 | pub trait_ref: TraitRef<'tcx> |
223e47cc | 2520 | } |
1a4d82fc | 2521 | pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>; |
223e47cc | 2522 | |
1a4d82fc JJ |
2523 | impl<'tcx> TraitPredicate<'tcx> { |
2524 | pub fn def_id(&self) -> ast::DefId { | |
2525 | self.trait_ref.def_id | |
2526 | } | |
223e47cc | 2527 | |
1a4d82fc JJ |
2528 | pub fn input_types(&self) -> &[Ty<'tcx>] { |
2529 | self.trait_ref.substs.types.as_slice() | |
2530 | } | |
223e47cc | 2531 | |
1a4d82fc JJ |
2532 | pub fn self_ty(&self) -> Ty<'tcx> { |
2533 | self.trait_ref.self_ty() | |
2534 | } | |
223e47cc LB |
2535 | } |
2536 | ||
1a4d82fc JJ |
2537 | impl<'tcx> PolyTraitPredicate<'tcx> { |
2538 | pub fn def_id(&self) -> ast::DefId { | |
2539 | self.0.def_id() | |
2540 | } | |
223e47cc LB |
2541 | } |
2542 | ||
85aaf69f | 2543 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
2544 | pub struct EquatePredicate<'tcx>(pub Ty<'tcx>, pub Ty<'tcx>); // `0 == 1` |
2545 | pub type PolyEquatePredicate<'tcx> = ty::Binder<EquatePredicate<'tcx>>; | |
970d7e83 | 2546 | |
85aaf69f | 2547 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
2548 | pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B` |
2549 | pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>; | |
2550 | pub type PolyRegionOutlivesPredicate = PolyOutlivesPredicate<ty::Region, ty::Region>; | |
2551 | pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region>; | |
970d7e83 | 2552 | |
1a4d82fc JJ |
2553 | /// This kind of predicate has no *direct* correspondent in the |
2554 | /// syntax, but it roughly corresponds to the syntactic forms: | |
2555 | /// | |
2556 | /// 1. `T : TraitRef<..., Item=Type>` | |
2557 | /// 2. `<T as TraitRef<...>>::Item == Type` (NYI) | |
2558 | /// | |
2559 | /// In particular, form #1 is "desugared" to the combination of a | |
2560 | /// normal trait predicate (`T : TraitRef<...>`) and one of these | |
2561 | /// predicates. Form #2 is a broader form in that it also permits | |
2562 | /// equality between arbitrary types. Processing an instance of Form | |
2563 | /// #2 eventually yields one of these `ProjectionPredicate` | |
2564 | /// instances to normalize the LHS. | |
62682a34 | 2565 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
2566 | pub struct ProjectionPredicate<'tcx> { |
2567 | pub projection_ty: ProjectionTy<'tcx>, | |
2568 | pub ty: Ty<'tcx>, | |
223e47cc LB |
2569 | } |
2570 | ||
1a4d82fc | 2571 | pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>; |
223e47cc | 2572 | |
1a4d82fc JJ |
2573 | impl<'tcx> PolyProjectionPredicate<'tcx> { |
2574 | pub fn item_name(&self) -> ast::Name { | |
2575 | self.0.projection_ty.item_name // safe to skip the binder to access a name | |
970d7e83 | 2576 | } |
970d7e83 | 2577 | |
1a4d82fc JJ |
2578 | pub fn sort_key(&self) -> (ast::DefId, ast::Name) { |
2579 | self.0.projection_ty.sort_key() | |
223e47cc LB |
2580 | } |
2581 | } | |
2582 | ||
1a4d82fc JJ |
2583 | /// Represents the projection of an associated type. In explicit UFCS |
2584 | /// form this would be written `<T as Trait<..>>::N`. | |
85aaf69f | 2585 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
2586 | pub struct ProjectionTy<'tcx> { |
2587 | /// The trait reference `T as Trait<..>`. | |
d9579d0f | 2588 | pub trait_ref: ty::TraitRef<'tcx>, |
1a4d82fc JJ |
2589 | |
2590 | /// The name `N` of the associated type. | |
2591 | pub item_name: ast::Name, | |
223e47cc LB |
2592 | } |
2593 | ||
1a4d82fc JJ |
2594 | impl<'tcx> ProjectionTy<'tcx> { |
2595 | pub fn sort_key(&self) -> (ast::DefId, ast::Name) { | |
2596 | (self.trait_ref.def_id, self.item_name) | |
970d7e83 LB |
2597 | } |
2598 | } | |
2599 | ||
1a4d82fc JJ |
2600 | pub trait ToPolyTraitRef<'tcx> { |
2601 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; | |
223e47cc LB |
2602 | } |
2603 | ||
d9579d0f | 2604 | impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> { |
1a4d82fc JJ |
2605 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { |
2606 | assert!(!self.has_escaping_regions()); | |
2607 | ty::Binder(self.clone()) | |
970d7e83 LB |
2608 | } |
2609 | } | |
2610 | ||
1a4d82fc JJ |
2611 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { |
2612 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
c34b1796 | 2613 | self.map_bound_ref(|trait_pred| trait_pred.trait_ref.clone()) |
970d7e83 LB |
2614 | } |
2615 | } | |
2616 | ||
1a4d82fc JJ |
2617 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> { |
2618 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
2619 | // Note: unlike with TraitRef::to_poly_trait_ref(), | |
2620 | // self.0.trait_ref is permitted to have escaping regions. | |
2621 | // This is because here `self` has a `Binder` and so does our | |
2622 | // return value, so we are preserving the number of binding | |
2623 | // levels. | |
2624 | ty::Binder(self.0.projection_ty.trait_ref.clone()) | |
223e47cc LB |
2625 | } |
2626 | } | |
2627 | ||
c1a9b12d SL |
2628 | pub trait ToPredicate<'tcx> { |
2629 | fn to_predicate(&self) -> Predicate<'tcx>; | |
223e47cc LB |
2630 | } |
2631 | ||
c1a9b12d SL |
2632 | impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { |
2633 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1a4d82fc JJ |
2634 | // we're about to add a binder, so let's check that we don't |
2635 | // accidentally capture anything, or else that might be some | |
2636 | // weird debruijn accounting. | |
2637 | assert!(!self.has_escaping_regions()); | |
2638 | ||
2639 | ty::Predicate::Trait(ty::Binder(ty::TraitPredicate { | |
2640 | trait_ref: self.clone() | |
2641 | })) | |
223e47cc LB |
2642 | } |
2643 | } | |
2644 | ||
c1a9b12d SL |
2645 | impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> { |
2646 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1a4d82fc | 2647 | ty::Predicate::Trait(self.to_poly_trait_predicate()) |
223e47cc LB |
2648 | } |
2649 | } | |
2650 | ||
c1a9b12d SL |
2651 | impl<'tcx> ToPredicate<'tcx> for PolyEquatePredicate<'tcx> { |
2652 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1a4d82fc | 2653 | Predicate::Equate(self.clone()) |
223e47cc LB |
2654 | } |
2655 | } | |
2656 | ||
c1a9b12d SL |
2657 | impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate { |
2658 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1a4d82fc | 2659 | Predicate::RegionOutlives(self.clone()) |
223e47cc LB |
2660 | } |
2661 | } | |
2662 | ||
c1a9b12d SL |
2663 | impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { |
2664 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1a4d82fc | 2665 | Predicate::TypeOutlives(self.clone()) |
223e47cc LB |
2666 | } |
2667 | } | |
2668 | ||
c1a9b12d SL |
2669 | impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { |
2670 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1a4d82fc | 2671 | Predicate::Projection(self.clone()) |
223e47cc LB |
2672 | } |
2673 | } | |
2674 | ||
1a4d82fc | 2675 | impl<'tcx> Predicate<'tcx> { |
85aaf69f SL |
2676 | /// Iterates over the types in this predicate. Note that in all |
2677 | /// cases this is skipping over a binder, so late-bound regions | |
2678 | /// with depth 0 are bound by the predicate. | |
2679 | pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> { | |
2680 | let vec: Vec<_> = match *self { | |
2681 | ty::Predicate::Trait(ref data) => { | |
2682 | data.0.trait_ref.substs.types.as_slice().to_vec() | |
2683 | } | |
2684 | ty::Predicate::Equate(ty::Binder(ref data)) => { | |
2685 | vec![data.0, data.1] | |
2686 | } | |
2687 | ty::Predicate::TypeOutlives(ty::Binder(ref data)) => { | |
2688 | vec![data.0] | |
2689 | } | |
2690 | ty::Predicate::RegionOutlives(..) => { | |
2691 | vec![] | |
2692 | } | |
2693 | ty::Predicate::Projection(ref data) => { | |
2694 | let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice(); | |
2695 | trait_inputs.iter() | |
2696 | .cloned() | |
62682a34 | 2697 | .chain(Some(data.0.ty)) |
85aaf69f SL |
2698 | .collect() |
2699 | } | |
2700 | }; | |
2701 | ||
2702 | // The only reason to collect into a vector here is that I was | |
2703 | // too lazy to make the full (somewhat complicated) iterator | |
2704 | // type that would be needed here. But I wanted this fn to | |
2705 | // return an iterator conceptually, rather than a `Vec`, so as | |
2706 | // to be closer to `Ty::walk`. | |
2707 | vec.into_iter() | |
2708 | } | |
2709 | ||
1a4d82fc JJ |
2710 | pub fn has_escaping_regions(&self) -> bool { |
2711 | match *self { | |
2712 | Predicate::Trait(ref trait_ref) => trait_ref.has_escaping_regions(), | |
2713 | Predicate::Equate(ref p) => p.has_escaping_regions(), | |
2714 | Predicate::RegionOutlives(ref p) => p.has_escaping_regions(), | |
2715 | Predicate::TypeOutlives(ref p) => p.has_escaping_regions(), | |
2716 | Predicate::Projection(ref p) => p.has_escaping_regions(), | |
2717 | } | |
223e47cc | 2718 | } |
223e47cc | 2719 | |
1a4d82fc JJ |
2720 | pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> { |
2721 | match *self { | |
2722 | Predicate::Trait(ref t) => { | |
2723 | Some(t.to_poly_trait_ref()) | |
2724 | } | |
2725 | Predicate::Projection(..) | | |
2726 | Predicate::Equate(..) | | |
2727 | Predicate::RegionOutlives(..) | | |
2728 | Predicate::TypeOutlives(..) => { | |
2729 | None | |
2730 | } | |
2731 | } | |
223e47cc LB |
2732 | } |
2733 | } | |
2734 | ||
1a4d82fc JJ |
2735 | /// Represents the bounds declared on a particular set of type |
2736 | /// parameters. Should eventually be generalized into a flag list of | |
85aaf69f SL |
2737 | /// where clauses. You can obtain a `InstantiatedPredicates` list from a |
2738 | /// `GenericPredicates` by using the `instantiate` method. Note that this method | |
2739 | /// reflects an important semantic invariant of `InstantiatedPredicates`: while | |
2740 | /// the `GenericPredicates` are expressed in terms of the bound type | |
2741 | /// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance | |
1a4d82fc JJ |
2742 | /// represented a set of bounds for some particular instantiation, |
2743 | /// meaning that the generic parameters have been substituted with | |
2744 | /// their values. | |
2745 | /// | |
2746 | /// Example: | |
2747 | /// | |
2748 | /// struct Foo<T,U:Bar<T>> { ... } | |
2749 | /// | |
85aaf69f | 2750 | /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like |
1a4d82fc | 2751 | /// `[[], [U:Bar<T>]]`. Now if there were some particular reference |
c34b1796 AL |
2752 | /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], |
2753 | /// [usize:Bar<isize>]]`. | |
62682a34 | 2754 | #[derive(Clone)] |
85aaf69f | 2755 | pub struct InstantiatedPredicates<'tcx> { |
1a4d82fc | 2756 | pub predicates: VecPerParamSpace<Predicate<'tcx>>, |
223e47cc LB |
2757 | } |
2758 | ||
85aaf69f SL |
2759 | impl<'tcx> InstantiatedPredicates<'tcx> { |
2760 | pub fn empty() -> InstantiatedPredicates<'tcx> { | |
2761 | InstantiatedPredicates { predicates: VecPerParamSpace::empty() } | |
223e47cc LB |
2762 | } |
2763 | ||
1a4d82fc JJ |
2764 | pub fn has_escaping_regions(&self) -> bool { |
2765 | self.predicates.any(|p| p.has_escaping_regions()) | |
223e47cc LB |
2766 | } |
2767 | ||
1a4d82fc JJ |
2768 | pub fn is_empty(&self) -> bool { |
2769 | self.predicates.is_empty() | |
223e47cc | 2770 | } |
223e47cc LB |
2771 | } |
2772 | ||
1a4d82fc JJ |
2773 | impl<'tcx> TraitRef<'tcx> { |
2774 | pub fn new(def_id: ast::DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { | |
2775 | TraitRef { def_id: def_id, substs: substs } | |
970d7e83 LB |
2776 | } |
2777 | ||
1a4d82fc JJ |
2778 | pub fn self_ty(&self) -> Ty<'tcx> { |
2779 | self.substs.self_ty().unwrap() | |
970d7e83 LB |
2780 | } |
2781 | ||
1a4d82fc JJ |
2782 | pub fn input_types(&self) -> &[Ty<'tcx>] { |
2783 | // Select only the "input types" from a trait-reference. For | |
2784 | // now this is all the types that appear in the | |
2785 | // trait-reference, but it should eventually exclude | |
2786 | // associated types. | |
2787 | self.substs.types.as_slice() | |
223e47cc | 2788 | } |
1a4d82fc | 2789 | } |
223e47cc | 2790 | |
1a4d82fc JJ |
2791 | /// When type checking, we use the `ParameterEnvironment` to track |
2792 | /// details about the type/lifetime parameters that are in scope. | |
2793 | /// It primarily stores the bounds information. | |
2794 | /// | |
2795 | /// Note: This information might seem to be redundant with the data in | |
2796 | /// `tcx.ty_param_defs`, but it is not. That table contains the | |
2797 | /// parameter definitions from an "outside" perspective, but this | |
2798 | /// struct will contain the bounds for a parameter as seen from inside | |
2799 | /// the function body. Currently the only real distinction is that | |
2800 | /// bound lifetime parameters are replaced with free ones, but in the | |
2801 | /// future I hope to refine the representation of types so as to make | |
2802 | /// more distinctions clearer. | |
2803 | #[derive(Clone)] | |
2804 | pub struct ParameterEnvironment<'a, 'tcx:'a> { | |
2805 | pub tcx: &'a ctxt<'tcx>, | |
2806 | ||
85aaf69f | 2807 | /// See `construct_free_substs` for details. |
1a4d82fc JJ |
2808 | pub free_substs: Substs<'tcx>, |
2809 | ||
2810 | /// Each type parameter has an implicit region bound that | |
2811 | /// indicates it must outlive at least the function body (the user | |
2812 | /// may specify stronger requirements). This field indicates the | |
2813 | /// region of the callee. | |
2814 | pub implicit_region_bound: ty::Region, | |
2815 | ||
2816 | /// Obligations that the caller must satisfy. This is basically | |
2817 | /// the set of bounds on the in-scope type parameters, translated | |
62682a34 | 2818 | /// into Obligations, and elaborated and normalized. |
85aaf69f | 2819 | pub caller_bounds: Vec<ty::Predicate<'tcx>>, |
1a4d82fc JJ |
2820 | |
2821 | /// Caches the results of trait selection. This cache is used | |
2822 | /// for things that have to do with the parameters in scope. | |
2823 | pub selection_cache: traits::SelectionCache<'tcx>, | |
2824 | } | |
2825 | ||
2826 | impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { | |
85aaf69f SL |
2827 | pub fn with_caller_bounds(&self, |
2828 | caller_bounds: Vec<ty::Predicate<'tcx>>) | |
2829 | -> ParameterEnvironment<'a,'tcx> | |
2830 | { | |
2831 | ParameterEnvironment { | |
2832 | tcx: self.tcx, | |
2833 | free_substs: self.free_substs.clone(), | |
2834 | implicit_region_bound: self.implicit_region_bound, | |
2835 | caller_bounds: caller_bounds, | |
2836 | selection_cache: traits::SelectionCache::new(), | |
2837 | } | |
2838 | } | |
2839 | ||
1a4d82fc JJ |
2840 | pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx> { |
2841 | match cx.map.find(id) { | |
2842 | Some(ast_map::NodeImplItem(ref impl_item)) => { | |
c34b1796 | 2843 | match impl_item.node { |
d9579d0f AL |
2844 | ast::ConstImplItem(_, _) => { |
2845 | let def_id = ast_util::local_def(id); | |
c1a9b12d SL |
2846 | let scheme = cx.lookup_item_type(def_id); |
2847 | let predicates = cx.lookup_predicates(def_id); | |
2848 | cx.construct_parameter_environment(impl_item.span, | |
2849 | &scheme.generics, | |
2850 | &predicates, | |
2851 | id) | |
d9579d0f | 2852 | } |
c34b1796 | 2853 | ast::MethodImplItem(_, ref body) => { |
1a4d82fc | 2854 | let method_def_id = ast_util::local_def(id); |
c1a9b12d | 2855 | match cx.impl_or_trait_item(method_def_id) { |
1a4d82fc JJ |
2856 | MethodTraitItem(ref method_ty) => { |
2857 | let method_generics = &method_ty.generics; | |
85aaf69f | 2858 | let method_bounds = &method_ty.predicates; |
c1a9b12d | 2859 | cx.construct_parameter_environment( |
c34b1796 | 2860 | impl_item.span, |
1a4d82fc | 2861 | method_generics, |
85aaf69f | 2862 | method_bounds, |
c34b1796 | 2863 | body.id) |
1a4d82fc | 2864 | } |
d9579d0f | 2865 | _ => { |
1a4d82fc JJ |
2866 | cx.sess |
2867 | .bug("ParameterEnvironment::for_item(): \ | |
d9579d0f | 2868 | got non-method item from impl method?!") |
1a4d82fc JJ |
2869 | } |
2870 | } | |
2871 | } | |
2872 | ast::TypeImplItem(_) => { | |
2873 | cx.sess.bug("ParameterEnvironment::for_item(): \ | |
2874 | can't create a parameter environment \ | |
2875 | for type impl items") | |
2876 | } | |
c34b1796 | 2877 | ast::MacImplItem(_) => cx.sess.bug("unexpanded macro") |
1a4d82fc JJ |
2878 | } |
2879 | } | |
c34b1796 AL |
2880 | Some(ast_map::NodeTraitItem(trait_item)) => { |
2881 | match trait_item.node { | |
d9579d0f AL |
2882 | ast::ConstTraitItem(_, ref default) => { |
2883 | match *default { | |
2884 | Some(_) => { | |
2885 | let def_id = ast_util::local_def(id); | |
c1a9b12d SL |
2886 | let scheme = cx.lookup_item_type(def_id); |
2887 | let predicates = cx.lookup_predicates(def_id); | |
2888 | cx.construct_parameter_environment(trait_item.span, | |
2889 | &scheme.generics, | |
2890 | &predicates, | |
2891 | id) | |
d9579d0f AL |
2892 | } |
2893 | None => { | |
2894 | cx.sess.bug("ParameterEnvironment::from_item(): \ | |
2895 | can't create a parameter environment \ | |
2896 | for const trait items without defaults") | |
2897 | } | |
2898 | } | |
2899 | } | |
c34b1796 AL |
2900 | ast::MethodTraitItem(_, None) => { |
2901 | cx.sess.span_bug(trait_item.span, | |
1a4d82fc JJ |
2902 | "ParameterEnvironment::for_item(): |
2903 | can't create a parameter \ | |
2904 | environment for required trait \ | |
2905 | methods") | |
2906 | } | |
c34b1796 | 2907 | ast::MethodTraitItem(_, Some(ref body)) => { |
1a4d82fc | 2908 | let method_def_id = ast_util::local_def(id); |
c1a9b12d | 2909 | match cx.impl_or_trait_item(method_def_id) { |
1a4d82fc JJ |
2910 | MethodTraitItem(ref method_ty) => { |
2911 | let method_generics = &method_ty.generics; | |
85aaf69f | 2912 | let method_bounds = &method_ty.predicates; |
c1a9b12d | 2913 | cx.construct_parameter_environment( |
c34b1796 | 2914 | trait_item.span, |
1a4d82fc | 2915 | method_generics, |
85aaf69f | 2916 | method_bounds, |
c34b1796 | 2917 | body.id) |
1a4d82fc | 2918 | } |
d9579d0f | 2919 | _ => { |
1a4d82fc JJ |
2920 | cx.sess |
2921 | .bug("ParameterEnvironment::for_item(): \ | |
d9579d0f AL |
2922 | got non-method item from provided \ |
2923 | method?!") | |
1a4d82fc JJ |
2924 | } |
2925 | } | |
2926 | } | |
c34b1796 | 2927 | ast::TypeTraitItem(..) => { |
1a4d82fc JJ |
2928 | cx.sess.bug("ParameterEnvironment::from_item(): \ |
2929 | can't create a parameter environment \ | |
2930 | for type trait items") | |
2931 | } | |
2932 | } | |
2933 | } | |
2934 | Some(ast_map::NodeItem(item)) => { | |
2935 | match item.node { | |
62682a34 | 2936 | ast::ItemFn(_, _, _, _, _, ref body) => { |
1a4d82fc JJ |
2937 | // We assume this is a function. |
2938 | let fn_def_id = ast_util::local_def(id); | |
c1a9b12d SL |
2939 | let fn_scheme = cx.lookup_item_type(fn_def_id); |
2940 | let fn_predicates = cx.lookup_predicates(fn_def_id); | |
2941 | ||
2942 | cx.construct_parameter_environment(item.span, | |
2943 | &fn_scheme.generics, | |
2944 | &fn_predicates, | |
2945 | body.id) | |
1a4d82fc JJ |
2946 | } |
2947 | ast::ItemEnum(..) | | |
2948 | ast::ItemStruct(..) | | |
2949 | ast::ItemImpl(..) | | |
2950 | ast::ItemConst(..) | | |
2951 | ast::ItemStatic(..) => { | |
2952 | let def_id = ast_util::local_def(id); | |
c1a9b12d SL |
2953 | let scheme = cx.lookup_item_type(def_id); |
2954 | let predicates = cx.lookup_predicates(def_id); | |
2955 | cx.construct_parameter_environment(item.span, | |
2956 | &scheme.generics, | |
2957 | &predicates, | |
2958 | id) | |
1a4d82fc JJ |
2959 | } |
2960 | _ => { | |
2961 | cx.sess.span_bug(item.span, | |
2962 | "ParameterEnvironment::from_item(): | |
2963 | can't create a parameter \ | |
2964 | environment for this kind of item") | |
2965 | } | |
2966 | } | |
2967 | } | |
2968 | Some(ast_map::NodeExpr(..)) => { | |
2969 | // This is a convenience to allow closures to work. | |
2970 | ParameterEnvironment::for_item(cx, cx.map.get_parent(id)) | |
2971 | } | |
2972 | _ => { | |
2973 | cx.sess.bug(&format!("ParameterEnvironment::from_item(): \ | |
2974 | `{}` is not an item", | |
c34b1796 | 2975 | cx.map.node_to_string(id))) |
1a4d82fc JJ |
2976 | } |
2977 | } | |
223e47cc | 2978 | } |
c1a9b12d SL |
2979 | |
2980 | pub fn can_type_implement_copy(&self, self_type: Ty<'tcx>, span: Span) | |
2981 | -> Result<(),CopyImplementationError> { | |
2982 | let tcx = self.tcx; | |
2983 | ||
2984 | // FIXME: (@jroesch) float this code up | |
2985 | let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(self.clone()), false); | |
2986 | ||
2987 | let did = match self_type.sty { | |
2988 | ty::TyStruct(struct_did, substs) => { | |
2989 | let fields = tcx.struct_fields(struct_did, substs); | |
2990 | for field in &fields { | |
2991 | if infcx.type_moves_by_default(field.mt.ty, span) { | |
2992 | return Err(FieldDoesNotImplementCopy(field.name)) | |
2993 | } | |
2994 | } | |
2995 | struct_did | |
2996 | } | |
2997 | ty::TyEnum(enum_did, substs) => { | |
2998 | let enum_variants = tcx.enum_variants(enum_did); | |
2999 | for variant in enum_variants.iter() { | |
3000 | for variant_arg_type in &variant.args { | |
3001 | let substd_arg_type = | |
3002 | variant_arg_type.subst(tcx, substs); | |
3003 | if infcx.type_moves_by_default(substd_arg_type, span) { | |
3004 | return Err(VariantDoesNotImplementCopy(variant.name)) | |
3005 | } | |
3006 | } | |
3007 | } | |
3008 | enum_did | |
3009 | } | |
3010 | _ => return Err(TypeIsStructural), | |
3011 | }; | |
3012 | ||
3013 | if tcx.has_dtor(did) { | |
3014 | return Err(TypeHasDestructor) | |
3015 | } | |
3016 | ||
3017 | Ok(()) | |
3018 | } | |
3019 | } | |
3020 | ||
3021 | #[derive(Copy, Clone)] | |
3022 | pub enum CopyImplementationError { | |
3023 | FieldDoesNotImplementCopy(ast::Name), | |
3024 | VariantDoesNotImplementCopy(ast::Name), | |
3025 | TypeIsStructural, | |
3026 | TypeHasDestructor, | |
1a4d82fc | 3027 | } |
223e47cc | 3028 | |
1a4d82fc JJ |
3029 | /// A "type scheme", in ML terminology, is a type combined with some |
3030 | /// set of generic types that the type is, well, generic over. In Rust | |
3031 | /// terms, it is the "type" of a fn item or struct -- this type will | |
3032 | /// include various generic parameters that must be substituted when | |
3033 | /// the item/struct is referenced. That is called converting the type | |
3034 | /// scheme to a monotype. | |
3035 | /// | |
3036 | /// - `generics`: the set of type parameters and their bounds | |
3037 | /// - `ty`: the base types, which may reference the parameters defined | |
3038 | /// in `generics` | |
3039 | /// | |
3040 | /// Note that TypeSchemes are also sometimes called "polytypes" (and | |
3041 | /// in fact this struct used to carry that name, so you may find some | |
3042 | /// stray references in a comment or something). We try to reserve the | |
3043 | /// "poly" prefix to refer to higher-ranked things, as in | |
3044 | /// `PolyTraitRef`. | |
85aaf69f SL |
3045 | /// |
3046 | /// Note that each item also comes with predicates, see | |
3047 | /// `lookup_predicates`. | |
3048 | #[derive(Clone, Debug)] | |
1a4d82fc JJ |
3049 | pub struct TypeScheme<'tcx> { |
3050 | pub generics: Generics<'tcx>, | |
85aaf69f | 3051 | pub ty: Ty<'tcx>, |
1a4d82fc JJ |
3052 | } |
3053 | ||
d9579d0f AL |
3054 | bitflags! { |
3055 | flags TraitFlags: u32 { | |
3056 | const NO_TRAIT_FLAGS = 0, | |
3057 | const HAS_DEFAULT_IMPL = 1 << 0, | |
3058 | const IS_OBJECT_SAFE = 1 << 1, | |
3059 | const OBJECT_SAFETY_VALID = 1 << 2, | |
3060 | const IMPLS_VALID = 1 << 3, | |
3061 | } | |
3062 | } | |
3063 | ||
1a4d82fc JJ |
3064 | /// As `TypeScheme` but for a trait ref. |
3065 | pub struct TraitDef<'tcx> { | |
3066 | pub unsafety: ast::Unsafety, | |
3067 | ||
85aaf69f SL |
3068 | /// If `true`, then this trait had the `#[rustc_paren_sugar]` |
3069 | /// attribute, indicating that it should be used with `Foo()` | |
3070 | /// sugar. This is a temporary thing -- eventually any trait wil | |
3071 | /// be usable with the sugar (or without it). | |
3072 | pub paren_sugar: bool, | |
3073 | ||
1a4d82fc JJ |
3074 | /// Generic type definitions. Note that `Self` is listed in here |
3075 | /// as having a single bound, the trait itself (e.g., in the trait | |
3076 | /// `Eq`, there is a single bound `Self : Eq`). This is so that | |
3077 | /// default methods get to assume that the `Self` parameters | |
3078 | /// implements the trait. | |
3079 | pub generics: Generics<'tcx>, | |
3080 | ||
d9579d0f | 3081 | pub trait_ref: TraitRef<'tcx>, |
1a4d82fc JJ |
3082 | |
3083 | /// A list of the associated types defined in this trait. Useful | |
3084 | /// for resolving `X::Foo` type markers. | |
3085 | pub associated_type_names: Vec<ast::Name>, | |
d9579d0f AL |
3086 | |
3087 | // Impls of this trait. To allow for quicker lookup, the impls are indexed | |
3088 | // by a simplified version of their Self type: impls with a simplifiable | |
3089 | // Self are stored in nonblanket_impls keyed by it, while all other impls | |
3090 | // are stored in blanket_impls. | |
3091 | ||
3092 | /// Impls of the trait. | |
3093 | pub nonblanket_impls: RefCell< | |
3094 | FnvHashMap<fast_reject::SimplifiedType, Vec<DefId>> | |
3095 | >, | |
3096 | ||
3097 | /// Blanket impls associated with the trait. | |
3098 | pub blanket_impls: RefCell<Vec<DefId>>, | |
3099 | ||
3100 | /// Various flags | |
3101 | pub flags: Cell<TraitFlags> | |
3102 | } | |
3103 | ||
3104 | impl<'tcx> TraitDef<'tcx> { | |
3105 | // returns None if not yet calculated | |
3106 | pub fn object_safety(&self) -> Option<bool> { | |
3107 | if self.flags.get().intersects(TraitFlags::OBJECT_SAFETY_VALID) { | |
3108 | Some(self.flags.get().intersects(TraitFlags::IS_OBJECT_SAFE)) | |
3109 | } else { | |
3110 | None | |
3111 | } | |
3112 | } | |
3113 | ||
3114 | pub fn set_object_safety(&self, is_safe: bool) { | |
3115 | assert!(self.object_safety().map(|cs| cs == is_safe).unwrap_or(true)); | |
3116 | self.flags.set( | |
3117 | self.flags.get() | if is_safe { | |
3118 | TraitFlags::OBJECT_SAFETY_VALID | TraitFlags::IS_OBJECT_SAFE | |
3119 | } else { | |
3120 | TraitFlags::OBJECT_SAFETY_VALID | |
3121 | } | |
3122 | ); | |
3123 | } | |
3124 | ||
3125 | /// Records a trait-to-implementation mapping. | |
3126 | pub fn record_impl(&self, | |
3127 | tcx: &ctxt<'tcx>, | |
3128 | impl_def_id: DefId, | |
3129 | impl_trait_ref: TraitRef<'tcx>) { | |
62682a34 SL |
3130 | debug!("TraitDef::record_impl for {:?}, from {:?}", |
3131 | self, impl_trait_ref); | |
d9579d0f AL |
3132 | |
3133 | // We don't want to borrow_mut after we already populated all impls, | |
3134 | // so check if an impl is present with an immutable borrow first. | |
3135 | if let Some(sty) = fast_reject::simplify_type(tcx, | |
3136 | impl_trait_ref.self_ty(), false) { | |
3137 | if let Some(is) = self.nonblanket_impls.borrow().get(&sty) { | |
3138 | if is.contains(&impl_def_id) { | |
3139 | return // duplicate - skip | |
3140 | } | |
3141 | } | |
3142 | ||
3143 | self.nonblanket_impls.borrow_mut().entry(sty).or_insert(vec![]).push(impl_def_id) | |
3144 | } else { | |
3145 | if self.blanket_impls.borrow().contains(&impl_def_id) { | |
3146 | return // duplicate - skip | |
3147 | } | |
3148 | self.blanket_impls.borrow_mut().push(impl_def_id) | |
3149 | } | |
3150 | } | |
3151 | ||
3152 | ||
3153 | pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: &ctxt<'tcx>, mut f: F) { | |
c1a9b12d | 3154 | tcx.populate_implementations_for_trait_if_necessary(self.trait_ref.def_id); |
d9579d0f AL |
3155 | |
3156 | for &impl_def_id in self.blanket_impls.borrow().iter() { | |
3157 | f(impl_def_id); | |
3158 | } | |
3159 | ||
3160 | for v in self.nonblanket_impls.borrow().values() { | |
3161 | for &impl_def_id in v { | |
3162 | f(impl_def_id); | |
3163 | } | |
3164 | } | |
3165 | } | |
3166 | ||
3167 | pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self, | |
3168 | tcx: &ctxt<'tcx>, | |
3169 | self_ty: Ty<'tcx>, | |
3170 | mut f: F) | |
3171 | { | |
c1a9b12d | 3172 | tcx.populate_implementations_for_trait_if_necessary(self.trait_ref.def_id); |
d9579d0f AL |
3173 | |
3174 | for &impl_def_id in self.blanket_impls.borrow().iter() { | |
3175 | f(impl_def_id); | |
3176 | } | |
3177 | ||
3178 | if let Some(simp) = fast_reject::simplify_type(tcx, self_ty, false) { | |
3179 | if let Some(impls) = self.nonblanket_impls.borrow().get(&simp) { | |
3180 | for &impl_def_id in impls { | |
3181 | f(impl_def_id); | |
3182 | } | |
3183 | return; // we don't need to process the other non-blanket impls | |
3184 | } | |
3185 | } | |
3186 | ||
3187 | for v in self.nonblanket_impls.borrow().values() { | |
3188 | for &impl_def_id in v { | |
3189 | f(impl_def_id); | |
3190 | } | |
3191 | } | |
3192 | } | |
3193 | ||
1a4d82fc JJ |
3194 | } |
3195 | ||
3196 | /// Records the substitutions used to translate the polytype for an | |
3197 | /// item into the monotype of an item reference. | |
3198 | #[derive(Clone)] | |
3199 | pub struct ItemSubsts<'tcx> { | |
3200 | pub substs: Substs<'tcx>, | |
3201 | } | |
3202 | ||
c34b1796 | 3203 | #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)] |
85aaf69f | 3204 | pub enum ClosureKind { |
c34b1796 AL |
3205 | // Warning: Ordering is significant here! The ordering is chosen |
3206 | // because the trait Fn is a subtrait of FnMut and so in turn, and | |
3207 | // hence we order it so that Fn < FnMut < FnOnce. | |
85aaf69f SL |
3208 | FnClosureKind, |
3209 | FnMutClosureKind, | |
3210 | FnOnceClosureKind, | |
1a4d82fc JJ |
3211 | } |
3212 | ||
85aaf69f | 3213 | impl ClosureKind { |
1a4d82fc JJ |
3214 | pub fn trait_did(&self, cx: &ctxt) -> ast::DefId { |
3215 | let result = match *self { | |
85aaf69f SL |
3216 | FnClosureKind => cx.lang_items.require(FnTraitLangItem), |
3217 | FnMutClosureKind => { | |
1a4d82fc JJ |
3218 | cx.lang_items.require(FnMutTraitLangItem) |
3219 | } | |
85aaf69f | 3220 | FnOnceClosureKind => { |
1a4d82fc JJ |
3221 | cx.lang_items.require(FnOnceTraitLangItem) |
3222 | } | |
3223 | }; | |
3224 | match result { | |
3225 | Ok(trait_did) => trait_did, | |
85aaf69f | 3226 | Err(err) => cx.sess.fatal(&err[..]), |
1a4d82fc | 3227 | } |
223e47cc | 3228 | } |
c34b1796 AL |
3229 | |
3230 | /// True if this a type that impls this closure kind | |
3231 | /// must also implement `other`. | |
3232 | pub fn extends(self, other: ty::ClosureKind) -> bool { | |
3233 | match (self, other) { | |
3234 | (FnClosureKind, FnClosureKind) => true, | |
3235 | (FnClosureKind, FnMutClosureKind) => true, | |
3236 | (FnClosureKind, FnOnceClosureKind) => true, | |
3237 | (FnMutClosureKind, FnMutClosureKind) => true, | |
3238 | (FnMutClosureKind, FnOnceClosureKind) => true, | |
3239 | (FnOnceClosureKind, FnOnceClosureKind) => true, | |
3240 | _ => false, | |
3241 | } | |
3242 | } | |
1a4d82fc | 3243 | } |
223e47cc | 3244 | |
1a4d82fc JJ |
3245 | impl<'tcx> CommonTypes<'tcx> { |
3246 | fn new(arena: &'tcx TypedArena<TyS<'tcx>>, | |
c1a9b12d | 3247 | interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>) |
1a4d82fc JJ |
3248 | -> CommonTypes<'tcx> |
3249 | { | |
c1a9b12d | 3250 | let mk = |sty| ctxt::intern_ty(arena, interner, sty); |
1a4d82fc | 3251 | CommonTypes { |
c1a9b12d SL |
3252 | bool: mk(TyBool), |
3253 | char: mk(TyChar), | |
3254 | err: mk(TyError), | |
3255 | isize: mk(TyInt(ast::TyIs)), | |
3256 | i8: mk(TyInt(ast::TyI8)), | |
3257 | i16: mk(TyInt(ast::TyI16)), | |
3258 | i32: mk(TyInt(ast::TyI32)), | |
3259 | i64: mk(TyInt(ast::TyI64)), | |
3260 | usize: mk(TyUint(ast::TyUs)), | |
3261 | u8: mk(TyUint(ast::TyU8)), | |
3262 | u16: mk(TyUint(ast::TyU16)), | |
3263 | u32: mk(TyUint(ast::TyU32)), | |
3264 | u64: mk(TyUint(ast::TyU64)), | |
3265 | f32: mk(TyFloat(ast::TyF32)), | |
3266 | f64: mk(TyFloat(ast::TyF64)), | |
1a4d82fc | 3267 | } |
223e47cc | 3268 | } |
c1a9b12d | 3269 | } |
223e47cc | 3270 | |
c1a9b12d SL |
3271 | struct FlagComputation { |
3272 | flags: TypeFlags, | |
223e47cc | 3273 | |
c1a9b12d SL |
3274 | // maximum depth of any bound region that we have seen thus far |
3275 | depth: u32, | |
3276 | } | |
223e47cc | 3277 | |
c1a9b12d SL |
3278 | impl FlagComputation { |
3279 | fn new() -> FlagComputation { | |
3280 | FlagComputation { flags: TypeFlags::empty(), depth: 0 } | |
223e47cc | 3281 | } |
223e47cc | 3282 | |
c1a9b12d SL |
3283 | fn for_sty(st: &TypeVariants) -> FlagComputation { |
3284 | let mut result = FlagComputation::new(); | |
3285 | result.add_sty(st); | |
3286 | result | |
223e47cc | 3287 | } |
223e47cc | 3288 | |
c1a9b12d SL |
3289 | fn add_flags(&mut self, flags: TypeFlags) { |
3290 | self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS); | |
c34b1796 AL |
3291 | } |
3292 | ||
c1a9b12d SL |
3293 | fn add_depth(&mut self, depth: u32) { |
3294 | if depth > self.depth { | |
3295 | self.depth = depth; | |
3296 | } | |
c34b1796 AL |
3297 | } |
3298 | ||
c1a9b12d SL |
3299 | /// Adds the flags/depth from a set of types that appear within the current type, but within a |
3300 | /// region binder. | |
3301 | fn add_bound_computation(&mut self, computation: &FlagComputation) { | |
3302 | self.add_flags(computation.flags); | |
223e47cc | 3303 | |
85aaf69f | 3304 | // The types that contributed to `computation` occurred within |
1a4d82fc JJ |
3305 | // a region binder, so subtract one from the region depth |
3306 | // within when adding the depth to `self`. | |
3307 | let depth = computation.depth; | |
3308 | if depth > 0 { | |
3309 | self.add_depth(depth - 1); | |
3310 | } | |
3311 | } | |
223e47cc | 3312 | |
62682a34 | 3313 | fn add_sty(&mut self, st: &TypeVariants) { |
1a4d82fc | 3314 | match st { |
62682a34 SL |
3315 | &TyBool | |
3316 | &TyChar | | |
3317 | &TyInt(_) | | |
3318 | &TyFloat(_) | | |
3319 | &TyUint(_) | | |
3320 | &TyStr => { | |
223e47cc LB |
3321 | } |
3322 | ||
62682a34 SL |
3323 | // You might think that we could just return TyError for |
3324 | // any type containing TyError as a component, and get | |
d9579d0f | 3325 | // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with |
1a4d82fc JJ |
3326 | // the exception of function types that return bot). |
3327 | // But doing so caused sporadic memory corruption, and | |
3328 | // neither I (tjc) nor nmatsakis could figure out why, | |
3329 | // so we're doing it this way. | |
62682a34 | 3330 | &TyError => { |
d9579d0f | 3331 | self.add_flags(TypeFlags::HAS_TY_ERR) |
223e47cc LB |
3332 | } |
3333 | ||
62682a34 SL |
3334 | &TyParam(ref p) => { |
3335 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
1a4d82fc | 3336 | if p.space == subst::SelfSpace { |
d9579d0f | 3337 | self.add_flags(TypeFlags::HAS_SELF); |
1a4d82fc | 3338 | } else { |
d9579d0f | 3339 | self.add_flags(TypeFlags::HAS_PARAMS); |
1a4d82fc | 3340 | } |
223e47cc LB |
3341 | } |
3342 | ||
c1a9b12d | 3343 | &TyClosure(_, ref substs) => { |
62682a34 SL |
3344 | self.add_flags(TypeFlags::HAS_TY_CLOSURE); |
3345 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
c1a9b12d SL |
3346 | self.add_substs(&substs.func_substs); |
3347 | self.add_tys(&substs.upvar_tys); | |
223e47cc LB |
3348 | } |
3349 | ||
62682a34 SL |
3350 | &TyInfer(_) => { |
3351 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right? | |
d9579d0f | 3352 | self.add_flags(TypeFlags::HAS_TY_INFER) |
223e47cc LB |
3353 | } |
3354 | ||
62682a34 | 3355 | &TyEnum(_, substs) | &TyStruct(_, substs) => { |
1a4d82fc | 3356 | self.add_substs(substs); |
223e47cc LB |
3357 | } |
3358 | ||
62682a34 | 3359 | &TyProjection(ref data) => { |
d9579d0f | 3360 | self.add_flags(TypeFlags::HAS_PROJECTION); |
85aaf69f | 3361 | self.add_projection_ty(data); |
223e47cc LB |
3362 | } |
3363 | ||
62682a34 | 3364 | &TyTrait(box TraitTy { ref principal, ref bounds }) => { |
1a4d82fc JJ |
3365 | let mut computation = FlagComputation::new(); |
3366 | computation.add_substs(principal.0.substs); | |
85aaf69f SL |
3367 | for projection_bound in &bounds.projection_bounds { |
3368 | let mut proj_computation = FlagComputation::new(); | |
3369 | proj_computation.add_projection_predicate(&projection_bound.0); | |
62682a34 | 3370 | self.add_bound_computation(&proj_computation); |
85aaf69f | 3371 | } |
1a4d82fc | 3372 | self.add_bound_computation(&computation); |
223e47cc | 3373 | |
1a4d82fc | 3374 | self.add_bounds(bounds); |
223e47cc LB |
3375 | } |
3376 | ||
62682a34 | 3377 | &TyBox(tt) | &TyArray(tt, _) | &TySlice(tt) => { |
1a4d82fc | 3378 | self.add_ty(tt) |
223e47cc LB |
3379 | } |
3380 | ||
62682a34 | 3381 | &TyRawPtr(ref m) => { |
1a4d82fc | 3382 | self.add_ty(m.ty); |
223e47cc LB |
3383 | } |
3384 | ||
62682a34 | 3385 | &TyRef(r, ref m) => { |
1a4d82fc JJ |
3386 | self.add_region(*r); |
3387 | self.add_ty(m.ty); | |
223e47cc LB |
3388 | } |
3389 | ||
62682a34 | 3390 | &TyTuple(ref ts) => { |
85aaf69f | 3391 | self.add_tys(&ts[..]); |
223e47cc LB |
3392 | } |
3393 | ||
62682a34 | 3394 | &TyBareFn(_, ref f) => { |
1a4d82fc | 3395 | self.add_fn_sig(&f.sig); |
223e47cc | 3396 | } |
1a4d82fc JJ |
3397 | } |
3398 | } | |
223e47cc | 3399 | |
1a4d82fc | 3400 | fn add_ty(&mut self, ty: Ty) { |
62682a34 | 3401 | self.add_flags(ty.flags.get()); |
1a4d82fc JJ |
3402 | self.add_depth(ty.region_depth); |
3403 | } | |
223e47cc | 3404 | |
1a4d82fc | 3405 | fn add_tys(&mut self, tys: &[Ty]) { |
85aaf69f | 3406 | for &ty in tys { |
1a4d82fc JJ |
3407 | self.add_ty(ty); |
3408 | } | |
3409 | } | |
223e47cc | 3410 | |
1a4d82fc JJ |
3411 | fn add_fn_sig(&mut self, fn_sig: &PolyFnSig) { |
3412 | let mut computation = FlagComputation::new(); | |
223e47cc | 3413 | |
c34b1796 | 3414 | computation.add_tys(&fn_sig.0.inputs); |
223e47cc | 3415 | |
1a4d82fc JJ |
3416 | if let ty::FnConverging(output) = fn_sig.0.output { |
3417 | computation.add_ty(output); | |
3418 | } | |
223e47cc | 3419 | |
1a4d82fc | 3420 | self.add_bound_computation(&computation); |
223e47cc LB |
3421 | } |
3422 | ||
1a4d82fc | 3423 | fn add_region(&mut self, r: Region) { |
1a4d82fc | 3424 | match r { |
d9579d0f | 3425 | ty::ReInfer(_) => { self.add_flags(TypeFlags::HAS_RE_INFER); } |
62682a34 SL |
3426 | ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); } |
3427 | ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); } | |
3428 | ty::ReStatic => {} | |
3429 | _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); } | |
3430 | } | |
3431 | ||
3432 | if !r.is_global() { | |
3433 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
1a4d82fc | 3434 | } |
223e47cc LB |
3435 | } |
3436 | ||
85aaf69f SL |
3437 | fn add_projection_predicate(&mut self, projection_predicate: &ProjectionPredicate) { |
3438 | self.add_projection_ty(&projection_predicate.projection_ty); | |
3439 | self.add_ty(projection_predicate.ty); | |
3440 | } | |
3441 | ||
3442 | fn add_projection_ty(&mut self, projection_ty: &ProjectionTy) { | |
3443 | self.add_substs(projection_ty.trait_ref.substs); | |
3444 | } | |
3445 | ||
1a4d82fc JJ |
3446 | fn add_substs(&mut self, substs: &Substs) { |
3447 | self.add_tys(substs.types.as_slice()); | |
3448 | match substs.regions { | |
3449 | subst::ErasedRegions => {} | |
3450 | subst::NonerasedRegions(ref regions) => { | |
62682a34 | 3451 | for &r in regions { |
1a4d82fc JJ |
3452 | self.add_region(r); |
3453 | } | |
3454 | } | |
970d7e83 | 3455 | } |
970d7e83 LB |
3456 | } |
3457 | ||
1a4d82fc JJ |
3458 | fn add_bounds(&mut self, bounds: &ExistentialBounds) { |
3459 | self.add_region(bounds.region_bound); | |
970d7e83 | 3460 | } |
1a4d82fc | 3461 | } |
970d7e83 | 3462 | |
c1a9b12d SL |
3463 | impl<'tcx> ctxt<'tcx> { |
3464 | /// Create a type context and call the closure with a `&ty::ctxt` reference | |
3465 | /// to the context. The closure enforces that the type context and any interned | |
3466 | /// value (types, substs, etc.) can only be used while `ty::tls` has a valid | |
3467 | /// reference to the context, to allow formatting values that need it. | |
3468 | pub fn create_and_enter<F, R>(s: Session, | |
3469 | arenas: &'tcx CtxtArenas<'tcx>, | |
3470 | def_map: DefMap, | |
3471 | named_region_map: resolve_lifetime::NamedRegionMap, | |
3472 | map: ast_map::Map<'tcx>, | |
3473 | freevars: RefCell<FreevarMap>, | |
3474 | region_maps: RegionMaps, | |
3475 | lang_items: middle::lang_items::LanguageItems, | |
3476 | stability: stability::Index<'tcx>, | |
3477 | f: F) -> (Session, R) | |
3478 | where F: FnOnce(&ctxt<'tcx>) -> R | |
3479 | { | |
3480 | let interner = RefCell::new(FnvHashMap()); | |
3481 | let common_types = CommonTypes::new(&arenas.type_, &interner); | |
3482 | ||
3483 | tls::enter(ctxt { | |
3484 | arenas: arenas, | |
3485 | interner: interner, | |
3486 | substs_interner: RefCell::new(FnvHashMap()), | |
3487 | bare_fn_interner: RefCell::new(FnvHashMap()), | |
3488 | region_interner: RefCell::new(FnvHashMap()), | |
3489 | stability_interner: RefCell::new(FnvHashMap()), | |
3490 | types: common_types, | |
3491 | named_region_map: named_region_map, | |
3492 | region_maps: region_maps, | |
3493 | free_region_maps: RefCell::new(FnvHashMap()), | |
3494 | item_variance_map: RefCell::new(DefIdMap()), | |
3495 | variance_computed: Cell::new(false), | |
3496 | sess: s, | |
3497 | def_map: def_map, | |
3498 | tables: RefCell::new(Tables::empty()), | |
3499 | impl_trait_refs: RefCell::new(DefIdMap()), | |
3500 | trait_defs: RefCell::new(DefIdMap()), | |
3501 | predicates: RefCell::new(DefIdMap()), | |
3502 | super_predicates: RefCell::new(DefIdMap()), | |
3503 | fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()), | |
3504 | map: map, | |
3505 | freevars: freevars, | |
3506 | tcache: RefCell::new(DefIdMap()), | |
3507 | rcache: RefCell::new(FnvHashMap()), | |
3508 | tc_cache: RefCell::new(FnvHashMap()), | |
3509 | ast_ty_to_ty_cache: RefCell::new(NodeMap()), | |
3510 | enum_var_cache: RefCell::new(DefIdMap()), | |
3511 | impl_or_trait_items: RefCell::new(DefIdMap()), | |
3512 | trait_item_def_ids: RefCell::new(DefIdMap()), | |
3513 | trait_items_cache: RefCell::new(DefIdMap()), | |
3514 | ty_param_defs: RefCell::new(NodeMap()), | |
3515 | normalized_cache: RefCell::new(FnvHashMap()), | |
3516 | lang_items: lang_items, | |
3517 | provided_method_sources: RefCell::new(DefIdMap()), | |
3518 | struct_fields: RefCell::new(DefIdMap()), | |
3519 | destructor_for_type: RefCell::new(DefIdMap()), | |
3520 | destructors: RefCell::new(DefIdSet()), | |
3521 | inherent_impls: RefCell::new(DefIdMap()), | |
3522 | impl_items: RefCell::new(DefIdMap()), | |
3523 | used_unsafe: RefCell::new(NodeSet()), | |
3524 | used_mut_nodes: RefCell::new(NodeSet()), | |
3525 | populated_external_types: RefCell::new(DefIdSet()), | |
3526 | populated_external_primitive_impls: RefCell::new(DefIdSet()), | |
3527 | extern_const_statics: RefCell::new(DefIdMap()), | |
3528 | extern_const_variants: RefCell::new(DefIdMap()), | |
3529 | extern_const_fns: RefCell::new(DefIdMap()), | |
3530 | dependency_formats: RefCell::new(FnvHashMap()), | |
3531 | node_lint_levels: RefCell::new(FnvHashMap()), | |
3532 | transmute_restrictions: RefCell::new(Vec::new()), | |
3533 | stability: RefCell::new(stability), | |
3534 | selection_cache: traits::SelectionCache::new(), | |
3535 | repr_hint_cache: RefCell::new(DefIdMap()), | |
3536 | const_qualif_map: RefCell::new(NodeMap()), | |
3537 | custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), | |
3538 | cast_kinds: RefCell::new(NodeMap()), | |
3539 | fragment_infos: RefCell::new(DefIdMap()), | |
3540 | }, f) | |
223e47cc LB |
3541 | } |
3542 | ||
c1a9b12d SL |
3543 | // Type constructors |
3544 | ||
3545 | pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> { | |
3546 | if let Some(substs) = self.substs_interner.borrow().get(&substs) { | |
3547 | return *substs; | |
3548 | } | |
3549 | ||
3550 | let substs = self.arenas.substs.alloc(substs); | |
3551 | self.substs_interner.borrow_mut().insert(substs, substs); | |
3552 | substs | |
3553 | } | |
3554 | ||
3555 | /// Create an unsafe fn ty based on a safe fn ty. | |
3556 | pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { | |
3557 | assert_eq!(bare_fn.unsafety, ast::Unsafety::Normal); | |
3558 | let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy { | |
3559 | unsafety: ast::Unsafety::Unsafe, | |
3560 | abi: bare_fn.abi, | |
3561 | sig: bare_fn.sig.clone() | |
3562 | }); | |
3563 | self.mk_fn(None, unsafe_fn_ty_a) | |
1a4d82fc | 3564 | } |
223e47cc | 3565 | |
c1a9b12d SL |
3566 | pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> { |
3567 | if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) { | |
3568 | return *bare_fn; | |
3569 | } | |
3570 | ||
3571 | let bare_fn = self.arenas.bare_fn.alloc(bare_fn); | |
3572 | self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn); | |
3573 | bare_fn | |
223e47cc | 3574 | } |
223e47cc | 3575 | |
c1a9b12d SL |
3576 | pub fn mk_region(&self, region: Region) -> &'tcx Region { |
3577 | if let Some(region) = self.region_interner.borrow().get(®ion) { | |
3578 | return *region; | |
3579 | } | |
223e47cc | 3580 | |
c1a9b12d SL |
3581 | let region = self.arenas.region.alloc(region); |
3582 | self.region_interner.borrow_mut().insert(region, region); | |
3583 | region | |
3584 | } | |
223e47cc | 3585 | |
c1a9b12d SL |
3586 | pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind { |
3587 | *self.tables.borrow().closure_kinds.get(&def_id).unwrap() | |
3588 | } | |
3589 | ||
3590 | pub fn closure_type(&self, | |
3591 | def_id: ast::DefId, | |
3592 | substs: &ClosureSubsts<'tcx>) | |
3593 | -> ty::ClosureTy<'tcx> | |
3594 | { | |
3595 | self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs) | |
3596 | } | |
223e47cc | 3597 | |
c1a9b12d SL |
3598 | pub fn type_parameter_def(&self, |
3599 | node_id: ast::NodeId) | |
3600 | -> TypeParameterDef<'tcx> | |
3601 | { | |
3602 | self.ty_param_defs.borrow().get(&node_id).unwrap().clone() | |
3603 | } | |
223e47cc | 3604 | |
c1a9b12d SL |
3605 | pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> Option<ast::Mutability> { |
3606 | pat_util::pat_contains_ref_binding(&self.def_map, pat) | |
3607 | } | |
223e47cc | 3608 | |
c1a9b12d SL |
3609 | pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> Option<ast::Mutability> { |
3610 | pat_util::arm_contains_ref_binding(&self.def_map, arm) | |
3611 | } | |
223e47cc | 3612 | |
c1a9b12d SL |
3613 | fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>, |
3614 | interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>, | |
3615 | st: TypeVariants<'tcx>) | |
3616 | -> Ty<'tcx> { | |
3617 | let ty: Ty /* don't be &mut TyS */ = { | |
3618 | let mut interner = interner.borrow_mut(); | |
3619 | match interner.get(&st) { | |
3620 | Some(ty) => return *ty, | |
3621 | _ => () | |
3622 | } | |
223e47cc | 3623 | |
c1a9b12d | 3624 | let flags = FlagComputation::for_sty(&st); |
223e47cc | 3625 | |
c1a9b12d SL |
3626 | let ty = match () { |
3627 | () => type_arena.alloc(TyS { sty: st, | |
3628 | flags: Cell::new(flags.flags), | |
3629 | region_depth: flags.depth, }), | |
3630 | }; | |
223e47cc | 3631 | |
c1a9b12d SL |
3632 | interner.insert(InternedTy { ty: ty }, ty); |
3633 | ty | |
3634 | }; | |
223e47cc | 3635 | |
c1a9b12d SL |
3636 | debug!("Interned type: {:?} Pointer: {:?}", |
3637 | ty, ty as *const TyS); | |
3638 | ty | |
62682a34 | 3639 | } |
223e47cc | 3640 | |
c1a9b12d SL |
3641 | // Interns a type/name combination, stores the resulting box in cx.interner, |
3642 | // and returns the box as cast to an unsafe ptr (see comments for Ty above). | |
3643 | pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> { | |
3644 | ctxt::intern_ty(&self.arenas.type_, &self.interner, st) | |
3645 | } | |
223e47cc | 3646 | |
c1a9b12d SL |
3647 | pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> { |
3648 | match tm { | |
3649 | ast::TyIs => self.types.isize, | |
3650 | ast::TyI8 => self.types.i8, | |
3651 | ast::TyI16 => self.types.i16, | |
3652 | ast::TyI32 => self.types.i32, | |
3653 | ast::TyI64 => self.types.i64, | |
3654 | } | |
3655 | } | |
223e47cc | 3656 | |
c1a9b12d SL |
3657 | pub fn mk_mach_uint(&self, tm: ast::UintTy) -> Ty<'tcx> { |
3658 | match tm { | |
3659 | ast::TyUs => self.types.usize, | |
3660 | ast::TyU8 => self.types.u8, | |
3661 | ast::TyU16 => self.types.u16, | |
3662 | ast::TyU32 => self.types.u32, | |
3663 | ast::TyU64 => self.types.u64, | |
3664 | } | |
3665 | } | |
223e47cc | 3666 | |
c1a9b12d SL |
3667 | pub fn mk_mach_float(&self, tm: ast::FloatTy) -> Ty<'tcx> { |
3668 | match tm { | |
3669 | ast::TyF32 => self.types.f32, | |
3670 | ast::TyF64 => self.types.f64, | |
3671 | } | |
3672 | } | |
c34b1796 | 3673 | |
c1a9b12d SL |
3674 | pub fn mk_str(&self) -> Ty<'tcx> { |
3675 | self.mk_ty(TyStr) | |
3676 | } | |
223e47cc | 3677 | |
c1a9b12d SL |
3678 | pub fn mk_static_str(&self) -> Ty<'tcx> { |
3679 | self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str()) | |
3680 | } | |
1a4d82fc | 3681 | |
c1a9b12d SL |
3682 | pub fn mk_enum(&self, did: ast::DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
3683 | // take a copy of substs so that we own the vectors inside | |
3684 | self.mk_ty(TyEnum(did, substs)) | |
3685 | } | |
223e47cc | 3686 | |
c1a9b12d SL |
3687 | pub fn mk_box(&self, ty: Ty<'tcx>) -> Ty<'tcx> { |
3688 | self.mk_ty(TyBox(ty)) | |
3689 | } | |
223e47cc | 3690 | |
c1a9b12d SL |
3691 | pub fn mk_ptr(&self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { |
3692 | self.mk_ty(TyRawPtr(tm)) | |
3693 | } | |
223e47cc | 3694 | |
c1a9b12d SL |
3695 | pub fn mk_ref(&self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { |
3696 | self.mk_ty(TyRef(r, tm)) | |
3697 | } | |
223e47cc | 3698 | |
c1a9b12d SL |
3699 | pub fn mk_mut_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> { |
3700 | self.mk_ref(r, TypeAndMut {ty: ty, mutbl: ast::MutMutable}) | |
3701 | } | |
223e47cc | 3702 | |
c1a9b12d SL |
3703 | pub fn mk_imm_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> { |
3704 | self.mk_ref(r, TypeAndMut {ty: ty, mutbl: ast::MutImmutable}) | |
3705 | } | |
223e47cc | 3706 | |
c1a9b12d SL |
3707 | pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> { |
3708 | self.mk_ptr(TypeAndMut {ty: ty, mutbl: ast::MutMutable}) | |
3709 | } | |
223e47cc | 3710 | |
c1a9b12d SL |
3711 | pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> { |
3712 | self.mk_ptr(TypeAndMut {ty: ty, mutbl: ast::MutImmutable}) | |
3713 | } | |
970d7e83 | 3714 | |
c1a9b12d SL |
3715 | pub fn mk_nil_ptr(&self) -> Ty<'tcx> { |
3716 | self.mk_imm_ptr(self.mk_nil()) | |
3717 | } | |
223e47cc | 3718 | |
c1a9b12d SL |
3719 | pub fn mk_array(&self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> { |
3720 | self.mk_ty(TyArray(ty, n)) | |
3721 | } | |
3722 | ||
3723 | pub fn mk_slice(&self, ty: Ty<'tcx>) -> Ty<'tcx> { | |
3724 | self.mk_ty(TySlice(ty)) | |
3725 | } | |
3726 | ||
3727 | pub fn mk_tup(&self, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> { | |
3728 | self.mk_ty(TyTuple(ts)) | |
3729 | } | |
3730 | ||
3731 | pub fn mk_nil(&self) -> Ty<'tcx> { | |
3732 | self.mk_tup(Vec::new()) | |
3733 | } | |
3734 | ||
3735 | pub fn mk_bool(&self) -> Ty<'tcx> { | |
3736 | self.mk_ty(TyBool) | |
3737 | } | |
3738 | ||
3739 | pub fn mk_fn(&self, | |
3740 | opt_def_id: Option<ast::DefId>, | |
3741 | fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> { | |
3742 | self.mk_ty(TyBareFn(opt_def_id, fty)) | |
3743 | } | |
3744 | ||
3745 | pub fn mk_ctor_fn(&self, | |
3746 | def_id: ast::DefId, | |
3747 | input_tys: &[Ty<'tcx>], | |
3748 | output: Ty<'tcx>) -> Ty<'tcx> { | |
3749 | let input_args = input_tys.iter().cloned().collect(); | |
3750 | self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy { | |
3751 | unsafety: ast::Unsafety::Normal, | |
3752 | abi: abi::Rust, | |
3753 | sig: ty::Binder(FnSig { | |
3754 | inputs: input_args, | |
3755 | output: ty::FnConverging(output), | |
3756 | variadic: false | |
3757 | }) | |
3758 | })) | |
3759 | } | |
3760 | ||
3761 | pub fn mk_trait(&self, | |
3762 | principal: ty::PolyTraitRef<'tcx>, | |
3763 | bounds: ExistentialBounds<'tcx>) | |
3764 | -> Ty<'tcx> | |
3765 | { | |
3766 | assert!(bound_list_is_sorted(&bounds.projection_bounds)); | |
3767 | ||
3768 | let inner = box TraitTy { | |
3769 | principal: principal, | |
3770 | bounds: bounds | |
3771 | }; | |
3772 | self.mk_ty(TyTrait(inner)) | |
3773 | } | |
3774 | ||
3775 | pub fn mk_projection(&self, | |
3776 | trait_ref: TraitRef<'tcx>, | |
3777 | item_name: ast::Name) | |
3778 | -> Ty<'tcx> { | |
3779 | // take a copy of substs so that we own the vectors inside | |
3780 | let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; | |
3781 | self.mk_ty(TyProjection(inner)) | |
3782 | } | |
3783 | ||
3784 | pub fn mk_struct(&self, struct_id: ast::DefId, | |
3785 | substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { | |
3786 | // take a copy of substs so that we own the vectors inside | |
3787 | self.mk_ty(TyStruct(struct_id, substs)) | |
3788 | } | |
3789 | ||
3790 | pub fn mk_closure(&self, | |
3791 | closure_id: ast::DefId, | |
3792 | substs: &'tcx Substs<'tcx>, | |
3793 | tys: Vec<Ty<'tcx>>) | |
3794 | -> Ty<'tcx> { | |
3795 | self.mk_closure_from_closure_substs(closure_id, Box::new(ClosureSubsts { | |
3796 | func_substs: substs, | |
3797 | upvar_tys: tys | |
3798 | })) | |
3799 | } | |
3800 | ||
3801 | pub fn mk_closure_from_closure_substs(&self, | |
3802 | closure_id: ast::DefId, | |
3803 | closure_substs: Box<ClosureSubsts<'tcx>>) | |
3804 | -> Ty<'tcx> { | |
3805 | self.mk_ty(TyClosure(closure_id, closure_substs)) | |
3806 | } | |
3807 | ||
3808 | pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> { | |
3809 | self.mk_infer(TyVar(v)) | |
3810 | } | |
3811 | ||
3812 | pub fn mk_int_var(&self, v: IntVid) -> Ty<'tcx> { | |
3813 | self.mk_infer(IntVar(v)) | |
3814 | } | |
3815 | ||
3816 | pub fn mk_float_var(&self, v: FloatVid) -> Ty<'tcx> { | |
3817 | self.mk_infer(FloatVar(v)) | |
3818 | } | |
3819 | ||
3820 | pub fn mk_infer(&self, it: InferTy) -> Ty<'tcx> { | |
3821 | self.mk_ty(TyInfer(it)) | |
3822 | } | |
3823 | ||
3824 | pub fn mk_param(&self, | |
3825 | space: subst::ParamSpace, | |
3826 | index: u32, | |
3827 | name: ast::Name) -> Ty<'tcx> { | |
3828 | self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name })) | |
3829 | } | |
3830 | ||
3831 | pub fn mk_self_type(&self) -> Ty<'tcx> { | |
3832 | self.mk_param(subst::SelfSpace, 0, special_idents::type_self.name) | |
3833 | } | |
223e47cc | 3834 | |
c1a9b12d SL |
3835 | pub fn mk_param_from_def(&self, def: &TypeParameterDef) -> Ty<'tcx> { |
3836 | self.mk_param(def.space, def.index, def.name) | |
3837 | } | |
1a4d82fc | 3838 | } |
223e47cc | 3839 | |
c1a9b12d SL |
3840 | fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool { |
3841 | bounds.is_empty() || | |
3842 | bounds[1..].iter().enumerate().all( | |
3843 | |(index, bound)| bounds[index].sort_key() <= bound.sort_key()) | |
223e47cc LB |
3844 | } |
3845 | ||
c1a9b12d SL |
3846 | pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) { |
3847 | bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())) | |
223e47cc LB |
3848 | } |
3849 | ||
1a4d82fc JJ |
3850 | impl<'tcx> TyS<'tcx> { |
3851 | /// Iterator that walks `self` and any types reachable from | |
3852 | /// `self`, in depth-first order. Note that just walks the types | |
3853 | /// that appear in `self`, it does not descend into the fields of | |
3854 | /// structs or variants. For example: | |
3855 | /// | |
3856 | /// ```notrust | |
c34b1796 AL |
3857 | /// isize => { isize } |
3858 | /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize } | |
3859 | /// [isize] => { [isize], isize } | |
1a4d82fc JJ |
3860 | /// ``` |
3861 | pub fn walk(&'tcx self) -> TypeWalker<'tcx> { | |
3862 | TypeWalker::new(self) | |
970d7e83 | 3863 | } |
970d7e83 | 3864 | |
c34b1796 AL |
3865 | /// Iterator that walks the immediate children of `self`. Hence |
3866 | /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]` | |
3867 | /// (but not `i32`, like `walk`). | |
3868 | pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> { | |
3869 | ty_walk::walk_shallow(self) | |
223e47cc | 3870 | } |
85aaf69f SL |
3871 | |
3872 | pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> { | |
3873 | match self.sty { | |
62682a34 | 3874 | ty::TyParam(ref d) => Some(d.clone()), |
85aaf69f SL |
3875 | _ => None, |
3876 | } | |
3877 | } | |
c34b1796 AL |
3878 | |
3879 | pub fn is_param(&self, space: ParamSpace, index: u32) -> bool { | |
3880 | match self.sty { | |
62682a34 | 3881 | ty::TyParam(ref data) => data.space == space && data.idx == index, |
c34b1796 AL |
3882 | _ => false, |
3883 | } | |
3884 | } | |
223e47cc | 3885 | |
c1a9b12d SL |
3886 | /// Walks `ty` and any types appearing within `ty`, invoking the |
3887 | /// callback `f` on each type. If the callback returns false, then the | |
3888 | /// children of the current type are ignored. | |
3889 | /// | |
3890 | /// Note: prefer `ty.walk()` where possible. | |
3891 | pub fn maybe_walk<F>(&'tcx self, mut f: F) | |
3892 | where F : FnMut(Ty<'tcx>) -> bool | |
3893 | { | |
3894 | let mut walker = self.walk(); | |
3895 | while let Some(ty) = walker.next() { | |
3896 | if !f(ty) { | |
3897 | walker.skip_current_subtree(); | |
3898 | } | |
1a4d82fc JJ |
3899 | } |
3900 | } | |
223e47cc LB |
3901 | } |
3902 | ||
1a4d82fc JJ |
3903 | impl ParamTy { |
3904 | pub fn new(space: subst::ParamSpace, | |
3905 | index: u32, | |
3906 | name: ast::Name) | |
3907 | -> ParamTy { | |
3908 | ParamTy { space: space, idx: index, name: name } | |
3909 | } | |
223e47cc | 3910 | |
1a4d82fc JJ |
3911 | pub fn for_self() -> ParamTy { |
3912 | ParamTy::new(subst::SelfSpace, 0, special_idents::type_self.name) | |
3913 | } | |
223e47cc | 3914 | |
1a4d82fc JJ |
3915 | pub fn for_def(def: &TypeParameterDef) -> ParamTy { |
3916 | ParamTy::new(def.space, def.index, def.name) | |
3917 | } | |
223e47cc | 3918 | |
c1a9b12d SL |
3919 | pub fn to_ty<'tcx>(self, tcx: &ctxt<'tcx>) -> Ty<'tcx> { |
3920 | tcx.mk_param(self.space, self.idx, self.name) | |
223e47cc | 3921 | } |
223e47cc | 3922 | |
1a4d82fc JJ |
3923 | pub fn is_self(&self) -> bool { |
3924 | self.space == subst::SelfSpace && self.idx == 0 | |
223e47cc LB |
3925 | } |
3926 | } | |
3927 | ||
1a4d82fc JJ |
3928 | impl<'tcx> ItemSubsts<'tcx> { |
3929 | pub fn empty() -> ItemSubsts<'tcx> { | |
3930 | ItemSubsts { substs: Substs::empty() } | |
3931 | } | |
223e47cc | 3932 | |
1a4d82fc JJ |
3933 | pub fn is_noop(&self) -> bool { |
3934 | self.substs.is_noop() | |
223e47cc LB |
3935 | } |
3936 | } | |
3937 | ||
1a4d82fc | 3938 | // Type utilities |
c1a9b12d SL |
3939 | impl<'tcx> TyS<'tcx> { |
3940 | pub fn is_nil(&self) -> bool { | |
3941 | match self.sty { | |
3942 | TyTuple(ref tys) => tys.is_empty(), | |
3943 | _ => false | |
3944 | } | |
223e47cc | 3945 | } |
970d7e83 | 3946 | |
c1a9b12d SL |
3947 | pub fn is_empty(&self, cx: &ctxt) -> bool { |
3948 | match self.sty { | |
3949 | TyEnum(did, _) => cx.enum_variants(did).is_empty(), | |
3950 | _ => false | |
3951 | } | |
223e47cc | 3952 | } |
1a4d82fc | 3953 | |
c1a9b12d SL |
3954 | pub fn is_ty_var(&self) -> bool { |
3955 | match self.sty { | |
3956 | TyInfer(TyVar(_)) => true, | |
3957 | _ => false | |
3958 | } | |
223e47cc | 3959 | } |
223e47cc | 3960 | |
c1a9b12d | 3961 | pub fn is_bool(&self) -> bool { self.sty == TyBool } |
223e47cc | 3962 | |
c1a9b12d SL |
3963 | pub fn is_self(&self) -> bool { |
3964 | match self.sty { | |
3965 | TyParam(ref p) => p.space == subst::SelfSpace, | |
3966 | _ => false | |
3967 | } | |
223e47cc | 3968 | } |
223e47cc | 3969 | |
c1a9b12d SL |
3970 | fn is_slice(&self) -> bool { |
3971 | match self.sty { | |
3972 | TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty { | |
3973 | TySlice(_) | TyStr => true, | |
3974 | _ => false, | |
3975 | }, | |
3976 | _ => false | |
3977 | } | |
1a4d82fc | 3978 | } |
223e47cc | 3979 | |
c1a9b12d SL |
3980 | pub fn is_structural(&self) -> bool { |
3981 | match self.sty { | |
3982 | TyStruct(..) | TyTuple(_) | TyEnum(..) | | |
3983 | TyArray(..) | TyClosure(..) => true, | |
3984 | _ => self.is_slice() | self.is_trait() | |
3985 | } | |
970d7e83 | 3986 | } |
970d7e83 | 3987 | |
c1a9b12d SL |
3988 | pub fn is_simd(&self, cx: &ctxt) -> bool { |
3989 | match self.sty { | |
3990 | TyStruct(did, _) => cx.lookup_simd(did), | |
3991 | _ => false | |
223e47cc LB |
3992 | } |
3993 | } | |
223e47cc | 3994 | |
c1a9b12d SL |
3995 | pub fn sequence_element_type(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> { |
3996 | match self.sty { | |
3997 | TyArray(ty, _) | TySlice(ty) => ty, | |
3998 | TyStr => cx.mk_mach_uint(ast::TyU8), | |
3999 | _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}", | |
4000 | self)), | |
223e47cc LB |
4001 | } |
4002 | } | |
223e47cc | 4003 | |
c1a9b12d SL |
4004 | pub fn simd_type(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> { |
4005 | match self.sty { | |
4006 | TyStruct(did, substs) => { | |
4007 | let fields = cx.lookup_struct_fields(did); | |
4008 | cx.lookup_field_type(did, fields[0].id, substs) | |
4009 | } | |
4010 | _ => panic!("simd_type called on invalid type") | |
4011 | } | |
223e47cc | 4012 | } |
223e47cc | 4013 | |
c1a9b12d SL |
4014 | pub fn simd_size(&self, cx: &ctxt) -> usize { |
4015 | match self.sty { | |
4016 | TyStruct(did, _) => { | |
4017 | cx.lookup_struct_fields(did).len() | |
4018 | } | |
4019 | _ => panic!("simd_size called on invalid type") | |
4020 | } | |
223e47cc | 4021 | } |
223e47cc | 4022 | |
c1a9b12d SL |
4023 | pub fn is_region_ptr(&self) -> bool { |
4024 | match self.sty { | |
4025 | TyRef(..) => true, | |
4026 | _ => false | |
4027 | } | |
223e47cc | 4028 | } |
223e47cc | 4029 | |
c1a9b12d SL |
4030 | pub fn is_unsafe_ptr(&self) -> bool { |
4031 | match self.sty { | |
4032 | TyRawPtr(_) => return true, | |
4033 | _ => return false | |
4034 | } | |
4035 | } | |
4036 | ||
4037 | pub fn is_unique(&self) -> bool { | |
4038 | match self.sty { | |
4039 | TyBox(_) => true, | |
4040 | _ => false | |
4041 | } | |
4042 | } | |
4043 | ||
4044 | /* | |
4045 | A scalar type is one that denotes an atomic datum, with no sub-components. | |
4046 | (A TyRawPtr is scalar because it represents a non-managed pointer, so its | |
4047 | contents are abstract to rustc.) | |
4048 | */ | |
4049 | pub fn is_scalar(&self) -> bool { | |
4050 | match self.sty { | |
4051 | TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) | | |
4052 | TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) | | |
4053 | TyBareFn(..) | TyRawPtr(_) => true, | |
4054 | _ => false | |
4055 | } | |
223e47cc | 4056 | } |
223e47cc | 4057 | |
c1a9b12d SL |
4058 | /// Returns true if this type is a floating point type and false otherwise. |
4059 | pub fn is_floating_point(&self) -> bool { | |
4060 | match self.sty { | |
4061 | TyFloat(_) | | |
4062 | TyInfer(FloatVar(_)) => true, | |
4063 | _ => false, | |
4064 | } | |
4065 | } | |
c34b1796 | 4066 | |
c1a9b12d SL |
4067 | pub fn ty_to_def_id(&self) -> Option<ast::DefId> { |
4068 | match self.sty { | |
4069 | TyTrait(ref tt) => Some(tt.principal_def_id()), | |
4070 | TyStruct(id, _) | | |
4071 | TyEnum(id, _) | | |
4072 | TyClosure(id, _) => Some(id), | |
4073 | _ => None | |
4074 | } | |
223e47cc LB |
4075 | } |
4076 | } | |
4077 | ||
1a4d82fc JJ |
4078 | /// Type contents is how the type checker reasons about kinds. |
4079 | /// They track what kinds of things are found within a type. You can | |
4080 | /// think of them as kind of an "anti-kind". They track the kinds of values | |
4081 | /// and thinks that are contained in types. Having a larger contents for | |
4082 | /// a type tends to rule that type *out* from various kinds. For example, | |
4083 | /// a type that contains a reference is not sendable. | |
4084 | /// | |
4085 | /// The reason we compute type contents and not kinds is that it is | |
4086 | /// easier for me (nmatsakis) to think about what is contained within | |
4087 | /// a type than to think about what is *not* contained within a type. | |
4088 | #[derive(Clone, Copy)] | |
4089 | pub struct TypeContents { | |
4090 | pub bits: u64 | |
4091 | } | |
4092 | ||
4093 | macro_rules! def_type_content_sets { | |
4094 | (mod $mname:ident { $($name:ident = $bits:expr),+ }) => { | |
4095 | #[allow(non_snake_case)] | |
4096 | mod $mname { | |
4097 | use middle::ty::TypeContents; | |
4098 | $( | |
4099 | #[allow(non_upper_case_globals)] | |
4100 | pub const $name: TypeContents = TypeContents { bits: $bits }; | |
4101 | )+ | |
970d7e83 LB |
4102 | } |
4103 | } | |
4104 | } | |
4105 | ||
1a4d82fc JJ |
4106 | def_type_content_sets! { |
4107 | mod TC { | |
4108 | None = 0b0000_0000__0000_0000__0000, | |
223e47cc | 4109 | |
1a4d82fc | 4110 | // Things that are interior to the value (first nibble): |
1a4d82fc JJ |
4111 | InteriorUnsafe = 0b0000_0000__0000_0000__0010, |
4112 | InteriorParam = 0b0000_0000__0000_0000__0100, | |
4113 | // InteriorAll = 0b00000000__00000000__1111, | |
223e47cc | 4114 | |
1a4d82fc JJ |
4115 | // Things that are owned by the value (second and third nibbles): |
4116 | OwnsOwned = 0b0000_0000__0000_0001__0000, | |
4117 | OwnsDtor = 0b0000_0000__0000_0010__0000, | |
1a4d82fc | 4118 | OwnsAll = 0b0000_0000__1111_1111__0000, |
223e47cc | 4119 | |
1a4d82fc JJ |
4120 | // Things that mean drop glue is necessary |
4121 | NeedsDrop = 0b0000_0000__0000_0111__0000, | |
223e47cc | 4122 | |
1a4d82fc JJ |
4123 | // All bits |
4124 | All = 0b1111_1111__1111_1111__1111 | |
4125 | } | |
223e47cc LB |
4126 | } |
4127 | ||
1a4d82fc JJ |
4128 | impl TypeContents { |
4129 | pub fn when(&self, cond: bool) -> TypeContents { | |
4130 | if cond {*self} else {TC::None} | |
4131 | } | |
223e47cc | 4132 | |
1a4d82fc JJ |
4133 | pub fn intersects(&self, tc: TypeContents) -> bool { |
4134 | (self.bits & tc.bits) != 0 | |
4135 | } | |
223e47cc | 4136 | |
1a4d82fc JJ |
4137 | pub fn owns_owned(&self) -> bool { |
4138 | self.intersects(TC::OwnsOwned) | |
4139 | } | |
223e47cc | 4140 | |
1a4d82fc JJ |
4141 | pub fn interior_param(&self) -> bool { |
4142 | self.intersects(TC::InteriorParam) | |
4143 | } | |
223e47cc | 4144 | |
1a4d82fc JJ |
4145 | pub fn interior_unsafe(&self) -> bool { |
4146 | self.intersects(TC::InteriorUnsafe) | |
4147 | } | |
223e47cc | 4148 | |
1a4d82fc JJ |
4149 | pub fn needs_drop(&self, _: &ctxt) -> bool { |
4150 | self.intersects(TC::NeedsDrop) | |
4151 | } | |
223e47cc | 4152 | |
1a4d82fc JJ |
4153 | /// Includes only those bits that still apply when indirected through a `Box` pointer |
4154 | pub fn owned_pointer(&self) -> TypeContents { | |
c1a9b12d | 4155 | TC::OwnsOwned | (*self & TC::OwnsAll) |
1a4d82fc | 4156 | } |
223e47cc | 4157 | |
1a4d82fc JJ |
4158 | pub fn union<T, F>(v: &[T], mut f: F) -> TypeContents where |
4159 | F: FnMut(&T) -> TypeContents, | |
4160 | { | |
4161 | v.iter().fold(TC::None, |tc, ty| tc | f(ty)) | |
223e47cc LB |
4162 | } |
4163 | ||
1a4d82fc JJ |
4164 | pub fn has_dtor(&self) -> bool { |
4165 | self.intersects(TC::OwnsDtor) | |
4166 | } | |
4167 | } | |
223e47cc | 4168 | |
1a4d82fc JJ |
4169 | impl ops::BitOr for TypeContents { |
4170 | type Output = TypeContents; | |
4171 | ||
4172 | fn bitor(self, other: TypeContents) -> TypeContents { | |
4173 | TypeContents {bits: self.bits | other.bits} | |
223e47cc LB |
4174 | } |
4175 | } | |
4176 | ||
1a4d82fc JJ |
4177 | impl ops::BitAnd for TypeContents { |
4178 | type Output = TypeContents; | |
4179 | ||
4180 | fn bitand(self, other: TypeContents) -> TypeContents { | |
4181 | TypeContents {bits: self.bits & other.bits} | |
970d7e83 LB |
4182 | } |
4183 | } | |
4184 | ||
1a4d82fc JJ |
4185 | impl ops::Sub for TypeContents { |
4186 | type Output = TypeContents; | |
4187 | ||
4188 | fn sub(self, other: TypeContents) -> TypeContents { | |
4189 | TypeContents {bits: self.bits & !other.bits} | |
4190 | } | |
223e47cc LB |
4191 | } |
4192 | ||
85aaf69f | 4193 | impl fmt::Debug for TypeContents { |
1a4d82fc JJ |
4194 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
4195 | write!(f, "TypeContents({:b})", self.bits) | |
223e47cc LB |
4196 | } |
4197 | } | |
4198 | ||
c1a9b12d SL |
4199 | impl<'tcx> TyS<'tcx> { |
4200 | pub fn type_contents(&'tcx self, cx: &ctxt<'tcx>) -> TypeContents { | |
4201 | return memoized(&cx.tc_cache, self, |ty| { | |
4202 | tc_ty(cx, ty, &mut FnvHashMap()) | |
4203 | }); | |
1a4d82fc | 4204 | |
c1a9b12d SL |
4205 | fn tc_ty<'tcx>(cx: &ctxt<'tcx>, |
4206 | ty: Ty<'tcx>, | |
4207 | cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents | |
4208 | { | |
4209 | // Subtle: Note that we are *not* using cx.tc_cache here but rather a | |
4210 | // private cache for this walk. This is needed in the case of cyclic | |
4211 | // types like: | |
4212 | // | |
4213 | // struct List { next: Box<Option<List>>, ... } | |
4214 | // | |
4215 | // When computing the type contents of such a type, we wind up deeply | |
4216 | // recursing as we go. So when we encounter the recursive reference | |
4217 | // to List, we temporarily use TC::None as its contents. Later we'll | |
4218 | // patch up the cache with the correct value, once we've computed it | |
4219 | // (this is basically a co-inductive process, if that helps). So in | |
4220 | // the end we'll compute TC::OwnsOwned, in this case. | |
4221 | // | |
4222 | // The problem is, as we are doing the computation, we will also | |
4223 | // compute an *intermediate* contents for, e.g., Option<List> of | |
4224 | // TC::None. This is ok during the computation of List itself, but if | |
4225 | // we stored this intermediate value into cx.tc_cache, then later | |
4226 | // requests for the contents of Option<List> would also yield TC::None | |
4227 | // which is incorrect. This value was computed based on the crutch | |
4228 | // value for the type contents of list. The correct value is | |
4229 | // TC::OwnsOwned. This manifested as issue #4821. | |
4230 | match cache.get(&ty) { | |
4231 | Some(tc) => { return *tc; } | |
4232 | None => {} | |
4233 | } | |
4234 | match cx.tc_cache.borrow().get(&ty) { // Must check both caches! | |
4235 | Some(tc) => { return *tc; } | |
4236 | None => {} | |
4237 | } | |
4238 | cache.insert(ty, TC::None); | |
4239 | ||
4240 | let result = match ty.sty { | |
4241 | // usize and isize are ffi-unsafe | |
4242 | TyUint(ast::TyUs) | TyInt(ast::TyIs) => { | |
4243 | TC::None | |
1a4d82fc | 4244 | } |
1a4d82fc | 4245 | |
c1a9b12d SL |
4246 | // Scalar and unique types are sendable, and durable |
4247 | TyInfer(ty::FreshIntTy(_)) | TyInfer(ty::FreshFloatTy(_)) | | |
4248 | TyBool | TyInt(_) | TyUint(_) | TyFloat(_) | | |
4249 | TyBareFn(..) | ty::TyChar => { | |
4250 | TC::None | |
4251 | } | |
1a4d82fc | 4252 | |
c1a9b12d SL |
4253 | TyBox(typ) => { |
4254 | tc_ty(cx, typ, cache).owned_pointer() | |
1a4d82fc | 4255 | } |
1a4d82fc | 4256 | |
c1a9b12d SL |
4257 | TyTrait(_) => { |
4258 | TC::All - TC::InteriorParam | |
4259 | } | |
1a4d82fc | 4260 | |
c1a9b12d SL |
4261 | TyRawPtr(_) => { |
4262 | TC::None | |
4263 | } | |
1a4d82fc | 4264 | |
c1a9b12d SL |
4265 | TyRef(_, _) => { |
4266 | TC::None | |
4267 | } | |
1a4d82fc | 4268 | |
c1a9b12d SL |
4269 | TyArray(ty, _) => { |
4270 | tc_ty(cx, ty, cache) | |
1a4d82fc JJ |
4271 | } |
4272 | ||
c1a9b12d SL |
4273 | TySlice(ty) => { |
4274 | tc_ty(cx, ty, cache) | |
1a4d82fc | 4275 | } |
c1a9b12d | 4276 | TyStr => TC::None, |
1a4d82fc | 4277 | |
c1a9b12d SL |
4278 | TyStruct(did, substs) => { |
4279 | let flds = cx.struct_fields(did, substs); | |
4280 | let mut res = | |
4281 | TypeContents::union(&flds[..], | |
4282 | |f| tc_ty(cx, f.mt.ty, cache)); | |
1a4d82fc | 4283 | |
c1a9b12d SL |
4284 | if cx.has_dtor(did) { |
4285 | res = res | TC::OwnsDtor; | |
4286 | } | |
4287 | apply_lang_items(cx, did, res) | |
4288 | } | |
1a4d82fc | 4289 | |
c1a9b12d SL |
4290 | TyClosure(_, ref substs) => { |
4291 | TypeContents::union(&substs.upvar_tys, |ty| tc_ty(cx, &ty, cache)) | |
4292 | } | |
1a4d82fc | 4293 | |
c1a9b12d SL |
4294 | TyTuple(ref tys) => { |
4295 | TypeContents::union(&tys[..], | |
4296 | |ty| tc_ty(cx, *ty, cache)) | |
1a4d82fc JJ |
4297 | } |
4298 | ||
c1a9b12d SL |
4299 | TyEnum(did, substs) => { |
4300 | let variants = cx.substd_enum_variants(did, substs); | |
4301 | let mut res = | |
4302 | TypeContents::union(&variants[..], |variant| { | |
4303 | TypeContents::union(&variant.args, | |
4304 | |arg_ty| { | |
4305 | tc_ty(cx, *arg_ty, cache) | |
4306 | }) | |
4307 | }); | |
4308 | ||
4309 | if cx.has_dtor(did) { | |
4310 | res = res | TC::OwnsDtor; | |
1a4d82fc JJ |
4311 | } |
4312 | ||
c1a9b12d | 4313 | apply_lang_items(cx, did, res) |
1a4d82fc JJ |
4314 | } |
4315 | ||
c1a9b12d SL |
4316 | TyProjection(..) | |
4317 | TyParam(_) => { | |
4318 | TC::All | |
4319 | } | |
1a4d82fc | 4320 | |
c1a9b12d SL |
4321 | TyInfer(_) | |
4322 | TyError => { | |
4323 | cx.sess.bug("asked to compute contents of error type"); | |
4324 | } | |
4325 | }; | |
1a4d82fc | 4326 | |
c1a9b12d SL |
4327 | cache.insert(ty, result); |
4328 | result | |
4329 | } | |
1a4d82fc | 4330 | |
c1a9b12d SL |
4331 | fn apply_lang_items(cx: &ctxt, did: ast::DefId, tc: TypeContents) |
4332 | -> TypeContents { | |
4333 | if Some(did) == cx.lang_items.unsafe_cell_type() { | |
4334 | tc | TC::InteriorUnsafe | |
4335 | } else { | |
4336 | tc | |
1a4d82fc | 4337 | } |
c1a9b12d | 4338 | } |
1a4d82fc JJ |
4339 | } |
4340 | ||
c1a9b12d SL |
4341 | fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>, |
4342 | bound: ty::BuiltinBound, | |
4343 | span: Span) | |
4344 | -> bool | |
1a4d82fc | 4345 | { |
c1a9b12d SL |
4346 | let tcx = param_env.tcx; |
4347 | let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()), false); | |
1a4d82fc | 4348 | |
c1a9b12d SL |
4349 | let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, |
4350 | self, bound, span); | |
1a4d82fc | 4351 | |
c1a9b12d SL |
4352 | debug!("Ty::impls_bound({:?}, {:?}) = {:?}", |
4353 | self, bound, is_impld); | |
4354 | ||
4355 | is_impld | |
1a4d82fc | 4356 | } |
1a4d82fc | 4357 | |
c1a9b12d SL |
4358 | // FIXME (@jroesch): I made this public to use it, not sure if should be private |
4359 | pub fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>, | |
4360 | span: Span) -> bool { | |
4361 | if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) { | |
4362 | return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT); | |
1a4d82fc | 4363 | } |
1a4d82fc | 4364 | |
c1a9b12d | 4365 | assert!(!self.needs_infer()); |
1a4d82fc | 4366 | |
c1a9b12d SL |
4367 | // Fast-path for primitive types |
4368 | let result = match self.sty { | |
4369 | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | | |
4370 | TyRawPtr(..) | TyBareFn(..) | TyRef(_, TypeAndMut { | |
4371 | mutbl: ast::MutImmutable, .. | |
4372 | }) => Some(false), | |
1a4d82fc | 4373 | |
c1a9b12d SL |
4374 | TyStr | TyBox(..) | TyRef(_, TypeAndMut { |
4375 | mutbl: ast::MutMutable, .. | |
4376 | }) => Some(true), | |
1a4d82fc | 4377 | |
c1a9b12d SL |
4378 | TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) | |
4379 | TyClosure(..) | TyEnum(..) | TyStruct(..) | | |
4380 | TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None | |
4381 | }.unwrap_or_else(|| !self.impls_bound(param_env, ty::BoundCopy, span)); | |
62682a34 | 4382 | |
c1a9b12d SL |
4383 | if !self.has_param_types() && !self.has_self_ty() { |
4384 | self.flags.set(self.flags.get() | if result { | |
4385 | TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT | |
4386 | } else { | |
4387 | TypeFlags::MOVENESS_CACHED | |
4388 | }); | |
4389 | } | |
1a4d82fc | 4390 | |
c1a9b12d | 4391 | result |
62682a34 SL |
4392 | } |
4393 | ||
c1a9b12d SL |
4394 | #[inline] |
4395 | pub fn is_sized<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>, | |
4396 | span: Span) -> bool | |
4397 | { | |
4398 | if self.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) { | |
4399 | return self.flags.get().intersects(TypeFlags::IS_SIZED); | |
4400 | } | |
62682a34 | 4401 | |
c1a9b12d | 4402 | self.is_sized_uncached(param_env, span) |
62682a34 SL |
4403 | } |
4404 | ||
c1a9b12d SL |
4405 | fn is_sized_uncached<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>, |
4406 | span: Span) -> bool { | |
4407 | assert!(!self.needs_infer()); | |
1a4d82fc | 4408 | |
c1a9b12d SL |
4409 | // Fast-path for primitive types |
4410 | let result = match self.sty { | |
4411 | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | | |
4412 | TyBox(..) | TyRawPtr(..) | TyRef(..) | TyBareFn(..) | | |
4413 | TyArray(..) | TyTuple(..) | TyClosure(..) => Some(true), | |
1a4d82fc | 4414 | |
c1a9b12d | 4415 | TyStr | TyTrait(..) | TySlice(_) => Some(false), |
1a4d82fc | 4416 | |
c1a9b12d SL |
4417 | TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) | |
4418 | TyInfer(..) | TyError => None | |
4419 | }.unwrap_or_else(|| self.impls_bound(param_env, ty::BoundSized, span)); | |
1a4d82fc | 4420 | |
c1a9b12d SL |
4421 | if !self.has_param_types() && !self.has_self_ty() { |
4422 | self.flags.set(self.flags.get() | if result { | |
4423 | TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED | |
4424 | } else { | |
4425 | TypeFlags::SIZEDNESS_CACHED | |
4426 | }); | |
4427 | } | |
1a4d82fc | 4428 | |
c1a9b12d SL |
4429 | result |
4430 | } | |
1a4d82fc | 4431 | |
c1a9b12d SL |
4432 | // True if instantiating an instance of `r_ty` requires an instance of `r_ty`. |
4433 | pub fn is_instantiable(&'tcx self, cx: &ctxt<'tcx>) -> bool { | |
4434 | fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>, | |
4435 | r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool { | |
4436 | debug!("type_requires({:?}, {:?})?", | |
4437 | r_ty, ty); | |
4438 | ||
4439 | let r = r_ty == ty || subtypes_require(cx, seen, r_ty, ty); | |
4440 | ||
4441 | debug!("type_requires({:?}, {:?})? {:?}", | |
4442 | r_ty, ty, r); | |
4443 | return r; | |
4444 | } | |
4445 | ||
4446 | fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>, | |
4447 | r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool { | |
4448 | debug!("subtypes_require({:?}, {:?})?", | |
4449 | r_ty, ty); | |
4450 | ||
4451 | let r = match ty.sty { | |
4452 | // fixed length vectors need special treatment compared to | |
4453 | // normal vectors, since they don't necessarily have the | |
4454 | // possibility to have length zero. | |
4455 | TyArray(_, 0) => false, // don't need no contents | |
4456 | TyArray(ty, _) => type_requires(cx, seen, r_ty, ty), | |
4457 | ||
4458 | TyBool | | |
4459 | TyChar | | |
4460 | TyInt(_) | | |
4461 | TyUint(_) | | |
4462 | TyFloat(_) | | |
4463 | TyStr | | |
4464 | TyBareFn(..) | | |
4465 | TyParam(_) | | |
4466 | TyProjection(_) | | |
4467 | TySlice(_) => { | |
4468 | false | |
4469 | } | |
4470 | TyBox(typ) => { | |
4471 | type_requires(cx, seen, r_ty, typ) | |
4472 | } | |
4473 | TyRef(_, ref mt) => { | |
4474 | type_requires(cx, seen, r_ty, mt.ty) | |
4475 | } | |
62682a34 | 4476 | |
c1a9b12d SL |
4477 | TyRawPtr(..) => { |
4478 | false // unsafe ptrs can always be NULL | |
4479 | } | |
1a4d82fc | 4480 | |
c1a9b12d SL |
4481 | TyTrait(..) => { |
4482 | false | |
4483 | } | |
1a4d82fc | 4484 | |
c1a9b12d SL |
4485 | TyStruct(ref did, _) if seen.contains(did) => { |
4486 | false | |
4487 | } | |
1a4d82fc | 4488 | |
c1a9b12d SL |
4489 | TyStruct(did, substs) => { |
4490 | seen.push(did); | |
4491 | let fields = cx.struct_fields(did, substs); | |
4492 | let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty)); | |
4493 | seen.pop().unwrap(); | |
4494 | r | |
4495 | } | |
1a4d82fc | 4496 | |
c1a9b12d SL |
4497 | TyError | |
4498 | TyInfer(_) | | |
4499 | TyClosure(..) => { | |
4500 | // this check is run on type definitions, so we don't expect to see | |
4501 | // inference by-products or closure types | |
4502 | cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty)) | |
4503 | } | |
1a4d82fc | 4504 | |
c1a9b12d SL |
4505 | TyTuple(ref ts) => { |
4506 | ts.iter().any(|ty| type_requires(cx, seen, r_ty, *ty)) | |
4507 | } | |
1a4d82fc | 4508 | |
c1a9b12d SL |
4509 | TyEnum(ref did, _) if seen.contains(did) => { |
4510 | false | |
4511 | } | |
1a4d82fc | 4512 | |
c1a9b12d SL |
4513 | TyEnum(did, substs) => { |
4514 | seen.push(did); | |
4515 | let vs = cx.enum_variants(did); | |
4516 | let r = !vs.is_empty() && vs.iter().all(|variant| { | |
4517 | variant.args.iter().any(|aty| { | |
4518 | let sty = aty.subst(cx, substs); | |
4519 | type_requires(cx, seen, r_ty, sty) | |
4520 | }) | |
4521 | }); | |
4522 | seen.pop().unwrap(); | |
4523 | r | |
4524 | } | |
4525 | }; | |
1a4d82fc | 4526 | |
c1a9b12d SL |
4527 | debug!("subtypes_require({:?}, {:?})? {:?}", |
4528 | r_ty, ty, r); | |
1a4d82fc | 4529 | |
c1a9b12d SL |
4530 | return r; |
4531 | } | |
1a4d82fc | 4532 | |
c1a9b12d SL |
4533 | let mut seen = Vec::new(); |
4534 | !subtypes_require(cx, &mut seen, self, self) | |
1a4d82fc | 4535 | } |
1a4d82fc JJ |
4536 | } |
4537 | ||
4538 | /// Describes whether a type is representable. For types that are not | |
4539 | /// representable, 'SelfRecursive' and 'ContainsRecursive' are used to | |
4540 | /// distinguish between types that are recursive with themselves and types that | |
4541 | /// contain a different recursive type. These cases can therefore be treated | |
4542 | /// differently when reporting errors. | |
4543 | /// | |
4544 | /// The ordering of the cases is significant. They are sorted so that cmp::max | |
4545 | /// will keep the "more erroneous" of two values. | |
c34b1796 | 4546 | #[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)] |
1a4d82fc JJ |
4547 | pub enum Representability { |
4548 | Representable, | |
4549 | ContainsRecursive, | |
4550 | SelfRecursive, | |
4551 | } | |
4552 | ||
c1a9b12d SL |
4553 | impl<'tcx> TyS<'tcx> { |
4554 | /// Check whether a type is representable. This means it cannot contain unboxed | |
4555 | /// structural recursion. This check is needed for structs and enums. | |
4556 | pub fn is_representable(&'tcx self, cx: &ctxt<'tcx>, sp: Span) -> Representability { | |
4557 | ||
4558 | // Iterate until something non-representable is found | |
4559 | fn find_nonrepresentable<'tcx, It: Iterator<Item=Ty<'tcx>>>(cx: &ctxt<'tcx>, sp: Span, | |
4560 | seen: &mut Vec<Ty<'tcx>>, | |
4561 | iter: It) | |
4562 | -> Representability { | |
4563 | iter.fold(Representable, | |
4564 | |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty))) | |
4565 | } | |
4566 | ||
4567 | fn are_inner_types_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span, | |
4568 | seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>) | |
4569 | -> Representability { | |
4570 | match ty.sty { | |
4571 | TyTuple(ref ts) => { | |
4572 | find_nonrepresentable(cx, sp, seen, ts.iter().cloned()) | |
4573 | } | |
4574 | // Fixed-length vectors. | |
4575 | // FIXME(#11924) Behavior undecided for zero-length vectors. | |
4576 | TyArray(ty, _) => { | |
4577 | is_type_structurally_recursive(cx, sp, seen, ty) | |
4578 | } | |
4579 | TyStruct(did, substs) => { | |
4580 | let fields = cx.struct_fields(did, substs); | |
4581 | find_nonrepresentable(cx, sp, seen, fields.iter().map(|f| f.mt.ty)) | |
4582 | } | |
4583 | TyEnum(did, substs) => { | |
4584 | let vs = cx.enum_variants(did); | |
4585 | let iter = vs.iter() | |
4586 | .flat_map(|variant| &variant.args) | |
4587 | .map(|aty| { aty.subst_spanned(cx, substs, Some(sp)) }); | |
1a4d82fc | 4588 | |
c1a9b12d SL |
4589 | find_nonrepresentable(cx, sp, seen, iter) |
4590 | } | |
4591 | TyClosure(..) => { | |
4592 | // this check is run on type definitions, so we don't expect | |
4593 | // to see closure types | |
4594 | cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty)) | |
4595 | } | |
4596 | _ => Representable, | |
1a4d82fc | 4597 | } |
1a4d82fc | 4598 | } |
1a4d82fc | 4599 | |
c1a9b12d SL |
4600 | fn same_struct_or_enum_def_id(ty: Ty, did: DefId) -> bool { |
4601 | match ty.sty { | |
4602 | TyStruct(ty_did, _) | TyEnum(ty_did, _) => { | |
4603 | ty_did == did | |
4604 | } | |
4605 | _ => false | |
1a4d82fc | 4606 | } |
1a4d82fc | 4607 | } |
1a4d82fc | 4608 | |
c1a9b12d SL |
4609 | fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { |
4610 | match (&a.sty, &b.sty) { | |
4611 | (&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) | | |
4612 | (&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => { | |
4613 | if did_a != did_b { | |
4614 | return false; | |
4615 | } | |
1a4d82fc | 4616 | |
c1a9b12d SL |
4617 | let types_a = substs_a.types.get_slice(subst::TypeSpace); |
4618 | let types_b = substs_b.types.get_slice(subst::TypeSpace); | |
1a4d82fc | 4619 | |
c1a9b12d | 4620 | let mut pairs = types_a.iter().zip(types_b); |
1a4d82fc | 4621 | |
c1a9b12d SL |
4622 | pairs.all(|(&a, &b)| same_type(a, b)) |
4623 | } | |
4624 | _ => { | |
4625 | a == b | |
4626 | } | |
1a4d82fc JJ |
4627 | } |
4628 | } | |
1a4d82fc | 4629 | |
c1a9b12d SL |
4630 | // Does the type `ty` directly (without indirection through a pointer) |
4631 | // contain any types on stack `seen`? | |
4632 | fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span, | |
4633 | seen: &mut Vec<Ty<'tcx>>, | |
4634 | ty: Ty<'tcx>) -> Representability { | |
4635 | debug!("is_type_structurally_recursive: {:?}", ty); | |
1a4d82fc | 4636 | |
c1a9b12d SL |
4637 | match ty.sty { |
4638 | TyStruct(did, _) | TyEnum(did, _) => { | |
4639 | { | |
4640 | // Iterate through stack of previously seen types. | |
4641 | let mut iter = seen.iter(); | |
4642 | ||
4643 | // The first item in `seen` is the type we are actually curious about. | |
4644 | // We want to return SelfRecursive if this type contains itself. | |
4645 | // It is important that we DON'T take generic parameters into account | |
4646 | // for this check, so that Bar<T> in this example counts as SelfRecursive: | |
4647 | // | |
4648 | // struct Foo; | |
4649 | // struct Bar<T> { x: Bar<Foo> } | |
4650 | ||
4651 | match iter.next() { | |
4652 | Some(&seen_type) => { | |
4653 | if same_struct_or_enum_def_id(seen_type, did) { | |
4654 | debug!("SelfRecursive: {:?} contains {:?}", | |
4655 | seen_type, | |
4656 | ty); | |
4657 | return SelfRecursive; | |
4658 | } | |
4659 | } | |
4660 | None => {} | |
4661 | } | |
1a4d82fc | 4662 | |
c1a9b12d SL |
4663 | // We also need to know whether the first item contains other types |
4664 | // that are structurally recursive. If we don't catch this case, we | |
4665 | // will recurse infinitely for some inputs. | |
4666 | // | |
4667 | // It is important that we DO take generic parameters into account | |
4668 | // here, so that code like this is considered SelfRecursive, not | |
4669 | // ContainsRecursive: | |
4670 | // | |
4671 | // struct Foo { Option<Option<Foo>> } | |
4672 | ||
4673 | for &seen_type in iter { | |
4674 | if same_type(ty, seen_type) { | |
4675 | debug!("ContainsRecursive: {:?} contains {:?}", | |
62682a34 SL |
4676 | seen_type, |
4677 | ty); | |
c1a9b12d | 4678 | return ContainsRecursive; |
1a4d82fc JJ |
4679 | } |
4680 | } | |
1a4d82fc JJ |
4681 | } |
4682 | ||
c1a9b12d SL |
4683 | // For structs and enums, track all previously seen types by pushing them |
4684 | // onto the 'seen' stack. | |
4685 | seen.push(ty); | |
4686 | let out = are_inner_types_recursive(cx, sp, seen, ty); | |
4687 | seen.pop(); | |
4688 | out | |
4689 | } | |
4690 | _ => { | |
4691 | // No need to push in other cases. | |
4692 | are_inner_types_recursive(cx, sp, seen, ty) | |
1a4d82fc | 4693 | } |
1a4d82fc JJ |
4694 | } |
4695 | } | |
1a4d82fc | 4696 | |
c1a9b12d | 4697 | debug!("is_type_representable: {:?}", self); |
1a4d82fc | 4698 | |
c1a9b12d SL |
4699 | // To avoid a stack overflow when checking an enum variant or struct that |
4700 | // contains a different, structurally recursive type, maintain a stack | |
4701 | // of seen types and check recursion for each of them (issues #3008, #3779). | |
4702 | let mut seen: Vec<Ty> = Vec::new(); | |
4703 | let r = is_type_structurally_recursive(cx, sp, &mut seen, self); | |
4704 | debug!("is_type_representable: {:?} is {:?}", self, r); | |
4705 | r | |
1a4d82fc | 4706 | } |
1a4d82fc | 4707 | |
c1a9b12d SL |
4708 | pub fn is_trait(&self) -> bool { |
4709 | match self.sty { | |
4710 | TyTrait(..) => true, | |
4711 | _ => false | |
4712 | } | |
1a4d82fc | 4713 | } |
1a4d82fc | 4714 | |
c1a9b12d SL |
4715 | pub fn is_integral(&self) -> bool { |
4716 | match self.sty { | |
4717 | TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true, | |
4718 | _ => false | |
4719 | } | |
1a4d82fc | 4720 | } |
1a4d82fc | 4721 | |
c1a9b12d SL |
4722 | pub fn is_fresh(&self) -> bool { |
4723 | match self.sty { | |
4724 | TyInfer(FreshTy(_)) => true, | |
4725 | TyInfer(FreshIntTy(_)) => true, | |
4726 | TyInfer(FreshFloatTy(_)) => true, | |
4727 | _ => false | |
4728 | } | |
1a4d82fc | 4729 | } |
1a4d82fc | 4730 | |
c1a9b12d SL |
4731 | pub fn is_uint(&self) -> bool { |
4732 | match self.sty { | |
4733 | TyInfer(IntVar(_)) | TyUint(ast::TyUs) => true, | |
4734 | _ => false | |
4735 | } | |
1a4d82fc | 4736 | } |
1a4d82fc | 4737 | |
c1a9b12d SL |
4738 | pub fn is_char(&self) -> bool { |
4739 | match self.sty { | |
4740 | TyChar => true, | |
4741 | _ => false | |
4742 | } | |
1a4d82fc | 4743 | } |
1a4d82fc | 4744 | |
c1a9b12d SL |
4745 | pub fn is_bare_fn(&self) -> bool { |
4746 | match self.sty { | |
4747 | TyBareFn(..) => true, | |
4748 | _ => false | |
4749 | } | |
1a4d82fc | 4750 | } |
1a4d82fc | 4751 | |
c1a9b12d SL |
4752 | pub fn is_bare_fn_item(&self) -> bool { |
4753 | match self.sty { | |
4754 | TyBareFn(Some(_), _) => true, | |
4755 | _ => false | |
4756 | } | |
1a4d82fc | 4757 | } |
1a4d82fc | 4758 | |
c1a9b12d SL |
4759 | pub fn is_fp(&self) -> bool { |
4760 | match self.sty { | |
4761 | TyInfer(FloatVar(_)) | TyFloat(_) => true, | |
4762 | _ => false | |
4763 | } | |
1a4d82fc | 4764 | } |
1a4d82fc | 4765 | |
c1a9b12d SL |
4766 | pub fn is_numeric(&self) -> bool { |
4767 | self.is_integral() || self.is_fp() | |
1a4d82fc | 4768 | } |
1a4d82fc | 4769 | |
c1a9b12d SL |
4770 | pub fn is_signed(&self) -> bool { |
4771 | match self.sty { | |
4772 | TyInt(_) => true, | |
4773 | _ => false | |
1a4d82fc | 4774 | } |
1a4d82fc | 4775 | } |
1a4d82fc | 4776 | |
c1a9b12d SL |
4777 | pub fn is_machine(&self) -> bool { |
4778 | match self.sty { | |
4779 | TyInt(ast::TyIs) | TyUint(ast::TyUs) => false, | |
4780 | TyInt(..) | TyUint(..) | TyFloat(..) => true, | |
4781 | _ => false | |
1a4d82fc | 4782 | } |
1a4d82fc | 4783 | } |
1a4d82fc | 4784 | |
c1a9b12d SL |
4785 | // Whether a type is enum like, that is an enum type with only nullary |
4786 | // constructors | |
4787 | pub fn is_c_like_enum(&self, cx: &ctxt) -> bool { | |
4788 | match self.sty { | |
4789 | TyEnum(did, _) => { | |
4790 | let variants = cx.enum_variants(did); | |
4791 | if variants.is_empty() { | |
4792 | false | |
4793 | } else { | |
4794 | variants.iter().all(|v| v.args.is_empty()) | |
4795 | } | |
4796 | } | |
4797 | _ => false | |
1a4d82fc | 4798 | } |
1a4d82fc | 4799 | } |
1a4d82fc | 4800 | |
c1a9b12d SL |
4801 | // Returns the type and mutability of *ty. |
4802 | // | |
4803 | // The parameter `explicit` indicates if this is an *explicit* dereference. | |
4804 | // Some types---notably unsafe ptrs---can only be dereferenced explicitly. | |
4805 | pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> { | |
4806 | match self.sty { | |
4807 | TyBox(ty) => { | |
4808 | Some(TypeAndMut { | |
4809 | ty: ty, | |
4810 | mutbl: ast::MutImmutable, | |
4811 | }) | |
4812 | }, | |
4813 | TyRef(_, mt) => Some(mt), | |
4814 | TyRawPtr(mt) if explicit => Some(mt), | |
4815 | _ => None | |
1a4d82fc JJ |
4816 | } |
4817 | } | |
1a4d82fc | 4818 | |
c1a9b12d SL |
4819 | // Returns the type of ty[i] |
4820 | pub fn builtin_index(&self) -> Option<Ty<'tcx>> { | |
4821 | match self.sty { | |
4822 | TyArray(ty, _) | TySlice(ty) => Some(ty), | |
4823 | _ => None | |
1a4d82fc JJ |
4824 | } |
4825 | } | |
1a4d82fc | 4826 | |
c1a9b12d SL |
4827 | pub fn fn_sig(&self) -> &'tcx PolyFnSig<'tcx> { |
4828 | match self.sty { | |
4829 | TyBareFn(_, ref f) => &f.sig, | |
4830 | _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self) | |
4831 | } | |
1a4d82fc | 4832 | } |
1a4d82fc | 4833 | |
c1a9b12d SL |
4834 | /// Returns the ABI of the given function. |
4835 | pub fn fn_abi(&self) -> abi::Abi { | |
4836 | match self.sty { | |
4837 | TyBareFn(_, ref f) => f.abi, | |
4838 | _ => panic!("Ty::fn_abi() called on non-fn type"), | |
1a4d82fc JJ |
4839 | } |
4840 | } | |
1a4d82fc | 4841 | |
c1a9b12d SL |
4842 | // Type accessors for substructures of types |
4843 | pub fn fn_args(&self) -> ty::Binder<Vec<Ty<'tcx>>> { | |
4844 | self.fn_sig().inputs() | |
1a4d82fc | 4845 | } |
1a4d82fc | 4846 | |
c1a9b12d SL |
4847 | pub fn fn_ret(&self) -> Binder<FnOutput<'tcx>> { |
4848 | self.fn_sig().output() | |
1a4d82fc | 4849 | } |
1a4d82fc | 4850 | |
c1a9b12d SL |
4851 | pub fn is_fn(&self) -> bool { |
4852 | match self.sty { | |
4853 | TyBareFn(..) => true, | |
4854 | _ => false | |
1a4d82fc JJ |
4855 | } |
4856 | } | |
1a4d82fc | 4857 | |
c1a9b12d SL |
4858 | /// See `expr_ty_adjusted` |
4859 | pub fn adjust<F>(&'tcx self, cx: &ctxt<'tcx>, | |
4860 | span: Span, | |
4861 | expr_id: ast::NodeId, | |
4862 | adjustment: Option<&AutoAdjustment<'tcx>>, | |
4863 | mut method_type: F) | |
4864 | -> Ty<'tcx> where | |
4865 | F: FnMut(MethodCall) -> Option<Ty<'tcx>>, | |
4866 | { | |
4867 | if let TyError = self.sty { | |
4868 | return self; | |
1a4d82fc | 4869 | } |
1a4d82fc | 4870 | |
c1a9b12d SL |
4871 | return match adjustment { |
4872 | Some(adjustment) => { | |
4873 | match *adjustment { | |
4874 | AdjustReifyFnPointer => { | |
4875 | match self.sty { | |
4876 | ty::TyBareFn(Some(_), b) => { | |
4877 | cx.mk_fn(None, b) | |
4878 | } | |
4879 | _ => { | |
4880 | cx.sess.bug( | |
4881 | &format!("AdjustReifyFnPointer adjustment on non-fn-item: \ | |
4882 | {:?}", self)); | |
4883 | } | |
1a4d82fc JJ |
4884 | } |
4885 | } | |
1a4d82fc | 4886 | |
c1a9b12d SL |
4887 | AdjustUnsafeFnPointer => { |
4888 | match self.sty { | |
4889 | ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b), | |
4890 | ref b => { | |
4891 | cx.sess.bug( | |
4892 | &format!("AdjustReifyFnPointer adjustment on non-fn-item: \ | |
4893 | {:?}", | |
4894 | b)); | |
4895 | } | |
c34b1796 | 4896 | } |
c1a9b12d SL |
4897 | } |
4898 | ||
4899 | AdjustDerefRef(ref adj) => { | |
4900 | let mut adjusted_ty = self; | |
4901 | ||
4902 | if !adjusted_ty.references_error() { | |
4903 | for i in 0..adj.autoderefs { | |
4904 | let method_call = MethodCall::autoderef(expr_id, i as u32); | |
4905 | match method_type(method_call) { | |
4906 | Some(method_ty) => { | |
4907 | // Overloaded deref operators have all late-bound | |
4908 | // regions fully instantiated and coverge. | |
4909 | let fn_ret = | |
4910 | cx.no_late_bound_regions(&method_ty.fn_ret()).unwrap(); | |
4911 | adjusted_ty = fn_ret.unwrap(); | |
4912 | } | |
4913 | None => {} | |
1a4d82fc | 4914 | } |
c1a9b12d SL |
4915 | match adjusted_ty.builtin_deref(true) { |
4916 | Some(mt) => { adjusted_ty = mt.ty; } | |
4917 | None => { | |
4918 | cx.sess.span_bug( | |
4919 | span, | |
4920 | &format!("the {}th autoderef failed: {}", | |
4921 | i, | |
4922 | adjusted_ty) | |
4923 | ); | |
4924 | } | |
1a4d82fc JJ |
4925 | } |
4926 | } | |
4927 | } | |
1a4d82fc | 4928 | |
c1a9b12d SL |
4929 | if let Some(target) = adj.unsize { |
4930 | target | |
4931 | } else { | |
4932 | adjusted_ty.adjust_for_autoref(cx, adj.autoref) | |
4933 | } | |
9346a6ac | 4934 | } |
1a4d82fc JJ |
4935 | } |
4936 | } | |
c1a9b12d SL |
4937 | None => self |
4938 | }; | |
1a4d82fc | 4939 | } |
1a4d82fc | 4940 | |
c1a9b12d SL |
4941 | pub fn adjust_for_autoref(&'tcx self, cx: &ctxt<'tcx>, |
4942 | autoref: Option<AutoRef<'tcx>>) | |
4943 | -> Ty<'tcx> { | |
4944 | match autoref { | |
4945 | None => self, | |
4946 | Some(AutoPtr(r, m)) => { | |
4947 | cx.mk_ref(r, TypeAndMut { ty: self, mutbl: m }) | |
4948 | } | |
4949 | Some(AutoUnsafe(m)) => { | |
4950 | cx.mk_ptr(TypeAndMut { ty: self, mutbl: m }) | |
4951 | } | |
1a4d82fc JJ |
4952 | } |
4953 | } | |
1a4d82fc | 4954 | |
c1a9b12d | 4955 | fn sort_string(&self, cx: &ctxt) -> String { |
1a4d82fc | 4956 | |
c1a9b12d SL |
4957 | match self.sty { |
4958 | TyBool | TyChar | TyInt(_) | | |
4959 | TyUint(_) | TyFloat(_) | TyStr => self.to_string(), | |
4960 | TyTuple(ref tys) if tys.is_empty() => self.to_string(), | |
4961 | ||
4962 | TyEnum(id, _) => format!("enum `{}`", cx.item_path_str(id)), | |
4963 | TyBox(_) => "box".to_string(), | |
4964 | TyArray(_, n) => format!("array of {} elements", n), | |
4965 | TySlice(_) => "slice".to_string(), | |
4966 | TyRawPtr(_) => "*-ptr".to_string(), | |
4967 | TyRef(_, _) => "&-ptr".to_string(), | |
4968 | TyBareFn(Some(_), _) => format!("fn item"), | |
4969 | TyBareFn(None, _) => "fn pointer".to_string(), | |
4970 | TyTrait(ref inner) => { | |
4971 | format!("trait {}", cx.item_path_str(inner.principal_def_id())) | |
4972 | } | |
4973 | TyStruct(id, _) => { | |
4974 | format!("struct `{}`", cx.item_path_str(id)) | |
4975 | } | |
4976 | TyClosure(..) => "closure".to_string(), | |
4977 | TyTuple(_) => "tuple".to_string(), | |
4978 | TyInfer(TyVar(_)) => "inferred type".to_string(), | |
4979 | TyInfer(IntVar(_)) => "integral variable".to_string(), | |
4980 | TyInfer(FloatVar(_)) => "floating-point variable".to_string(), | |
4981 | TyInfer(FreshTy(_)) => "skolemized type".to_string(), | |
4982 | TyInfer(FreshIntTy(_)) => "skolemized integral type".to_string(), | |
4983 | TyInfer(FreshFloatTy(_)) => "skolemized floating-point type".to_string(), | |
4984 | TyProjection(_) => "associated type".to_string(), | |
4985 | TyParam(ref p) => { | |
4986 | if p.space == subst::SelfSpace { | |
4987 | "Self".to_string() | |
4988 | } else { | |
4989 | "type parameter".to_string() | |
4990 | } | |
1a4d82fc | 4991 | } |
c1a9b12d | 4992 | TyError => "type error".to_string(), |
1a4d82fc | 4993 | } |
1a4d82fc JJ |
4994 | } |
4995 | } | |
1a4d82fc JJ |
4996 | /// Explains the source of a type err in a short, human readable way. This is meant to be placed |
4997 | /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()` | |
4998 | /// afterwards to present additional details, particularly when it comes to lifetime-related | |
4999 | /// errors. | |
c1a9b12d | 5000 | impl<'tcx> fmt::Display for TypeError<'tcx> { |
62682a34 | 5001 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
c1a9b12d SL |
5002 | use self::TypeError::*; |
5003 | ||
62682a34 | 5004 | match *self { |
c1a9b12d SL |
5005 | CyclicTy => write!(f, "cyclic type of infinite size"), |
5006 | Mismatch => write!(f, "types differ"), | |
5007 | UnsafetyMismatch(values) => { | |
62682a34 SL |
5008 | write!(f, "expected {} fn, found {} fn", |
5009 | values.expected, | |
5010 | values.found) | |
5011 | } | |
c1a9b12d | 5012 | AbiMismatch(values) => { |
62682a34 SL |
5013 | write!(f, "expected {} fn, found {} fn", |
5014 | values.expected, | |
5015 | values.found) | |
5016 | } | |
c1a9b12d SL |
5017 | Mutability => write!(f, "values differ in mutability"), |
5018 | BoxMutability => { | |
62682a34 SL |
5019 | write!(f, "boxed values differ in mutability") |
5020 | } | |
c1a9b12d SL |
5021 | VecMutability => write!(f, "vectors differ in mutability"), |
5022 | PtrMutability => write!(f, "pointers differ in mutability"), | |
5023 | RefMutability => write!(f, "references differ in mutability"), | |
5024 | TyParamSize(values) => { | |
62682a34 SL |
5025 | write!(f, "expected a type with {} type params, \ |
5026 | found one with {} type params", | |
5027 | values.expected, | |
5028 | values.found) | |
5029 | } | |
c1a9b12d | 5030 | FixedArraySize(values) => { |
62682a34 SL |
5031 | write!(f, "expected an array with a fixed size of {} elements, \ |
5032 | found one with {} elements", | |
5033 | values.expected, | |
5034 | values.found) | |
5035 | } | |
c1a9b12d | 5036 | TupleSize(values) => { |
62682a34 SL |
5037 | write!(f, "expected a tuple with {} elements, \ |
5038 | found one with {} elements", | |
5039 | values.expected, | |
5040 | values.found) | |
5041 | } | |
c1a9b12d | 5042 | ArgCount => { |
62682a34 SL |
5043 | write!(f, "incorrect number of function parameters") |
5044 | } | |
c1a9b12d | 5045 | RegionsDoesNotOutlive(..) => { |
62682a34 SL |
5046 | write!(f, "lifetime mismatch") |
5047 | } | |
c1a9b12d | 5048 | RegionsNotSame(..) => { |
62682a34 SL |
5049 | write!(f, "lifetimes are not the same") |
5050 | } | |
c1a9b12d | 5051 | RegionsNoOverlap(..) => { |
62682a34 SL |
5052 | write!(f, "lifetimes do not intersect") |
5053 | } | |
c1a9b12d | 5054 | RegionsInsufficientlyPolymorphic(br, _) => { |
62682a34 SL |
5055 | write!(f, "expected bound lifetime parameter {}, \ |
5056 | found concrete lifetime", br) | |
5057 | } | |
c1a9b12d | 5058 | RegionsOverlyPolymorphic(br, _) => { |
62682a34 SL |
5059 | write!(f, "expected concrete lifetime, \ |
5060 | found bound lifetime parameter {}", br) | |
5061 | } | |
c1a9b12d | 5062 | Sorts(values) => tls::with(|tcx| { |
62682a34 SL |
5063 | // A naive approach to making sure that we're not reporting silly errors such as: |
5064 | // (expected closure, found closure). | |
c1a9b12d SL |
5065 | let expected_str = values.expected.sort_string(tcx); |
5066 | let found_str = values.found.sort_string(tcx); | |
62682a34 SL |
5067 | if expected_str == found_str { |
5068 | write!(f, "expected {}, found a different {}", expected_str, found_str) | |
5069 | } else { | |
5070 | write!(f, "expected {}, found {}", expected_str, found_str) | |
5071 | } | |
5072 | }), | |
c1a9b12d | 5073 | Traits(values) => tls::with(|tcx| { |
62682a34 | 5074 | write!(f, "expected trait `{}`, found trait `{}`", |
c1a9b12d SL |
5075 | tcx.item_path_str(values.expected), |
5076 | tcx.item_path_str(values.found)) | |
62682a34 | 5077 | }), |
c1a9b12d | 5078 | BuiltinBoundsMismatch(values) => { |
62682a34 SL |
5079 | if values.expected.is_empty() { |
5080 | write!(f, "expected no bounds, found `{}`", | |
5081 | values.found) | |
5082 | } else if values.found.is_empty() { | |
5083 | write!(f, "expected bounds `{}`, found no bounds", | |
5084 | values.expected) | |
5085 | } else { | |
5086 | write!(f, "expected bounds `{}`, found bounds `{}`", | |
5087 | values.expected, | |
5088 | values.found) | |
5089 | } | |
1a4d82fc | 5090 | } |
c1a9b12d | 5091 | IntegerAsChar => { |
62682a34 SL |
5092 | write!(f, "expected an integral type, found `char`") |
5093 | } | |
c1a9b12d | 5094 | IntMismatch(ref values) => { |
62682a34 SL |
5095 | write!(f, "expected `{:?}`, found `{:?}`", |
5096 | values.expected, | |
5097 | values.found) | |
5098 | } | |
c1a9b12d | 5099 | FloatMismatch(ref values) => { |
62682a34 SL |
5100 | write!(f, "expected `{:?}`, found `{:?}`", |
5101 | values.expected, | |
5102 | values.found) | |
5103 | } | |
c1a9b12d | 5104 | VariadicMismatch(ref values) => { |
62682a34 SL |
5105 | write!(f, "expected {} fn, found {} function", |
5106 | if values.expected { "variadic" } else { "non-variadic" }, | |
5107 | if values.found { "variadic" } else { "non-variadic" }) | |
5108 | } | |
c1a9b12d | 5109 | ConvergenceMismatch(ref values) => { |
62682a34 SL |
5110 | write!(f, "expected {} fn, found {} function", |
5111 | if values.expected { "converging" } else { "diverging" }, | |
5112 | if values.found { "converging" } else { "diverging" }) | |
5113 | } | |
c1a9b12d | 5114 | ProjectionNameMismatched(ref values) => { |
62682a34 SL |
5115 | write!(f, "expected {}, found {}", |
5116 | values.expected, | |
5117 | values.found) | |
5118 | } | |
c1a9b12d | 5119 | ProjectionBoundsLength(ref values) => { |
62682a34 SL |
5120 | write!(f, "expected {} associated type bindings, found {}", |
5121 | values.expected, | |
5122 | values.found) | |
c1a9b12d SL |
5123 | }, |
5124 | TyParamDefaultMismatch(ref values) => { | |
5125 | write!(f, "conflicting type parameter defaults `{}` and `{}`", | |
5126 | values.expected.ty, | |
5127 | values.found.ty) | |
1a4d82fc | 5128 | } |
1a4d82fc JJ |
5129 | } |
5130 | } | |
5131 | } | |
5132 | ||
1a4d82fc JJ |
5133 | /// Helper for looking things up in the various maps that are populated during |
5134 | /// typeck::collect (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of | |
5135 | /// these share the pattern that if the id is local, it should have been loaded | |
5136 | /// into the map by the `typeck::collect` phase. If the def-id is external, | |
5137 | /// then we have to go consult the crate loading code (and cache the result for | |
5138 | /// the future). | |
5139 | fn lookup_locally_or_in_crate_store<V, F>(descr: &str, | |
5140 | def_id: ast::DefId, | |
62682a34 | 5141 | map: &RefCell<DefIdMap<V>>, |
1a4d82fc JJ |
5142 | load_external: F) -> V where |
5143 | V: Clone, | |
5144 | F: FnOnce() -> V, | |
5145 | { | |
62682a34 | 5146 | match map.borrow().get(&def_id).cloned() { |
1a4d82fc JJ |
5147 | Some(v) => { return v; } |
5148 | None => { } | |
5149 | } | |
5150 | ||
5151 | if def_id.krate == ast::LOCAL_CRATE { | |
5152 | panic!("No def'n found for {:?} in tcx.{}", def_id, descr); | |
5153 | } | |
5154 | let v = load_external(); | |
62682a34 | 5155 | map.borrow_mut().insert(def_id, v.clone()); |
1a4d82fc JJ |
5156 | v |
5157 | } | |
5158 | ||
c1a9b12d SL |
5159 | impl BorrowKind { |
5160 | pub fn from_mutbl(m: ast::Mutability) -> BorrowKind { | |
5161 | match m { | |
5162 | ast::MutMutable => MutBorrow, | |
5163 | ast::MutImmutable => ImmBorrow, | |
5164 | } | |
5165 | } | |
d9579d0f | 5166 | |
c1a9b12d SL |
5167 | /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow |
5168 | /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a | |
5169 | /// mutability that is stronger than necessary so that it at least *would permit* the borrow in | |
5170 | /// question. | |
5171 | pub fn to_mutbl_lossy(self) -> ast::Mutability { | |
5172 | match self { | |
5173 | MutBorrow => ast::MutMutable, | |
5174 | ImmBorrow => ast::MutImmutable, | |
5175 | ||
5176 | // We have no type corresponding to a unique imm borrow, so | |
5177 | // use `&mut`. It gives all the capabilities of an `&uniq` | |
5178 | // and hence is a safe "over approximation". | |
5179 | UniqueImmBorrow => ast::MutMutable, | |
d9579d0f | 5180 | } |
c1a9b12d | 5181 | } |
d9579d0f | 5182 | |
c1a9b12d SL |
5183 | pub fn to_user_str(&self) -> &'static str { |
5184 | match *self { | |
5185 | MutBorrow => "mutable", | |
5186 | ImmBorrow => "immutable", | |
5187 | UniqueImmBorrow => "uniquely immutable", | |
5188 | } | |
5189 | } | |
1a4d82fc JJ |
5190 | } |
5191 | ||
c1a9b12d SL |
5192 | impl<'tcx> ctxt<'tcx> { |
5193 | /// Returns the type of element at index `i` in tuple or tuple-like type `t`. | |
5194 | /// For an enum `t`, `variant` is None only if `t` is a univariant enum. | |
5195 | pub fn positional_element_ty(&self, | |
5196 | ty: Ty<'tcx>, | |
5197 | i: usize, | |
5198 | variant: Option<ast::DefId>) -> Option<Ty<'tcx>> { | |
5199 | ||
5200 | match (&ty.sty, variant) { | |
5201 | (&TyTuple(ref v), None) => v.get(i).cloned(), | |
5202 | ||
5203 | ||
5204 | (&TyStruct(def_id, substs), None) => self.lookup_struct_fields(def_id) | |
5205 | .get(i) | |
5206 | .map(|&t| self.lookup_item_type(t.id).ty.subst(self, substs)), | |
5207 | ||
5208 | (&TyEnum(def_id, substs), Some(variant_def_id)) => { | |
5209 | let variant_info = self.enum_variant_with_id(def_id, variant_def_id); | |
5210 | variant_info.args.get(i).map(|t|t.subst(self, substs)) | |
5211 | } | |
5212 | ||
5213 | (&TyEnum(def_id, substs), None) => { | |
5214 | assert!(self.enum_is_univariant(def_id)); | |
5215 | let enum_variants = self.enum_variants(def_id); | |
5216 | let variant_info = &enum_variants[0]; | |
5217 | variant_info.args.get(i).map(|t|t.subst(self, substs)) | |
5218 | } | |
5219 | ||
5220 | _ => None | |
1a4d82fc JJ |
5221 | } |
5222 | } | |
1a4d82fc | 5223 | |
c1a9b12d SL |
5224 | /// Returns the type of element at field `n` in struct or struct-like type `t`. |
5225 | /// For an enum `t`, `variant` must be some def id. | |
5226 | pub fn named_element_ty(&self, | |
5227 | ty: Ty<'tcx>, | |
5228 | n: ast::Name, | |
5229 | variant: Option<ast::DefId>) -> Option<Ty<'tcx>> { | |
1a4d82fc | 5230 | |
c1a9b12d SL |
5231 | match (&ty.sty, variant) { |
5232 | (&TyStruct(def_id, substs), None) => { | |
5233 | let r = self.lookup_struct_fields(def_id); | |
5234 | r.iter().find(|f| f.name == n) | |
5235 | .map(|&f| self.lookup_field_type(def_id, f.id, substs)) | |
5236 | } | |
5237 | (&TyEnum(def_id, substs), Some(variant_def_id)) => { | |
5238 | let variant_info = self.enum_variant_with_id(def_id, variant_def_id); | |
5239 | variant_info.arg_names.as_ref() | |
5240 | .expect("must have struct enum variant if accessing a named fields") | |
5241 | .iter().zip(&variant_info.args) | |
5242 | .find(|&(&name, _)| name == n) | |
5243 | .map(|(_name, arg_t)| arg_t.subst(self, substs)) | |
5244 | } | |
5245 | _ => None | |
5246 | } | |
5247 | } | |
62682a34 | 5248 | |
c1a9b12d SL |
5249 | pub fn node_id_to_type(&self, id: ast::NodeId) -> Ty<'tcx> { |
5250 | match self.node_id_to_type_opt(id) { | |
5251 | Some(ty) => ty, | |
5252 | None => self.sess.bug( | |
5253 | &format!("node_id_to_type: no type for node `{}`", | |
5254 | self.map.node_to_string(id))) | |
1a4d82fc | 5255 | } |
62682a34 | 5256 | } |
1a4d82fc | 5257 | |
c1a9b12d SL |
5258 | pub fn node_id_to_type_opt(&self, id: ast::NodeId) -> Option<Ty<'tcx>> { |
5259 | self.tables.borrow().node_types.get(&id).cloned() | |
5260 | } | |
1a4d82fc | 5261 | |
c1a9b12d SL |
5262 | pub fn node_id_item_substs(&self, id: ast::NodeId) -> ItemSubsts<'tcx> { |
5263 | match self.tables.borrow().item_substs.get(&id) { | |
5264 | None => ItemSubsts::empty(), | |
5265 | Some(ts) => ts.clone(), | |
5266 | } | |
1a4d82fc | 5267 | } |
1a4d82fc | 5268 | |
c1a9b12d SL |
5269 | // Returns the type of a pattern as a monotype. Like @expr_ty, this function |
5270 | // doesn't provide type parameter substitutions. | |
5271 | pub fn pat_ty(&self, pat: &ast::Pat) -> Ty<'tcx> { | |
5272 | self.node_id_to_type(pat.id) | |
5273 | } | |
5274 | pub fn pat_ty_opt(&self, pat: &ast::Pat) -> Option<Ty<'tcx>> { | |
5275 | self.node_id_to_type_opt(pat.id) | |
5276 | } | |
1a4d82fc | 5277 | |
c1a9b12d SL |
5278 | // Returns the type of an expression as a monotype. |
5279 | // | |
5280 | // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in | |
5281 | // some cases, we insert `AutoAdjustment` annotations such as auto-deref or | |
5282 | // auto-ref. The type returned by this function does not consider such | |
5283 | // adjustments. See `expr_ty_adjusted()` instead. | |
5284 | // | |
5285 | // NB (2): This type doesn't provide type parameter substitutions; e.g. if you | |
5286 | // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" | |
5287 | // instead of "fn(ty) -> T with T = isize". | |
5288 | pub fn expr_ty(&self, expr: &ast::Expr) -> Ty<'tcx> { | |
5289 | self.node_id_to_type(expr.id) | |
5290 | } | |
1a4d82fc | 5291 | |
c1a9b12d SL |
5292 | pub fn expr_ty_opt(&self, expr: &ast::Expr) -> Option<Ty<'tcx>> { |
5293 | self.node_id_to_type_opt(expr.id) | |
5294 | } | |
5295 | ||
5296 | /// Returns the type of `expr`, considering any `AutoAdjustment` | |
5297 | /// entry recorded for that expression. | |
1a4d82fc | 5298 | /// |
c1a9b12d SL |
5299 | /// It would almost certainly be better to store the adjusted ty in with |
5300 | /// the `AutoAdjustment`, but I opted not to do this because it would | |
5301 | /// require serializing and deserializing the type and, although that's not | |
5302 | /// hard to do, I just hate that code so much I didn't want to touch it | |
5303 | /// unless it was to fix it properly, which seemed a distraction from the | |
5304 | /// thread at hand! -nmatsakis | |
5305 | pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> { | |
5306 | self.expr_ty(expr) | |
5307 | .adjust(self, expr.span, expr.id, | |
5308 | self.tables.borrow().adjustments.get(&expr.id), | |
5309 | |method_call| { | |
5310 | self.tables.borrow().method_map.get(&method_call).map(|method| method.ty) | |
5311 | }) | |
5312 | } | |
1a4d82fc | 5313 | |
c1a9b12d SL |
5314 | pub fn expr_span(&self, id: NodeId) -> Span { |
5315 | match self.map.find(id) { | |
5316 | Some(ast_map::NodeExpr(e)) => { | |
5317 | e.span | |
5318 | } | |
5319 | Some(f) => { | |
5320 | self.sess.bug(&format!("Node id {} is not an expr: {:?}", | |
5321 | id, f)); | |
5322 | } | |
5323 | None => { | |
5324 | self.sess.bug(&format!("Node id {} is not present \ | |
5325 | in the node map", id)); | |
1a4d82fc JJ |
5326 | } |
5327 | } | |
5328 | } | |
1a4d82fc | 5329 | |
c1a9b12d SL |
5330 | pub fn local_var_name_str(&self, id: NodeId) -> InternedString { |
5331 | match self.map.find(id) { | |
5332 | Some(ast_map::NodeLocal(pat)) => { | |
5333 | match pat.node { | |
5334 | ast::PatIdent(_, ref path1, _) => path1.node.name.as_str(), | |
5335 | _ => { | |
5336 | self.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, pat)); | |
5337 | }, | |
5338 | } | |
5339 | }, | |
5340 | r => self.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, r)), | |
1a4d82fc | 5341 | } |
1a4d82fc | 5342 | } |
1a4d82fc | 5343 | |
c1a9b12d SL |
5344 | pub fn resolve_expr(&self, expr: &ast::Expr) -> def::Def { |
5345 | match self.def_map.borrow().get(&expr.id) { | |
5346 | Some(def) => def.full_def(), | |
5347 | None => { | |
5348 | self.sess.span_bug(expr.span, &format!( | |
5349 | "no def-map entry for expr {}", expr.id)); | |
5350 | } | |
5351 | } | |
5352 | } | |
5353 | ||
5354 | pub fn expr_is_lval(&self, expr: &ast::Expr) -> bool { | |
5355 | match expr.node { | |
5356 | ast::ExprPath(..) => { | |
5357 | // We can't use resolve_expr here, as this needs to run on broken | |
5358 | // programs. We don't need to through - associated items are all | |
5359 | // rvalues. | |
5360 | match self.def_map.borrow().get(&expr.id) { | |
5361 | Some(&def::PathResolution { | |
5362 | base_def: def::DefStatic(..), .. | |
5363 | }) | Some(&def::PathResolution { | |
5364 | base_def: def::DefUpvar(..), .. | |
5365 | }) | Some(&def::PathResolution { | |
5366 | base_def: def::DefLocal(..), .. | |
5367 | }) => { | |
5368 | true | |
5369 | } | |
1a4d82fc | 5370 | |
c1a9b12d | 5371 | Some(..) => false, |
1a4d82fc | 5372 | |
c1a9b12d SL |
5373 | None => self.sess.span_bug(expr.span, &format!( |
5374 | "no def for path {}", expr.id)) | |
5375 | } | |
5376 | } | |
1a4d82fc | 5377 | |
c1a9b12d SL |
5378 | ast::ExprUnary(ast::UnDeref, _) | |
5379 | ast::ExprField(..) | | |
5380 | ast::ExprTupField(..) | | |
5381 | ast::ExprIndex(..) => { | |
5382 | true | |
5383 | } | |
5384 | ||
5385 | ast::ExprCall(..) | | |
5386 | ast::ExprMethodCall(..) | | |
5387 | ast::ExprStruct(..) | | |
5388 | ast::ExprRange(..) | | |
5389 | ast::ExprTup(..) | | |
5390 | ast::ExprIf(..) | | |
5391 | ast::ExprMatch(..) | | |
5392 | ast::ExprClosure(..) | | |
5393 | ast::ExprBlock(..) | | |
5394 | ast::ExprRepeat(..) | | |
5395 | ast::ExprVec(..) | | |
5396 | ast::ExprBreak(..) | | |
5397 | ast::ExprAgain(..) | | |
5398 | ast::ExprRet(..) | | |
5399 | ast::ExprWhile(..) | | |
5400 | ast::ExprLoop(..) | | |
5401 | ast::ExprAssign(..) | | |
5402 | ast::ExprInlineAsm(..) | | |
5403 | ast::ExprAssignOp(..) | | |
5404 | ast::ExprLit(_) | | |
5405 | ast::ExprUnary(..) | | |
5406 | ast::ExprBox(..) | | |
5407 | ast::ExprAddrOf(..) | | |
5408 | ast::ExprBinary(..) | | |
5409 | ast::ExprCast(..) => { | |
5410 | false | |
5411 | } | |
1a4d82fc | 5412 | |
c1a9b12d | 5413 | ast::ExprParen(ref e) => self.expr_is_lval(e), |
c34b1796 | 5414 | |
c1a9b12d SL |
5415 | ast::ExprIfLet(..) | |
5416 | ast::ExprWhileLet(..) | | |
5417 | ast::ExprForLoop(..) | | |
5418 | ast::ExprMac(..) => { | |
5419 | self.sess.span_bug( | |
5420 | expr.span, | |
5421 | "macro expression remains after expansion"); | |
5422 | } | |
c34b1796 AL |
5423 | } |
5424 | } | |
5425 | ||
c1a9b12d SL |
5426 | pub fn field_idx_strict(&self, name: ast::Name, fields: &[Field<'tcx>]) |
5427 | -> usize { | |
5428 | let mut i = 0; | |
5429 | for f in fields { if f.name == name { return i; } i += 1; } | |
5430 | self.sess.bug(&format!( | |
5431 | "no field named `{}` found in the list of fields `{:?}`", | |
5432 | name, | |
5433 | fields.iter() | |
5434 | .map(|f| f.name.to_string()) | |
5435 | .collect::<Vec<String>>())); | |
c34b1796 AL |
5436 | } |
5437 | ||
c1a9b12d SL |
5438 | pub fn note_and_explain_type_err(&self, err: &TypeError<'tcx>, sp: Span) { |
5439 | use self::TypeError::*; | |
c34b1796 | 5440 | |
c1a9b12d SL |
5441 | match err.clone() { |
5442 | RegionsDoesNotOutlive(subregion, superregion) => { | |
5443 | self.note_and_explain_region("", subregion, "..."); | |
5444 | self.note_and_explain_region("...does not necessarily outlive ", | |
5445 | superregion, ""); | |
5446 | } | |
5447 | RegionsNotSame(region1, region2) => { | |
5448 | self.note_and_explain_region("", region1, "..."); | |
5449 | self.note_and_explain_region("...is not the same lifetime as ", | |
5450 | region2, ""); | |
5451 | } | |
5452 | RegionsNoOverlap(region1, region2) => { | |
5453 | self.note_and_explain_region("", region1, "..."); | |
5454 | self.note_and_explain_region("...does not overlap ", | |
5455 | region2, ""); | |
5456 | } | |
5457 | RegionsInsufficientlyPolymorphic(_, conc_region) => { | |
5458 | self.note_and_explain_region("concrete lifetime that was found is ", | |
5459 | conc_region, ""); | |
5460 | } | |
5461 | RegionsOverlyPolymorphic(_, ty::ReInfer(ty::ReVar(_))) => { | |
5462 | // don't bother to print out the message below for | |
5463 | // inference variables, it's not very illuminating. | |
5464 | } | |
5465 | RegionsOverlyPolymorphic(_, conc_region) => { | |
5466 | self.note_and_explain_region("expected concrete lifetime is ", | |
5467 | conc_region, ""); | |
5468 | } | |
5469 | Sorts(values) => { | |
5470 | let expected_str = values.expected.sort_string(self); | |
5471 | let found_str = values.found.sort_string(self); | |
5472 | if expected_str == found_str && expected_str == "closure" { | |
5473 | self.sess.span_note(sp, | |
5474 | &format!("no two closures, even if identical, have the same type")); | |
5475 | self.sess.span_help(sp, | |
5476 | &format!("consider boxing your closure and/or \ | |
5477 | using it as a trait object")); | |
5478 | } | |
5479 | }, | |
5480 | TyParamDefaultMismatch(values) => { | |
5481 | let expected = values.expected; | |
5482 | let found = values.found; | |
5483 | self.sess.span_note(sp, | |
5484 | &format!("conflicting type parameter defaults `{}` and `{}`", | |
5485 | expected.ty, | |
5486 | found.ty)); | |
5487 | ||
5488 | match (expected.def_id.krate == ast::LOCAL_CRATE, | |
5489 | self.map.opt_span(expected.def_id.node)) { | |
5490 | (true, Some(span)) => { | |
5491 | self.sess.span_note(span, | |
5492 | &format!("a default was defined here...")); | |
5493 | } | |
5494 | (_, _) => { | |
5495 | let elems = csearch::get_item_path(self, expected.def_id) | |
5496 | .into_iter() | |
5497 | .map(|p| p.to_string()) | |
5498 | .collect::<Vec<_>>(); | |
5499 | self.sess.note( | |
5500 | &format!("a default is defined on `{}`", | |
5501 | elems.join("::"))); | |
5502 | } | |
5503 | } | |
c34b1796 | 5504 | |
c1a9b12d SL |
5505 | self.sess.span_note( |
5506 | expected.origin_span, | |
5507 | &format!("...that was applied to an unconstrained type variable here")); | |
c34b1796 | 5508 | |
c1a9b12d SL |
5509 | match (found.def_id.krate == ast::LOCAL_CRATE, |
5510 | self.map.opt_span(found.def_id.node)) { | |
5511 | (true, Some(span)) => { | |
5512 | self.sess.span_note(span, | |
5513 | &format!("a second default was defined here...")); | |
5514 | } | |
5515 | (_, _) => { | |
5516 | let elems = csearch::get_item_path(self, found.def_id) | |
5517 | .into_iter() | |
5518 | .map(|p| p.to_string()) | |
5519 | .collect::<Vec<_>>(); | |
5520 | ||
5521 | self.sess.note( | |
5522 | &format!("a second default is defined on `{}`", elems.join(" "))); | |
5523 | } | |
5524 | } | |
c34b1796 | 5525 | |
c1a9b12d SL |
5526 | self.sess.span_note( |
5527 | found.origin_span, | |
5528 | &format!("...that also applies to the same type variable here")); | |
5529 | } | |
5530 | _ => {} | |
c34b1796 AL |
5531 | } |
5532 | } | |
5533 | ||
c1a9b12d SL |
5534 | pub fn provided_source(&self, id: ast::DefId) -> Option<ast::DefId> { |
5535 | self.provided_method_sources.borrow().get(&id).cloned() | |
c34b1796 | 5536 | } |
c34b1796 | 5537 | |
c1a9b12d SL |
5538 | pub fn provided_trait_methods(&self, id: ast::DefId) -> Vec<Rc<Method<'tcx>>> { |
5539 | if is_local(id) { | |
5540 | if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id.node).node { | |
5541 | ms.iter().filter_map(|ti| { | |
5542 | if let ast::MethodTraitItem(_, Some(_)) = ti.node { | |
5543 | match self.impl_or_trait_item(ast_util::local_def(ti.id)) { | |
5544 | MethodTraitItem(m) => Some(m), | |
5545 | _ => { | |
5546 | self.sess.bug("provided_trait_methods(): \ | |
5547 | non-method item found from \ | |
5548 | looking up provided method?!") | |
5549 | } | |
5550 | } | |
5551 | } else { | |
5552 | None | |
c34b1796 | 5553 | } |
c1a9b12d SL |
5554 | }).collect() |
5555 | } else { | |
5556 | self.sess.bug(&format!("provided_trait_methods: `{:?}` is not a trait", id)) | |
5557 | } | |
5558 | } else { | |
5559 | csearch::get_provided_trait_methods(self, id) | |
5560 | } | |
5561 | } | |
5562 | ||
5563 | pub fn associated_consts(&self, id: ast::DefId) -> Vec<Rc<AssociatedConst<'tcx>>> { | |
5564 | if is_local(id) { | |
5565 | match self.map.expect_item(id.node).node { | |
5566 | ItemTrait(_, _, _, ref tis) => { | |
5567 | tis.iter().filter_map(|ti| { | |
5568 | if let ast::ConstTraitItem(_, _) = ti.node { | |
5569 | match self.impl_or_trait_item(ast_util::local_def(ti.id)) { | |
5570 | ConstTraitItem(ac) => Some(ac), | |
5571 | _ => { | |
5572 | self.sess.bug("associated_consts(): \ | |
5573 | non-const item found from \ | |
5574 | looking up a constant?!") | |
5575 | } | |
5576 | } | |
5577 | } else { | |
5578 | None | |
5579 | } | |
5580 | }).collect() | |
c34b1796 | 5581 | } |
c1a9b12d SL |
5582 | ItemImpl(_, _, _, _, _, ref iis) => { |
5583 | iis.iter().filter_map(|ii| { | |
5584 | if let ast::ConstImplItem(_, _) = ii.node { | |
5585 | match self.impl_or_trait_item(ast_util::local_def(ii.id)) { | |
5586 | ConstTraitItem(ac) => Some(ac), | |
5587 | _ => { | |
5588 | self.sess.bug("associated_consts(): \ | |
5589 | non-const item found from \ | |
5590 | looking up a constant?!") | |
5591 | } | |
5592 | } | |
c34b1796 | 5593 | } else { |
c1a9b12d | 5594 | None |
c34b1796 | 5595 | } |
c1a9b12d SL |
5596 | }).collect() |
5597 | } | |
5598 | _ => { | |
5599 | self.sess.bug(&format!("associated_consts: `{:?}` is not a trait \ | |
5600 | or impl", id)) | |
c34b1796 AL |
5601 | } |
5602 | } | |
c1a9b12d SL |
5603 | } else { |
5604 | csearch::get_associated_consts(self, id) | |
c34b1796 | 5605 | } |
c34b1796 AL |
5606 | } |
5607 | ||
c1a9b12d SL |
5608 | pub fn trait_items(&self, trait_did: ast::DefId) -> Rc<Vec<ImplOrTraitItem<'tcx>>> { |
5609 | let mut trait_items = self.trait_items_cache.borrow_mut(); | |
5610 | match trait_items.get(&trait_did).cloned() { | |
5611 | Some(trait_items) => trait_items, | |
5612 | None => { | |
5613 | let def_ids = self.trait_item_def_ids(trait_did); | |
5614 | let items: Rc<Vec<ImplOrTraitItem>> = | |
5615 | Rc::new(def_ids.iter() | |
5616 | .map(|d| self.impl_or_trait_item(d.def_id())) | |
5617 | .collect()); | |
5618 | trait_items.insert(trait_did, items.clone()); | |
5619 | items | |
5620 | } | |
5621 | } | |
5622 | } | |
c34b1796 | 5623 | |
c1a9b12d SL |
5624 | pub fn trait_impl_polarity(&self, id: ast::DefId) -> Option<ast::ImplPolarity> { |
5625 | if id.krate == ast::LOCAL_CRATE { | |
5626 | match self.map.find(id.node) { | |
5627 | Some(ast_map::NodeItem(item)) => { | |
1a4d82fc | 5628 | match item.node { |
c1a9b12d SL |
5629 | ast::ItemImpl(_, polarity, _, _, _, _) => Some(polarity), |
5630 | _ => None | |
1a4d82fc JJ |
5631 | } |
5632 | } | |
c1a9b12d | 5633 | _ => None |
1a4d82fc | 5634 | } |
c1a9b12d SL |
5635 | } else { |
5636 | csearch::get_impl_polarity(self, id) | |
1a4d82fc | 5637 | } |
c1a9b12d | 5638 | } |
1a4d82fc | 5639 | |
c1a9b12d SL |
5640 | pub fn custom_coerce_unsized_kind(&self, did: ast::DefId) -> CustomCoerceUnsized { |
5641 | memoized(&self.custom_coerce_unsized_kinds, did, |did: DefId| { | |
5642 | let (kind, src) = if did.krate != ast::LOCAL_CRATE { | |
5643 | (csearch::get_custom_coerce_unsized_kind(self, did), "external") | |
5644 | } else { | |
5645 | (None, "local") | |
5646 | }; | |
1a4d82fc | 5647 | |
c1a9b12d SL |
5648 | match kind { |
5649 | Some(kind) => kind, | |
5650 | None => { | |
5651 | self.sess.bug(&format!("custom_coerce_unsized_kind: \ | |
5652 | {} impl `{}` is missing its kind", | |
5653 | src, self.item_path_str(did))); | |
5654 | } | |
5655 | } | |
5656 | }) | |
5657 | } | |
85aaf69f | 5658 | |
c1a9b12d SL |
5659 | pub fn impl_or_trait_item(&self, id: ast::DefId) -> ImplOrTraitItem<'tcx> { |
5660 | lookup_locally_or_in_crate_store( | |
5661 | "impl_or_trait_items", id, &self.impl_or_trait_items, | |
5662 | || csearch::get_impl_or_trait_item(self, id)) | |
5663 | } | |
1a4d82fc | 5664 | |
c1a9b12d SL |
5665 | pub fn trait_item_def_ids(&self, id: ast::DefId) -> Rc<Vec<ImplOrTraitItemId>> { |
5666 | lookup_locally_or_in_crate_store( | |
5667 | "trait_item_def_ids", id, &self.trait_item_def_ids, | |
5668 | || Rc::new(csearch::get_trait_item_def_ids(&self.sess.cstore, id))) | |
1a4d82fc | 5669 | } |
1a4d82fc | 5670 | |
c1a9b12d SL |
5671 | /// Returns the trait-ref corresponding to a given impl, or None if it is |
5672 | /// an inherent impl. | |
5673 | pub fn impl_trait_ref(&self, id: ast::DefId) -> Option<TraitRef<'tcx>> { | |
5674 | lookup_locally_or_in_crate_store( | |
5675 | "impl_trait_refs", id, &self.impl_trait_refs, | |
5676 | || csearch::get_impl_trait(self, id)) | |
5677 | } | |
1a4d82fc | 5678 | |
c1a9b12d SL |
5679 | /// Returns whether this DefId refers to an impl |
5680 | pub fn is_impl(&self, id: ast::DefId) -> bool { | |
5681 | if id.krate == ast::LOCAL_CRATE { | |
5682 | if let Some(ast_map::NodeItem( | |
5683 | &ast::Item { node: ast::ItemImpl(..), .. })) = self.map.find(id.node) { | |
5684 | true | |
5685 | } else { | |
5686 | false | |
5687 | } | |
5688 | } else { | |
5689 | csearch::is_impl(&self.sess.cstore, id) | |
5690 | } | |
5691 | } | |
1a4d82fc | 5692 | |
c1a9b12d SL |
5693 | pub fn trait_ref_to_def_id(&self, tr: &ast::TraitRef) -> ast::DefId { |
5694 | self.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id() | |
5695 | } | |
1a4d82fc | 5696 | |
c1a9b12d SL |
5697 | pub fn try_add_builtin_trait(&self, |
5698 | trait_def_id: ast::DefId, | |
5699 | builtin_bounds: &mut EnumSet<BuiltinBound>) | |
5700 | -> bool | |
5701 | { | |
5702 | //! Checks whether `trait_ref` refers to one of the builtin | |
5703 | //! traits, like `Send`, and adds the corresponding | |
5704 | //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref` | |
5705 | //! is a builtin trait. | |
1a4d82fc | 5706 | |
c1a9b12d SL |
5707 | match self.lang_items.to_builtin_kind(trait_def_id) { |
5708 | Some(bound) => { builtin_bounds.insert(bound); true } | |
5709 | None => false | |
5710 | } | |
d9579d0f | 5711 | } |
d9579d0f | 5712 | |
c1a9b12d SL |
5713 | pub fn substd_enum_variants(&self, |
5714 | id: ast::DefId, | |
5715 | substs: &Substs<'tcx>) | |
5716 | -> Vec<Rc<VariantInfo<'tcx>>> { | |
5717 | self.enum_variants(id).iter().map(|variant_info| { | |
5718 | let substd_args = variant_info.args.iter() | |
5719 | .map(|aty| aty.subst(self, substs)).collect::<Vec<_>>(); | |
d9579d0f | 5720 | |
c1a9b12d | 5721 | let substd_ctor_ty = variant_info.ctor_ty.subst(self, substs); |
1a4d82fc | 5722 | |
c1a9b12d SL |
5723 | Rc::new(VariantInfo { |
5724 | args: substd_args, | |
5725 | ctor_ty: substd_ctor_ty, | |
5726 | ..(**variant_info).clone() | |
5727 | }) | |
5728 | }).collect() | |
1a4d82fc | 5729 | } |
1a4d82fc | 5730 | |
c1a9b12d SL |
5731 | pub fn item_path_str(&self, id: ast::DefId) -> String { |
5732 | self.with_path(id, |path| ast_map::path_to_string(path)) | |
5733 | } | |
1a4d82fc | 5734 | |
c1a9b12d SL |
5735 | /* If struct_id names a struct with a dtor. */ |
5736 | pub fn ty_dtor(&self, struct_id: DefId) -> DtorKind { | |
5737 | match self.destructor_for_type.borrow().get(&struct_id) { | |
5738 | Some(&method_def_id) => { | |
5739 | let flag = !self.has_attr(struct_id, "unsafe_no_drop_flag"); | |
1a4d82fc | 5740 | |
c1a9b12d | 5741 | TraitDtor(method_def_id, flag) |
1a4d82fc | 5742 | } |
c1a9b12d | 5743 | None => NoDtor, |
1a4d82fc | 5744 | } |
c1a9b12d | 5745 | } |
1a4d82fc | 5746 | |
c1a9b12d SL |
5747 | pub fn has_dtor(&self, struct_id: DefId) -> bool { |
5748 | self.destructor_for_type.borrow().contains_key(&struct_id) | |
9346a6ac | 5749 | } |
9346a6ac | 5750 | |
c1a9b12d SL |
5751 | pub fn with_path<T, F>(&self, id: ast::DefId, f: F) -> T where |
5752 | F: FnOnce(ast_map::PathElems) -> T, | |
5753 | { | |
5754 | if id.krate == ast::LOCAL_CRATE { | |
5755 | self.map.with_path(id.node, f) | |
9346a6ac | 5756 | } else { |
c1a9b12d | 5757 | f(csearch::get_item_path(self, id).iter().cloned().chain(LinkedPath::empty())) |
9346a6ac AL |
5758 | } |
5759 | } | |
9346a6ac | 5760 | |
c1a9b12d SL |
5761 | pub fn enum_is_univariant(&self, id: ast::DefId) -> bool { |
5762 | self.enum_variants(id).len() == 1 | |
5763 | } | |
1a4d82fc | 5764 | |
c1a9b12d SL |
5765 | /// Returns `(normalized_type, ty)`, where `normalized_type` is the |
5766 | /// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8}, | |
5767 | /// and `ty` is the original type (i.e. may include `isize` or | |
5768 | /// `usize`). | |
5769 | pub fn enum_repr_type(&self, opt_hint: Option<&attr::ReprAttr>) | |
5770 | -> (attr::IntType, Ty<'tcx>) { | |
5771 | let repr_type = match opt_hint { | |
5772 | // Feed in the given type | |
5773 | Some(&attr::ReprInt(_, int_t)) => int_t, | |
5774 | // ... but provide sensible default if none provided | |
5775 | // | |
5776 | // NB. Historically `fn enum_variants` generate i64 here, while | |
5777 | // rustc_typeck::check would generate isize. | |
5778 | _ => SignedInt(ast::TyIs), | |
5779 | }; | |
1a4d82fc | 5780 | |
c1a9b12d SL |
5781 | let repr_type_ty = repr_type.to_ty(self); |
5782 | let repr_type = match repr_type { | |
5783 | SignedInt(ast::TyIs) => | |
5784 | SignedInt(self.sess.target.int_type), | |
5785 | UnsignedInt(ast::TyUs) => | |
5786 | UnsignedInt(self.sess.target.uint_type), | |
5787 | other => other | |
5788 | }; | |
5789 | ||
5790 | (repr_type, repr_type_ty) | |
5791 | } | |
5792 | ||
5793 | fn report_discrim_overflow(&self, | |
5794 | variant_span: Span, | |
5795 | variant_name: &str, | |
5796 | repr_type: attr::IntType, | |
5797 | prev_val: Disr) { | |
5798 | let computed_value = repr_type.disr_wrap_incr(Some(prev_val)); | |
5799 | let computed_value = repr_type.disr_string(computed_value); | |
5800 | let prev_val = repr_type.disr_string(prev_val); | |
5801 | let repr_type = repr_type.to_ty(self); | |
5802 | span_err!(self.sess, variant_span, E0370, | |
5803 | "enum discriminant overflowed on value after {}: {}; \ | |
5804 | set explicitly via {} = {} if that is desired outcome", | |
5805 | prev_val, repr_type, variant_name, computed_value); | |
5806 | } | |
5807 | ||
5808 | // This computes the discriminant values for the sequence of Variants | |
5809 | // attached to a particular enum, taking into account the #[repr] (if | |
5810 | // any) provided via the `opt_hint`. | |
5811 | fn compute_enum_variants(&self, | |
5812 | vs: &'tcx [P<ast::Variant>], | |
5813 | opt_hint: Option<&attr::ReprAttr>) | |
5814 | -> Vec<Rc<ty::VariantInfo<'tcx>>> { | |
5815 | let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new(); | |
5816 | let mut prev_disr_val: Option<ty::Disr> = None; | |
5817 | ||
5818 | let (repr_type, repr_type_ty) = self.enum_repr_type(opt_hint); | |
5819 | ||
5820 | for v in vs { | |
5821 | // If the discriminant value is specified explicitly in the | |
5822 | // enum, check whether the initialization expression is valid, | |
5823 | // otherwise use the last value plus one. | |
5824 | let current_disr_val; | |
5825 | ||
5826 | // This closure marks cases where, when an error occurs during | |
5827 | // the computation, attempt to assign a (hopefully) fresh | |
5828 | // value to avoid spurious error reports downstream. | |
5829 | let attempt_fresh_value = move || -> Disr { | |
5830 | repr_type.disr_wrap_incr(prev_disr_val) | |
1a4d82fc | 5831 | }; |
1a4d82fc | 5832 | |
c1a9b12d SL |
5833 | match v.node.disr_expr { |
5834 | Some(ref e) => { | |
5835 | debug!("disr expr, checking {}", pprust::expr_to_string(&**e)); | |
5836 | ||
5837 | let hint = UncheckedExprHint(repr_type_ty); | |
5838 | match const_eval::eval_const_expr_partial(self, &**e, hint) { | |
5839 | Ok(ConstVal::Int(val)) => current_disr_val = val as Disr, | |
5840 | Ok(ConstVal::Uint(val)) => current_disr_val = val as Disr, | |
5841 | Ok(_) => { | |
5842 | let sign_desc = if repr_type.is_signed() { | |
5843 | "signed" | |
5844 | } else { | |
5845 | "unsigned" | |
5846 | }; | |
5847 | span_err!(self.sess, e.span, E0079, | |
5848 | "expected {} integer constant", | |
5849 | sign_desc); | |
5850 | current_disr_val = attempt_fresh_value(); | |
5851 | }, | |
5852 | Err(ref err) => { | |
5853 | span_err!(self.sess, err.span, E0080, | |
5854 | "constant evaluation error: {}", | |
5855 | err.description()); | |
5856 | current_disr_val = attempt_fresh_value(); | |
5857 | }, | |
5858 | } | |
5859 | }, | |
5860 | None => { | |
5861 | current_disr_val = match prev_disr_val { | |
5862 | Some(prev_disr_val) => { | |
5863 | if let Some(v) = repr_type.disr_incr(prev_disr_val) { | |
5864 | v | |
5865 | } else { | |
5866 | self.report_discrim_overflow(v.span, &v.node.name.name.as_str(), | |
5867 | repr_type, prev_disr_val); | |
5868 | attempt_fresh_value() | |
5869 | } | |
5870 | } | |
5871 | None => ty::INITIAL_DISCRIMINANT_VALUE, | |
5872 | } | |
5873 | }, | |
5874 | } | |
5875 | ||
5876 | let variant_info = Rc::new(VariantInfo::from_ast_variant(self, &**v, current_disr_val)); | |
5877 | prev_disr_val = Some(current_disr_val); | |
5878 | ||
5879 | variants.push(variant_info); | |
1a4d82fc | 5880 | } |
c1a9b12d SL |
5881 | |
5882 | variants | |
1a4d82fc | 5883 | } |
1a4d82fc | 5884 | |
c1a9b12d SL |
5885 | pub fn enum_variants(&self, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo<'tcx>>>> { |
5886 | memoized(&self.enum_var_cache, id, |id: ast::DefId| { | |
5887 | if ast::LOCAL_CRATE != id.krate { | |
5888 | Rc::new(csearch::get_enum_variants(self, id)) | |
5889 | } else { | |
5890 | match self.map.get(id.node) { | |
5891 | ast_map::NodeItem(ref item) => { | |
5892 | match item.node { | |
5893 | ast::ItemEnum(ref enum_definition, _) => { | |
5894 | Rc::new(self.compute_enum_variants( | |
5895 | &enum_definition.variants, | |
5896 | self.lookup_repr_hints(id).get(0))) | |
5897 | } | |
5898 | _ => { | |
5899 | self.sess.bug("enum_variants: id not bound to an enum") | |
5900 | } | |
1a4d82fc | 5901 | } |
1a4d82fc | 5902 | } |
c1a9b12d | 5903 | _ => self.sess.bug("enum_variants: id not bound to an enum") |
1a4d82fc JJ |
5904 | } |
5905 | } | |
5906 | }) | |
c34b1796 | 5907 | } |
d9579d0f | 5908 | |
c1a9b12d SL |
5909 | // Returns information about the enum variant with the given ID: |
5910 | pub fn enum_variant_with_id(&self, | |
5911 | enum_id: ast::DefId, | |
5912 | variant_id: ast::DefId) | |
5913 | -> Rc<VariantInfo<'tcx>> { | |
5914 | self.enum_variants(enum_id).iter() | |
5915 | .find(|variant| variant.id == variant_id) | |
5916 | .expect("enum_variant_with_id(): no variant exists with that ID") | |
5917 | .clone() | |
c34b1796 AL |
5918 | } |
5919 | ||
c1a9b12d SL |
5920 | // Register a given item type |
5921 | pub fn register_item_type(&self, did: ast::DefId, ty: TypeScheme<'tcx>) { | |
5922 | self.tcache.borrow_mut().insert(did, ty); | |
5923 | } | |
c34b1796 | 5924 | |
c1a9b12d SL |
5925 | // If the given item is in an external crate, looks up its type and adds it to |
5926 | // the type cache. Returns the type parameters and type. | |
5927 | pub fn lookup_item_type(&self, did: ast::DefId) -> TypeScheme<'tcx> { | |
5928 | lookup_locally_or_in_crate_store( | |
5929 | "tcache", did, &self.tcache, | |
5930 | || csearch::get_type(self, did)) | |
5931 | } | |
c34b1796 | 5932 | |
c1a9b12d SL |
5933 | /// Given the did of a trait, returns its canonical trait ref. |
5934 | pub fn lookup_trait_def(&self, did: ast::DefId) -> &'tcx TraitDef<'tcx> { | |
5935 | lookup_locally_or_in_crate_store( | |
5936 | "trait_defs", did, &self.trait_defs, | |
5937 | || self.arenas.trait_defs.alloc(csearch::get_trait_def(self, did)) | |
5938 | ) | |
5939 | } | |
c34b1796 | 5940 | |
c1a9b12d SL |
5941 | /// Given the did of an item, returns its full set of predicates. |
5942 | pub fn lookup_predicates(&self, did: ast::DefId) -> GenericPredicates<'tcx> { | |
5943 | lookup_locally_or_in_crate_store( | |
5944 | "predicates", did, &self.predicates, | |
5945 | || csearch::get_predicates(self, did)) | |
1a4d82fc | 5946 | } |
d9579d0f | 5947 | |
c1a9b12d SL |
5948 | /// Given the did of a trait, returns its superpredicates. |
5949 | pub fn lookup_super_predicates(&self, did: ast::DefId) -> GenericPredicates<'tcx> { | |
5950 | lookup_locally_or_in_crate_store( | |
5951 | "super_predicates", did, &self.super_predicates, | |
5952 | || csearch::get_super_predicates(self, did)) | |
1a4d82fc JJ |
5953 | } |
5954 | ||
c1a9b12d SL |
5955 | /// Get the attributes of a definition. |
5956 | pub fn get_attrs(&self, did: DefId) -> Cow<'tcx, [ast::Attribute]> { | |
5957 | if is_local(did) { | |
5958 | Cow::Borrowed(self.map.attrs(did.node)) | |
5959 | } else { | |
5960 | Cow::Owned(csearch::get_item_attrs(&self.sess.cstore, did)) | |
5961 | } | |
5962 | } | |
1a4d82fc | 5963 | |
c1a9b12d SL |
5964 | /// Determine whether an item is annotated with an attribute |
5965 | pub fn has_attr(&self, did: DefId, attr: &str) -> bool { | |
5966 | self.get_attrs(did).iter().any(|item| item.check_name(attr)) | |
5967 | } | |
1a4d82fc | 5968 | |
c1a9b12d SL |
5969 | /// Determine whether an item is annotated with `#[repr(packed)]` |
5970 | pub fn lookup_packed(&self, did: DefId) -> bool { | |
5971 | self.lookup_repr_hints(did).contains(&attr::ReprPacked) | |
5972 | } | |
1a4d82fc | 5973 | |
c1a9b12d SL |
5974 | /// Determine whether an item is annotated with `#[simd]` |
5975 | pub fn lookup_simd(&self, did: DefId) -> bool { | |
5976 | self.has_attr(did, "simd") | |
5977 | } | |
1a4d82fc | 5978 | |
c1a9b12d SL |
5979 | /// Obtain the representation annotation for a struct definition. |
5980 | pub fn lookup_repr_hints(&self, did: DefId) -> Rc<Vec<attr::ReprAttr>> { | |
5981 | memoized(&self.repr_hint_cache, did, |did: DefId| { | |
5982 | Rc::new(if did.krate == LOCAL_CRATE { | |
5983 | self.get_attrs(did).iter().flat_map(|meta| { | |
5984 | attr::find_repr_attrs(self.sess.diagnostic(), meta).into_iter() | |
5985 | }).collect() | |
5986 | } else { | |
5987 | csearch::get_repr_attrs(&self.sess.cstore, did) | |
5988 | }) | |
5989 | }) | |
1a4d82fc | 5990 | } |
c34b1796 | 5991 | |
c1a9b12d SL |
5992 | // Look up a field ID, whether or not it's local |
5993 | pub fn lookup_field_type_unsubstituted(&self, | |
5994 | struct_id: DefId, | |
5995 | id: DefId) | |
5996 | -> Ty<'tcx> { | |
5997 | if id.krate == ast::LOCAL_CRATE { | |
5998 | self.node_id_to_type(id.node) | |
5999 | } else { | |
6000 | memoized(&self.tcache, id, | |
6001 | |id| csearch::get_field_type(self, struct_id, id)).ty | |
6002 | } | |
1a4d82fc JJ |
6003 | } |
6004 | ||
d9579d0f | 6005 | |
c1a9b12d SL |
6006 | // Look up a field ID, whether or not it's local |
6007 | // Takes a list of type substs in case the struct is generic | |
6008 | pub fn lookup_field_type(&self, | |
6009 | struct_id: DefId, | |
6010 | id: DefId, | |
6011 | substs: &Substs<'tcx>) | |
6012 | -> Ty<'tcx> { | |
6013 | self.lookup_field_type_unsubstituted(struct_id, id).subst(self, substs) | |
c34b1796 AL |
6014 | } |
6015 | ||
c1a9b12d SL |
6016 | // Look up the list of field names and IDs for a given struct. |
6017 | // Panics if the id is not bound to a struct. | |
6018 | pub fn lookup_struct_fields(&self, did: ast::DefId) -> Vec<FieldTy> { | |
6019 | if did.krate == ast::LOCAL_CRATE { | |
6020 | let struct_fields = self.struct_fields.borrow(); | |
6021 | match struct_fields.get(&did) { | |
6022 | Some(fields) => (**fields).clone(), | |
6023 | _ => { | |
6024 | self.sess.bug( | |
6025 | &format!("ID not mapped to struct fields: {}", | |
6026 | self.map.node_to_string(did.node))); | |
1a4d82fc | 6027 | } |
1a4d82fc | 6028 | } |
c1a9b12d SL |
6029 | } else { |
6030 | csearch::get_struct_fields(&self.sess.cstore, did) | |
1a4d82fc | 6031 | } |
c1a9b12d | 6032 | } |
1a4d82fc | 6033 | |
c1a9b12d SL |
6034 | pub fn is_tuple_struct(&self, did: ast::DefId) -> bool { |
6035 | let fields = self.lookup_struct_fields(did); | |
6036 | !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field) | |
6037 | } | |
1a4d82fc | 6038 | |
c1a9b12d SL |
6039 | // Returns a list of fields corresponding to the struct's items. trans uses |
6040 | // this. Takes a list of substs with which to instantiate field types. | |
6041 | pub fn struct_fields(&self, did: ast::DefId, substs: &Substs<'tcx>) | |
6042 | -> Vec<Field<'tcx>> { | |
6043 | self.lookup_struct_fields(did).iter().map(|f| { | |
6044 | Field { | |
6045 | name: f.name, | |
6046 | mt: TypeAndMut { | |
6047 | ty: self.lookup_field_type(did, f.id, substs), | |
6048 | mutbl: MutImmutable | |
6049 | } | |
6050 | } | |
6051 | }).collect() | |
1a4d82fc | 6052 | } |
c1a9b12d SL |
6053 | |
6054 | /// Returns the deeply last field of nested structures, or the same type, | |
6055 | /// if not a structure at all. Corresponds to the only possible unsized | |
6056 | /// field, and its type can be used to determine unsizing strategy. | |
6057 | pub fn struct_tail(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> { | |
6058 | while let TyStruct(def_id, substs) = ty.sty { | |
6059 | match self.struct_fields(def_id, substs).last() { | |
6060 | Some(f) => ty = f.mt.ty, | |
6061 | None => break | |
1a4d82fc JJ |
6062 | } |
6063 | } | |
c1a9b12d | 6064 | ty |
1a4d82fc | 6065 | } |
1a4d82fc | 6066 | |
c1a9b12d SL |
6067 | /// Same as applying struct_tail on `source` and `target`, but only |
6068 | /// keeps going as long as the two types are instances of the same | |
6069 | /// structure definitions. | |
6070 | /// For `(Foo<Foo<T>>, Foo<Trait>)`, the result will be `(Foo<T>, Trait)`, | |
6071 | /// whereas struct_tail produces `T`, and `Trait`, respectively. | |
6072 | pub fn struct_lockstep_tails(&self, | |
6073 | source: Ty<'tcx>, | |
6074 | target: Ty<'tcx>) | |
6075 | -> (Ty<'tcx>, Ty<'tcx>) { | |
6076 | let (mut a, mut b) = (source, target); | |
6077 | while let (&TyStruct(a_did, a_substs), &TyStruct(b_did, b_substs)) = (&a.sty, &b.sty) { | |
6078 | if a_did != b_did { | |
6079 | break; | |
6080 | } | |
6081 | if let Some(a_f) = self.struct_fields(a_did, a_substs).last() { | |
6082 | if let Some(b_f) = self.struct_fields(b_did, b_substs).last() { | |
6083 | a = a_f.mt.ty; | |
6084 | b = b_f.mt.ty; | |
6085 | } else { | |
6086 | break; | |
6087 | } | |
6088 | } else { | |
6089 | break; | |
6090 | } | |
6091 | } | |
6092 | (a, b) | |
1a4d82fc | 6093 | } |
c1a9b12d SL |
6094 | |
6095 | // Returns the repeat count for a repeating vector expression. | |
6096 | pub fn eval_repeat_count(&self, count_expr: &ast::Expr) -> usize { | |
6097 | let hint = UncheckedExprHint(self.types.usize); | |
6098 | match const_eval::eval_const_expr_partial(self, count_expr, hint) { | |
6099 | Ok(val) => { | |
6100 | let found = match val { | |
6101 | ConstVal::Uint(count) => return count as usize, | |
6102 | ConstVal::Int(count) if count >= 0 => return count as usize, | |
6103 | const_val => const_val.description(), | |
6104 | }; | |
6105 | span_err!(self.sess, count_expr.span, E0306, | |
6106 | "expected positive integer for repeat count, found {}", | |
6107 | found); | |
6108 | } | |
6109 | Err(err) => { | |
6110 | let err_msg = match count_expr.node { | |
6111 | ast::ExprPath(None, ast::Path { | |
6112 | global: false, | |
6113 | ref segments, | |
6114 | .. | |
6115 | }) if segments.len() == 1 => | |
6116 | format!("found variable"), | |
6117 | _ => match err.kind { | |
6118 | ErrKind::MiscCatchAll => format!("but found {}", err.description()), | |
6119 | _ => format!("but {}", err.description()) | |
6120 | } | |
6121 | }; | |
6122 | span_err!(self.sess, count_expr.span, E0307, | |
6123 | "expected constant integer for repeat count, {}", err_msg); | |
1a4d82fc JJ |
6124 | } |
6125 | } | |
c1a9b12d | 6126 | 0 |
1a4d82fc | 6127 | } |
1a4d82fc | 6128 | |
c1a9b12d SL |
6129 | // Iterate over a type parameter's bounded traits and any supertraits |
6130 | // of those traits, ignoring kinds. | |
6131 | // Here, the supertraits are the transitive closure of the supertrait | |
6132 | // relation on the supertraits from each bounded trait's constraint | |
6133 | // list. | |
6134 | pub fn each_bound_trait_and_supertraits<F>(&self, | |
6135 | bounds: &[PolyTraitRef<'tcx>], | |
6136 | mut f: F) | |
6137 | -> bool where | |
6138 | F: FnMut(PolyTraitRef<'tcx>) -> bool, | |
6139 | { | |
6140 | for bound_trait_ref in traits::transitive_bounds(self, bounds) { | |
6141 | if !f(bound_trait_ref) { | |
6142 | return false; | |
6143 | } | |
223e47cc | 6144 | } |
c1a9b12d | 6145 | return true; |
1a4d82fc | 6146 | } |
1a4d82fc | 6147 | |
c1a9b12d SL |
6148 | /// Given a set of predicates that apply to an object type, returns |
6149 | /// the region bounds that the (erased) `Self` type must | |
6150 | /// outlive. Precisely *because* the `Self` type is erased, the | |
6151 | /// parameter `erased_self_ty` must be supplied to indicate what type | |
6152 | /// has been used to represent `Self` in the predicates | |
6153 | /// themselves. This should really be a unique type; `FreshTy(0)` is a | |
6154 | /// popular choice. | |
6155 | /// | |
6156 | /// Requires that trait definitions have been processed so that we can | |
6157 | /// elaborate predicates and walk supertraits. | |
6158 | pub fn required_region_bounds(&self, | |
6159 | erased_self_ty: Ty<'tcx>, | |
6160 | predicates: Vec<ty::Predicate<'tcx>>) | |
6161 | -> Vec<ty::Region> | |
6162 | { | |
6163 | debug!("required_region_bounds(erased_self_ty={:?}, predicates={:?})", | |
6164 | erased_self_ty, | |
6165 | predicates); | |
6166 | ||
6167 | assert!(!erased_self_ty.has_escaping_regions()); | |
6168 | ||
6169 | traits::elaborate_predicates(self, predicates) | |
6170 | .filter_map(|predicate| { | |
6171 | match predicate { | |
6172 | ty::Predicate::Projection(..) | | |
6173 | ty::Predicate::Trait(..) | | |
6174 | ty::Predicate::Equate(..) | | |
6175 | ty::Predicate::RegionOutlives(..) => { | |
6176 | None | |
6177 | } | |
6178 | ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => { | |
6179 | // Search for a bound of the form `erased_self_ty | |
6180 | // : 'a`, but be wary of something like `for<'a> | |
6181 | // erased_self_ty : 'a` (we interpret a | |
6182 | // higher-ranked bound like that as 'static, | |
6183 | // though at present the code in `fulfill.rs` | |
6184 | // considers such bounds to be unsatisfiable, so | |
6185 | // it's kind of a moot point since you could never | |
6186 | // construct such an object, but this seems | |
6187 | // correct even if that code changes). | |
6188 | if t == erased_self_ty && !r.has_escaping_regions() { | |
6189 | if r.has_escaping_regions() { | |
6190 | Some(ty::ReStatic) | |
6191 | } else { | |
6192 | Some(r) | |
6193 | } | |
6194 | } else { | |
6195 | None | |
6196 | } | |
6197 | } | |
6198 | } | |
6199 | }) | |
6200 | .collect() | |
6201 | } | |
1a4d82fc | 6202 | |
c1a9b12d SL |
6203 | pub fn item_variances(&self, item_id: ast::DefId) -> Rc<ItemVariances> { |
6204 | lookup_locally_or_in_crate_store( | |
6205 | "item_variance_map", item_id, &self.item_variance_map, | |
6206 | || Rc::new(csearch::get_item_variances(&self.sess.cstore, item_id))) | |
6207 | } | |
1a4d82fc | 6208 | |
c1a9b12d SL |
6209 | pub fn trait_has_default_impl(&self, trait_def_id: DefId) -> bool { |
6210 | self.populate_implementations_for_trait_if_necessary(trait_def_id); | |
1a4d82fc | 6211 | |
c1a9b12d SL |
6212 | let def = self.lookup_trait_def(trait_def_id); |
6213 | def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL) | |
223e47cc | 6214 | } |
223e47cc | 6215 | |
c1a9b12d SL |
6216 | /// Records a trait-to-implementation mapping. |
6217 | pub fn record_trait_has_default_impl(&self, trait_def_id: DefId) { | |
6218 | let def = self.lookup_trait_def(trait_def_id); | |
6219 | def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL) | |
223e47cc | 6220 | } |
223e47cc | 6221 | |
c1a9b12d SL |
6222 | /// Load primitive inherent implementations if necessary |
6223 | pub fn populate_implementations_for_primitive_if_necessary(&self, | |
6224 | primitive_def_id: ast::DefId) { | |
6225 | if primitive_def_id.krate == LOCAL_CRATE { | |
6226 | return | |
6227 | } | |
223e47cc | 6228 | |
c1a9b12d SL |
6229 | if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) { |
6230 | return | |
6231 | } | |
223e47cc | 6232 | |
c1a9b12d SL |
6233 | debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", |
6234 | primitive_def_id); | |
85aaf69f | 6235 | |
c1a9b12d | 6236 | let impl_items = csearch::get_impl_items(&self.sess.cstore, primitive_def_id); |
223e47cc | 6237 | |
c1a9b12d SL |
6238 | // Store the implementation info. |
6239 | self.impl_items.borrow_mut().insert(primitive_def_id, impl_items); | |
6240 | self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id); | |
6241 | } | |
223e47cc | 6242 | |
c1a9b12d SL |
6243 | /// Populates the type context with all the inherent implementations for |
6244 | /// the given type if necessary. | |
6245 | pub fn populate_inherent_implementations_for_type_if_necessary(&self, | |
6246 | type_id: ast::DefId) { | |
6247 | if type_id.krate == LOCAL_CRATE { | |
6248 | return | |
85aaf69f | 6249 | } |
85aaf69f | 6250 | |
c1a9b12d SL |
6251 | if self.populated_external_types.borrow().contains(&type_id) { |
6252 | return | |
6253 | } | |
6254 | ||
6255 | debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}", | |
6256 | type_id); | |
6257 | ||
6258 | let mut inherent_impls = Vec::new(); | |
6259 | csearch::each_inherent_implementation_for_type(&self.sess.cstore, type_id, |impl_def_id| { | |
6260 | // Record the implementation. | |
6261 | inherent_impls.push(impl_def_id); | |
6262 | ||
6263 | // Store the implementation info. | |
6264 | let impl_items = csearch::get_impl_items(&self.sess.cstore, impl_def_id); | |
6265 | self.impl_items.borrow_mut().insert(impl_def_id, impl_items); | |
6266 | }); | |
6267 | ||
6268 | self.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls)); | |
6269 | self.populated_external_types.borrow_mut().insert(type_id); | |
85aaf69f | 6270 | } |
85aaf69f | 6271 | |
c1a9b12d SL |
6272 | /// Populates the type context with all the implementations for the given |
6273 | /// trait if necessary. | |
6274 | pub fn populate_implementations_for_trait_if_necessary(&self, trait_id: ast::DefId) { | |
6275 | if trait_id.krate == LOCAL_CRATE { | |
6276 | return | |
6277 | } | |
85aaf69f | 6278 | |
c1a9b12d SL |
6279 | let def = self.lookup_trait_def(trait_id); |
6280 | if def.flags.get().intersects(TraitFlags::IMPLS_VALID) { | |
6281 | return; | |
6282 | } | |
223e47cc | 6283 | |
c1a9b12d | 6284 | debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def); |
1a4d82fc | 6285 | |
c1a9b12d SL |
6286 | if csearch::is_defaulted_trait(&self.sess.cstore, trait_id) { |
6287 | self.record_trait_has_default_impl(trait_id); | |
6288 | } | |
1a4d82fc | 6289 | |
c1a9b12d SL |
6290 | csearch::each_implementation_for_trait(&self.sess.cstore, trait_id, |impl_def_id| { |
6291 | let impl_items = csearch::get_impl_items(&self.sess.cstore, impl_def_id); | |
6292 | let trait_ref = self.impl_trait_ref(impl_def_id).unwrap(); | |
6293 | // Record the trait->implementation mapping. | |
6294 | def.record_impl(self, impl_def_id, trait_ref); | |
1a4d82fc | 6295 | |
c1a9b12d SL |
6296 | // For any methods that use a default implementation, add them to |
6297 | // the map. This is a bit unfortunate. | |
6298 | for impl_item_def_id in &impl_items { | |
6299 | let method_def_id = impl_item_def_id.def_id(); | |
6300 | match self.impl_or_trait_item(method_def_id) { | |
6301 | MethodTraitItem(method) => { | |
6302 | if let Some(source) = method.provided_source { | |
6303 | self.provided_method_sources | |
6304 | .borrow_mut() | |
6305 | .insert(method_def_id, source); | |
6306 | } | |
6307 | } | |
6308 | _ => {} | |
6309 | } | |
6310 | } | |
85aaf69f | 6311 | |
c1a9b12d SL |
6312 | // Store the implementation info. |
6313 | self.impl_items.borrow_mut().insert(impl_def_id, impl_items); | |
6314 | }); | |
1a4d82fc | 6315 | |
c1a9b12d SL |
6316 | def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID); |
6317 | } | |
223e47cc | 6318 | |
c1a9b12d SL |
6319 | /// Given the def_id of an impl, return the def_id of the trait it implements. |
6320 | /// If it implements no trait, return `None`. | |
6321 | pub fn trait_id_of_impl(&self, def_id: ast::DefId) -> Option<ast::DefId> { | |
6322 | self.impl_trait_ref(def_id).map(|tr| tr.def_id) | |
1a4d82fc | 6323 | } |
223e47cc | 6324 | |
c1a9b12d SL |
6325 | /// If the given def ID describes a method belonging to an impl, return the |
6326 | /// ID of the impl that the method belongs to. Otherwise, return `None`. | |
6327 | pub fn impl_of_method(&self, def_id: ast::DefId) -> Option<ast::DefId> { | |
6328 | if def_id.krate != LOCAL_CRATE { | |
6329 | return match csearch::get_impl_or_trait_item(self, | |
6330 | def_id).container() { | |
6331 | TraitContainer(_) => None, | |
6332 | ImplContainer(def_id) => Some(def_id), | |
6333 | }; | |
6334 | } | |
6335 | match self.impl_or_trait_items.borrow().get(&def_id).cloned() { | |
6336 | Some(trait_item) => { | |
6337 | match trait_item.container() { | |
6338 | TraitContainer(_) => None, | |
6339 | ImplContainer(def_id) => Some(def_id), | |
6340 | } | |
6341 | } | |
6342 | None => None | |
6343 | } | |
6344 | } | |
223e47cc | 6345 | |
c1a9b12d SL |
6346 | /// If the given def ID describes an item belonging to a trait (either a |
6347 | /// default method or an implementation of a trait method), return the ID of | |
6348 | /// the trait that the method belongs to. Otherwise, return `None`. | |
6349 | pub fn trait_of_item(&self, def_id: ast::DefId) -> Option<ast::DefId> { | |
6350 | if def_id.krate != LOCAL_CRATE { | |
6351 | return csearch::get_trait_of_item(&self.sess.cstore, def_id, self); | |
6352 | } | |
6353 | match self.impl_or_trait_items.borrow().get(&def_id).cloned() { | |
6354 | Some(impl_or_trait_item) => { | |
6355 | match impl_or_trait_item.container() { | |
6356 | TraitContainer(def_id) => Some(def_id), | |
6357 | ImplContainer(def_id) => self.trait_id_of_impl(def_id), | |
6358 | } | |
6359 | } | |
6360 | None => None | |
1a4d82fc JJ |
6361 | } |
6362 | } | |
223e47cc | 6363 | |
c1a9b12d SL |
6364 | /// If the given def ID describes an item belonging to a trait, (either a |
6365 | /// default method or an implementation of a trait method), return the ID of | |
6366 | /// the method inside trait definition (this means that if the given def ID | |
6367 | /// is already that of the original trait method, then the return value is | |
6368 | /// the same). | |
6369 | /// Otherwise, return `None`. | |
6370 | pub fn trait_item_of_item(&self, def_id: ast::DefId) -> Option<ImplOrTraitItemId> { | |
6371 | let impl_item = match self.impl_or_trait_items.borrow().get(&def_id) { | |
6372 | Some(m) => m.clone(), | |
6373 | None => return None, | |
6374 | }; | |
6375 | let name = impl_item.name(); | |
6376 | match self.trait_of_item(def_id) { | |
6377 | Some(trait_did) => { | |
6378 | self.trait_items(trait_did).iter() | |
6379 | .find(|item| item.name() == name) | |
6380 | .map(|item| item.id()) | |
6381 | } | |
6382 | None => None | |
6383 | } | |
6384 | } | |
6385 | ||
6386 | /// Creates a hash of the type `Ty` which will be the same no matter what crate | |
6387 | /// context it's calculated within. This is used by the `type_id` intrinsic. | |
6388 | pub fn hash_crate_independent(&self, ty: Ty<'tcx>, svh: &Svh) -> u64 { | |
6389 | let mut state = SipHasher::new(); | |
6390 | helper(self, ty, svh, &mut state); | |
6391 | return state.finish(); | |
6392 | ||
6393 | fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh, | |
6394 | state: &mut SipHasher) { | |
6395 | macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } } | |
6396 | macro_rules! hash { ($e:expr) => { $e.hash(state) } } | |
6397 | ||
6398 | let region = |state: &mut SipHasher, r: Region| { | |
6399 | match r { | |
6400 | ReStatic => {} | |
6401 | ReLateBound(db, BrAnon(i)) => { | |
6402 | db.hash(state); | |
6403 | i.hash(state); | |
6404 | } | |
6405 | ReEmpty | | |
6406 | ReEarlyBound(..) | | |
6407 | ReLateBound(..) | | |
6408 | ReFree(..) | | |
6409 | ReScope(..) | | |
6410 | ReInfer(..) => { | |
6411 | tcx.sess.bug("unexpected region found when hashing a type") | |
6412 | } | |
6413 | } | |
6414 | }; | |
6415 | let did = |state: &mut SipHasher, did: DefId| { | |
6416 | let h = if ast_util::is_local(did) { | |
6417 | svh.clone() | |
6418 | } else { | |
6419 | tcx.sess.cstore.get_crate_hash(did.krate) | |
6420 | }; | |
6421 | h.as_str().hash(state); | |
6422 | did.node.hash(state); | |
6423 | }; | |
6424 | let mt = |state: &mut SipHasher, mt: TypeAndMut| { | |
6425 | mt.mutbl.hash(state); | |
6426 | }; | |
6427 | let fn_sig = |state: &mut SipHasher, sig: &Binder<FnSig<'tcx>>| { | |
6428 | let sig = tcx.anonymize_late_bound_regions(sig).0; | |
6429 | for a in &sig.inputs { helper(tcx, *a, svh, state); } | |
6430 | if let ty::FnConverging(output) = sig.output { | |
6431 | helper(tcx, output, svh, state); | |
6432 | } | |
6433 | }; | |
6434 | ty.maybe_walk(|ty| { | |
6435 | match ty.sty { | |
6436 | TyBool => byte!(2), | |
6437 | TyChar => byte!(3), | |
6438 | TyInt(i) => { | |
6439 | byte!(4); | |
6440 | hash!(i); | |
6441 | } | |
6442 | TyUint(u) => { | |
6443 | byte!(5); | |
6444 | hash!(u); | |
6445 | } | |
6446 | TyFloat(f) => { | |
6447 | byte!(6); | |
6448 | hash!(f); | |
6449 | } | |
6450 | TyStr => { | |
6451 | byte!(7); | |
6452 | } | |
6453 | TyEnum(d, _) => { | |
6454 | byte!(8); | |
6455 | did(state, d); | |
6456 | } | |
6457 | TyBox(_) => { | |
6458 | byte!(9); | |
6459 | } | |
6460 | TyArray(_, n) => { | |
6461 | byte!(10); | |
6462 | n.hash(state); | |
6463 | } | |
6464 | TySlice(_) => { | |
6465 | byte!(11); | |
6466 | } | |
6467 | TyRawPtr(m) => { | |
6468 | byte!(12); | |
6469 | mt(state, m); | |
6470 | } | |
6471 | TyRef(r, m) => { | |
6472 | byte!(13); | |
6473 | region(state, *r); | |
6474 | mt(state, m); | |
6475 | } | |
6476 | TyBareFn(opt_def_id, ref b) => { | |
6477 | byte!(14); | |
6478 | hash!(opt_def_id); | |
6479 | hash!(b.unsafety); | |
6480 | hash!(b.abi); | |
6481 | fn_sig(state, &b.sig); | |
6482 | return false; | |
6483 | } | |
6484 | TyTrait(ref data) => { | |
6485 | byte!(17); | |
6486 | did(state, data.principal_def_id()); | |
6487 | hash!(data.bounds); | |
6488 | ||
6489 | let principal = tcx.anonymize_late_bound_regions(&data.principal).0; | |
6490 | for subty in &principal.substs.types { | |
6491 | helper(tcx, subty, svh, state); | |
6492 | } | |
6493 | ||
6494 | return false; | |
6495 | } | |
6496 | TyStruct(d, _) => { | |
6497 | byte!(18); | |
6498 | did(state, d); | |
6499 | } | |
6500 | TyTuple(ref inner) => { | |
6501 | byte!(19); | |
6502 | hash!(inner.len()); | |
6503 | } | |
6504 | TyParam(p) => { | |
6505 | byte!(20); | |
6506 | hash!(p.space); | |
6507 | hash!(p.idx); | |
6508 | hash!(p.name.as_str()); | |
6509 | } | |
6510 | TyInfer(_) => unreachable!(), | |
6511 | TyError => byte!(21), | |
6512 | TyClosure(d, _) => { | |
6513 | byte!(22); | |
6514 | did(state, d); | |
6515 | } | |
6516 | TyProjection(ref data) => { | |
6517 | byte!(23); | |
6518 | did(state, data.trait_ref.def_id); | |
6519 | hash!(data.item_name.as_str()); | |
6520 | } | |
6521 | } | |
6522 | true | |
6523 | }); | |
6524 | } | |
6525 | } | |
6526 | ||
6527 | /// Construct a parameter environment suitable for static contexts or other contexts where there | |
6528 | /// are no free type/lifetime parameters in scope. | |
6529 | pub fn empty_parameter_environment<'a>(&'a self) -> ParameterEnvironment<'a,'tcx> { | |
6530 | ty::ParameterEnvironment { tcx: self, | |
6531 | free_substs: Substs::empty(), | |
6532 | caller_bounds: Vec::new(), | |
6533 | implicit_region_bound: ty::ReEmpty, | |
6534 | selection_cache: traits::SelectionCache::new(), } | |
6535 | } | |
6536 | ||
6537 | /// Constructs and returns a substitution that can be applied to move from | |
6538 | /// the "outer" view of a type or method to the "inner" view. | |
6539 | /// In general, this means converting from bound parameters to | |
6540 | /// free parameters. Since we currently represent bound/free type | |
6541 | /// parameters in the same way, this only has an effect on regions. | |
6542 | pub fn construct_free_substs(&self, generics: &Generics<'tcx>, | |
6543 | free_id: ast::NodeId) -> Substs<'tcx> { | |
6544 | // map T => T | |
6545 | let mut types = VecPerParamSpace::empty(); | |
6546 | for def in generics.types.as_slice() { | |
6547 | debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", | |
6548 | def); | |
6549 | types.push(def.space, self.mk_param_from_def(def)); | |
223e47cc | 6550 | } |
1a4d82fc | 6551 | |
c1a9b12d | 6552 | let free_id_outlive = region::DestructionScopeData::new(free_id); |
223e47cc | 6553 | |
c1a9b12d SL |
6554 | // map bound 'a => free 'a |
6555 | let mut regions = VecPerParamSpace::empty(); | |
6556 | for def in generics.regions.as_slice() { | |
6557 | let region = | |
6558 | ReFree(FreeRegion { scope: free_id_outlive, | |
6559 | bound_region: BrNamed(def.def_id, def.name) }); | |
6560 | debug!("push_region_params {:?}", region); | |
6561 | regions.push(def.space, region); | |
6562 | } | |
1a4d82fc | 6563 | |
c1a9b12d SL |
6564 | Substs { |
6565 | types: types, | |
6566 | regions: subst::NonerasedRegions(regions) | |
6567 | } | |
1a4d82fc JJ |
6568 | } |
6569 | ||
c1a9b12d SL |
6570 | /// See `ParameterEnvironment` struct def'n for details |
6571 | pub fn construct_parameter_environment<'a>(&'a self, | |
6572 | span: Span, | |
6573 | generics: &ty::Generics<'tcx>, | |
6574 | generic_predicates: &ty::GenericPredicates<'tcx>, | |
6575 | free_id: ast::NodeId) | |
6576 | -> ParameterEnvironment<'a, 'tcx> | |
1a4d82fc | 6577 | { |
c1a9b12d SL |
6578 | // |
6579 | // Construct the free substs. | |
6580 | // | |
1a4d82fc | 6581 | |
c1a9b12d SL |
6582 | let free_substs = self.construct_free_substs(generics, free_id); |
6583 | let free_id_outlive = region::DestructionScopeData::new(free_id); | |
1a4d82fc | 6584 | |
c1a9b12d SL |
6585 | // |
6586 | // Compute the bounds on Self and the type parameters. | |
6587 | // | |
1a4d82fc | 6588 | |
c1a9b12d SL |
6589 | let bounds = generic_predicates.instantiate(self, &free_substs); |
6590 | let bounds = self.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds)); | |
6591 | let predicates = bounds.predicates.into_vec(); | |
1a4d82fc | 6592 | |
c1a9b12d SL |
6593 | debug!("construct_parameter_environment: free_id={:?} free_subst={:?} predicates={:?}", |
6594 | free_id, | |
6595 | free_substs, | |
6596 | predicates); | |
223e47cc | 6597 | |
c1a9b12d SL |
6598 | // |
6599 | // Finally, we have to normalize the bounds in the environment, in | |
6600 | // case they contain any associated type projections. This process | |
6601 | // can yield errors if the put in illegal associated types, like | |
6602 | // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We | |
6603 | // report these errors right here; this doesn't actually feel | |
6604 | // right to me, because constructing the environment feels like a | |
6605 | // kind of a "idempotent" action, but I'm not sure where would be | |
6606 | // a better place. In practice, we construct environments for | |
6607 | // every fn once during type checking, and we'll abort if there | |
6608 | // are any errors at that point, so after type checking you can be | |
6609 | // sure that this will succeed without errors anyway. | |
6610 | // | |
223e47cc | 6611 | |
c1a9b12d SL |
6612 | let unnormalized_env = ty::ParameterEnvironment { |
6613 | tcx: self, | |
6614 | free_substs: free_substs, | |
6615 | implicit_region_bound: ty::ReScope(free_id_outlive.to_code_extent()), | |
6616 | caller_bounds: predicates, | |
6617 | selection_cache: traits::SelectionCache::new(), | |
6618 | }; | |
6619 | ||
6620 | let cause = traits::ObligationCause::misc(span, free_id); | |
6621 | traits::normalize_param_env_or_error(unnormalized_env, cause) | |
1a4d82fc | 6622 | } |
223e47cc | 6623 | |
c1a9b12d SL |
6624 | pub fn is_method_call(&self, expr_id: ast::NodeId) -> bool { |
6625 | self.tables.borrow().method_map.contains_key(&MethodCall::expr(expr_id)) | |
223e47cc LB |
6626 | } |
6627 | ||
c1a9b12d SL |
6628 | pub fn is_overloaded_autoderef(&self, expr_id: ast::NodeId, autoderefs: u32) -> bool { |
6629 | self.tables.borrow().method_map.contains_key(&MethodCall::autoderef(expr_id, | |
6630 | autoderefs)) | |
1a4d82fc JJ |
6631 | } |
6632 | ||
c1a9b12d SL |
6633 | pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { |
6634 | Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone()) | |
1a4d82fc JJ |
6635 | } |
6636 | } | |
6637 | ||
1a4d82fc | 6638 | /// The category of explicit self. |
85aaf69f | 6639 | #[derive(Clone, Copy, Eq, PartialEq, Debug)] |
1a4d82fc JJ |
6640 | pub enum ExplicitSelfCategory { |
6641 | StaticExplicitSelfCategory, | |
6642 | ByValueExplicitSelfCategory, | |
6643 | ByReferenceExplicitSelfCategory(Region, ast::Mutability), | |
6644 | ByBoxExplicitSelfCategory, | |
6645 | } | |
6646 | ||
1a4d82fc | 6647 | /// A free variable referred to in a function. |
85aaf69f | 6648 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] |
1a4d82fc JJ |
6649 | pub struct Freevar { |
6650 | /// The variable being accessed free. | |
6651 | pub def: def::Def, | |
6652 | ||
6653 | // First span where it is accessed (there can be multiple). | |
6654 | pub span: Span | |
6655 | } | |
6656 | ||
6657 | pub type FreevarMap = NodeMap<Vec<Freevar>>; | |
6658 | ||
6659 | pub type CaptureModeMap = NodeMap<ast::CaptureClause>; | |
6660 | ||
6661 | // Trait method resolution | |
6662 | pub type TraitMap = NodeMap<Vec<DefId>>; | |
6663 | ||
6664 | // Map from the NodeId of a glob import to a list of items which are actually | |
6665 | // imported. | |
6666 | pub type GlobMap = HashMap<NodeId, HashSet<Name>>; | |
6667 | ||
1a4d82fc JJ |
6668 | impl<'tcx> AutoAdjustment<'tcx> { |
6669 | pub fn is_identity(&self) -> bool { | |
6670 | match *self { | |
9346a6ac AL |
6671 | AdjustReifyFnPointer | |
6672 | AdjustUnsafeFnPointer => false, | |
1a4d82fc | 6673 | AdjustDerefRef(ref r) => r.is_identity(), |
223e47cc | 6674 | } |
1a4d82fc JJ |
6675 | } |
6676 | } | |
6677 | ||
6678 | impl<'tcx> AutoDerefRef<'tcx> { | |
6679 | pub fn is_identity(&self) -> bool { | |
9346a6ac | 6680 | self.autoderefs == 0 && self.unsize.is_none() && self.autoref.is_none() |
1a4d82fc JJ |
6681 | } |
6682 | } | |
6683 | ||
c1a9b12d SL |
6684 | impl<'tcx> ctxt<'tcx> { |
6685 | pub fn with_freevars<T, F>(&self, fid: ast::NodeId, f: F) -> T where | |
6686 | F: FnOnce(&[Freevar]) -> T, | |
6687 | { | |
6688 | match self.freevars.borrow().get(&fid) { | |
6689 | None => f(&[]), | |
6690 | Some(d) => f(&d[..]) | |
6691 | } | |
6692 | } | |
1a4d82fc | 6693 | |
c1a9b12d SL |
6694 | /// Replace any late-bound regions bound in `value` with free variants attached to scope-id |
6695 | /// `scope_id`. | |
6696 | pub fn liberate_late_bound_regions<T>(&self, | |
6697 | all_outlive_scope: region::DestructionScopeData, | |
6698 | value: &Binder<T>) | |
6699 | -> T | |
6700 | where T : TypeFoldable<'tcx> | |
6701 | { | |
6702 | ty_fold::replace_late_bound_regions( | |
6703 | self, value, | |
6704 | |br| ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, bound_region: br})).0 | |
6705 | } | |
1a4d82fc | 6706 | |
c1a9b12d SL |
6707 | /// Flattens two binding levels into one. So `for<'a> for<'b> Foo` |
6708 | /// becomes `for<'a,'b> Foo`. | |
6709 | pub fn flatten_late_bound_regions<T>(&self, bound2_value: &Binder<Binder<T>>) | |
6710 | -> Binder<T> | |
6711 | where T: TypeFoldable<'tcx> | |
6712 | { | |
6713 | let bound0_value = bound2_value.skip_binder().skip_binder(); | |
6714 | let value = ty_fold::fold_regions(self, bound0_value, &mut false, | |
6715 | |region, current_depth| { | |
6716 | match region { | |
6717 | ty::ReLateBound(debruijn, br) if debruijn.depth >= current_depth => { | |
6718 | // should be true if no escaping regions from bound2_value | |
6719 | assert!(debruijn.depth - current_depth <= 1); | |
6720 | ty::ReLateBound(DebruijnIndex::new(current_depth), br) | |
6721 | } | |
6722 | _ => { | |
6723 | region | |
6724 | } | |
c34b1796 | 6725 | } |
c1a9b12d SL |
6726 | }); |
6727 | Binder(value) | |
6728 | } | |
6729 | ||
6730 | pub fn no_late_bound_regions<T>(&self, value: &Binder<T>) -> Option<T> | |
6731 | where T : TypeFoldable<'tcx> + RegionEscape | |
6732 | { | |
6733 | if value.0.has_escaping_regions() { | |
6734 | None | |
6735 | } else { | |
6736 | Some(value.0.clone()) | |
c34b1796 | 6737 | } |
c1a9b12d | 6738 | } |
c34b1796 | 6739 | |
c1a9b12d SL |
6740 | /// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also |
6741 | /// method lookup and a few other places where precise region relationships are not required. | |
6742 | pub fn erase_late_bound_regions<T>(&self, value: &Binder<T>) -> T | |
6743 | where T : TypeFoldable<'tcx> | |
6744 | { | |
6745 | ty_fold::replace_late_bound_regions(self, value, |_| ty::ReStatic).0 | |
85aaf69f | 6746 | } |
1a4d82fc | 6747 | |
c1a9b12d SL |
6748 | /// Rewrite any late-bound regions so that they are anonymous. Region numbers are |
6749 | /// assigned starting at 1 and increasing monotonically in the order traversed | |
6750 | /// by the fold operation. | |
6751 | /// | |
6752 | /// The chief purpose of this function is to canonicalize regions so that two | |
6753 | /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become | |
6754 | /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and | |
6755 | /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization. | |
6756 | pub fn anonymize_late_bound_regions<T>(&self, sig: &Binder<T>) -> Binder<T> | |
6757 | where T : TypeFoldable<'tcx>, | |
6758 | { | |
6759 | let mut counter = 0; | |
6760 | ty::Binder(ty_fold::replace_late_bound_regions(self, sig, |_| { | |
6761 | counter += 1; | |
6762 | ReLateBound(ty::DebruijnIndex::new(1), BrAnon(counter)) | |
6763 | }).0) | |
6764 | } | |
1a4d82fc | 6765 | |
c1a9b12d SL |
6766 | pub fn make_substs_for_receiver_types(&self, |
6767 | trait_ref: &ty::TraitRef<'tcx>, | |
6768 | method: &ty::Method<'tcx>) | |
6769 | -> subst::Substs<'tcx> | |
6770 | { | |
6771 | /*! | |
6772 | * Substitutes the values for the receiver's type parameters | |
6773 | * that are found in method, leaving the method's type parameters | |
6774 | * intact. | |
6775 | */ | |
6776 | ||
6777 | let meth_tps: Vec<Ty> = | |
6778 | method.generics.types.get_slice(subst::FnSpace) | |
6779 | .iter() | |
6780 | .map(|def| self.mk_param_from_def(def)) | |
6781 | .collect(); | |
6782 | let meth_regions: Vec<ty::Region> = | |
6783 | method.generics.regions.get_slice(subst::FnSpace) | |
6784 | .iter() | |
6785 | .map(|def| def.to_early_bound_region()) | |
6786 | .collect(); | |
6787 | trait_ref.substs.clone().with_method(meth_tps, meth_regions) | |
6788 | } | |
1a4d82fc JJ |
6789 | } |
6790 | ||
1a4d82fc JJ |
6791 | impl DebruijnIndex { |
6792 | pub fn new(depth: u32) -> DebruijnIndex { | |
6793 | assert!(depth > 0); | |
6794 | DebruijnIndex { depth: depth } | |
6795 | } | |
6796 | ||
6797 | pub fn shifted(&self, amount: u32) -> DebruijnIndex { | |
6798 | DebruijnIndex { depth: self.depth + amount } | |
6799 | } | |
6800 | } | |
6801 | ||
62682a34 SL |
6802 | impl<'tcx> fmt::Debug for AutoAdjustment<'tcx> { |
6803 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
1a4d82fc | 6804 | match *self { |
9346a6ac | 6805 | AdjustReifyFnPointer => { |
62682a34 | 6806 | write!(f, "AdjustReifyFnPointer") |
1a4d82fc | 6807 | } |
c34b1796 | 6808 | AdjustUnsafeFnPointer => { |
62682a34 | 6809 | write!(f, "AdjustUnsafeFnPointer") |
c34b1796 | 6810 | } |
1a4d82fc | 6811 | AdjustDerefRef(ref data) => { |
62682a34 | 6812 | write!(f, "{:?}", data) |
1a4d82fc | 6813 | } |
223e47cc | 6814 | } |
1a4d82fc JJ |
6815 | } |
6816 | } | |
6817 | ||
62682a34 SL |
6818 | impl<'tcx> fmt::Debug for AutoDerefRef<'tcx> { |
6819 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
6820 | write!(f, "AutoDerefRef({}, unsize={:?}, {:?})", | |
6821 | self.autoderefs, self.unsize, self.autoref) | |
223e47cc LB |
6822 | } |
6823 | } | |
6824 | ||
62682a34 SL |
6825 | impl<'tcx> fmt::Debug for TraitTy<'tcx> { |
6826 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
6827 | write!(f, "TraitTy({:?},{:?})", | |
6828 | self.principal, | |
6829 | self.bounds) | |
223e47cc | 6830 | } |
1a4d82fc | 6831 | } |
223e47cc | 6832 | |
62682a34 SL |
6833 | impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { |
6834 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
1a4d82fc | 6835 | match *self { |
62682a34 SL |
6836 | Predicate::Trait(ref a) => write!(f, "{:?}", a), |
6837 | Predicate::Equate(ref pair) => write!(f, "{:?}", pair), | |
6838 | Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair), | |
6839 | Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair), | |
6840 | Predicate::Projection(ref pair) => write!(f, "{:?}", pair), | |
1a4d82fc JJ |
6841 | } |
6842 | } | |
970d7e83 LB |
6843 | } |
6844 | ||
c1a9b12d | 6845 | // FIXME(#20298) -- all of these traits basically walk various |
1a4d82fc JJ |
6846 | // structures to test whether types/regions are reachable with various |
6847 | // properties. It should be possible to express them in terms of one | |
6848 | // common "walker" trait or something. | |
970d7e83 | 6849 | |
c1a9b12d SL |
6850 | /// An "escaping region" is a bound region whose binder is not part of `t`. |
6851 | /// | |
6852 | /// So, for example, consider a type like the following, which has two binders: | |
6853 | /// | |
6854 | /// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize)) | |
6855 | /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope | |
6856 | /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope | |
6857 | /// | |
6858 | /// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the | |
6859 | /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner | |
6860 | /// fn type*, that type has an escaping region: `'a`. | |
6861 | /// | |
6862 | /// Note that what I'm calling an "escaping region" is often just called a "free region". However, | |
6863 | /// we already use the term "free region". It refers to the regions that we use to represent bound | |
6864 | /// regions on a fn definition while we are typechecking its body. | |
6865 | /// | |
6866 | /// To clarify, conceptually there is no particular difference between an "escaping" region and a | |
6867 | /// "free" region. However, there is a big difference in practice. Basically, when "entering" a | |
6868 | /// binding level, one is generally required to do some sort of processing to a bound region, such | |
6869 | /// as replacing it with a fresh/skolemized region, or making an entry in the environment to | |
6870 | /// represent the scope to which it is attached, etc. An escaping region represents a bound region | |
6871 | /// for which this processing has not yet been done. | |
1a4d82fc JJ |
6872 | pub trait RegionEscape { |
6873 | fn has_escaping_regions(&self) -> bool { | |
6874 | self.has_regions_escaping_depth(0) | |
223e47cc | 6875 | } |
1a4d82fc JJ |
6876 | |
6877 | fn has_regions_escaping_depth(&self, depth: u32) -> bool; | |
223e47cc LB |
6878 | } |
6879 | ||
1a4d82fc JJ |
6880 | impl<'tcx> RegionEscape for Ty<'tcx> { |
6881 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
c1a9b12d | 6882 | self.region_depth > depth |
223e47cc | 6883 | } |
970d7e83 | 6884 | } |
223e47cc | 6885 | |
1a4d82fc JJ |
6886 | impl<'tcx> RegionEscape for Substs<'tcx> { |
6887 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6888 | self.types.has_regions_escaping_depth(depth) || | |
6889 | self.regions.has_regions_escaping_depth(depth) | |
6890 | } | |
970d7e83 LB |
6891 | } |
6892 | ||
c1a9b12d SL |
6893 | impl<'tcx> RegionEscape for ClosureSubsts<'tcx> { |
6894 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6895 | self.func_substs.has_regions_escaping_depth(depth) || | |
6896 | self.upvar_tys.iter().any(|t| t.has_regions_escaping_depth(depth)) | |
6897 | } | |
6898 | } | |
6899 | ||
6900 | impl<T:RegionEscape> RegionEscape for Vec<T> { | |
6901 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6902 | self.iter().any(|t| t.has_regions_escaping_depth(depth)) | |
6903 | } | |
6904 | } | |
6905 | ||
6906 | impl<'tcx> RegionEscape for FnSig<'tcx> { | |
6907 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6908 | self.inputs.has_regions_escaping_depth(depth) || | |
6909 | self.output.has_regions_escaping_depth(depth) | |
6910 | } | |
6911 | } | |
6912 | ||
1a4d82fc JJ |
6913 | impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace<T> { |
6914 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6915 | self.iter_enumerated().any(|(space, _, t)| { | |
6916 | if space == subst::FnSpace { | |
6917 | t.has_regions_escaping_depth(depth+1) | |
6918 | } else { | |
6919 | t.has_regions_escaping_depth(depth) | |
970d7e83 | 6920 | } |
1a4d82fc | 6921 | }) |
223e47cc LB |
6922 | } |
6923 | } | |
6924 | ||
1a4d82fc JJ |
6925 | impl<'tcx> RegionEscape for TypeScheme<'tcx> { |
6926 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
85aaf69f | 6927 | self.ty.has_regions_escaping_depth(depth) |
223e47cc LB |
6928 | } |
6929 | } | |
6930 | ||
1a4d82fc JJ |
6931 | impl RegionEscape for Region { |
6932 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6933 | self.escapes_depth(depth) | |
223e47cc LB |
6934 | } |
6935 | } | |
6936 | ||
85aaf69f | 6937 | impl<'tcx> RegionEscape for GenericPredicates<'tcx> { |
1a4d82fc JJ |
6938 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { |
6939 | self.predicates.has_regions_escaping_depth(depth) | |
6940 | } | |
223e47cc LB |
6941 | } |
6942 | ||
1a4d82fc JJ |
6943 | impl<'tcx> RegionEscape for Predicate<'tcx> { |
6944 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6945 | match *self { | |
6946 | Predicate::Trait(ref data) => data.has_regions_escaping_depth(depth), | |
6947 | Predicate::Equate(ref data) => data.has_regions_escaping_depth(depth), | |
6948 | Predicate::RegionOutlives(ref data) => data.has_regions_escaping_depth(depth), | |
6949 | Predicate::TypeOutlives(ref data) => data.has_regions_escaping_depth(depth), | |
6950 | Predicate::Projection(ref data) => data.has_regions_escaping_depth(depth), | |
6951 | } | |
6952 | } | |
223e47cc LB |
6953 | } |
6954 | ||
c34b1796 AL |
6955 | impl<'tcx,P:RegionEscape> RegionEscape for traits::Obligation<'tcx,P> { |
6956 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6957 | self.predicate.has_regions_escaping_depth(depth) | |
6958 | } | |
6959 | } | |
6960 | ||
1a4d82fc JJ |
6961 | impl<'tcx> RegionEscape for TraitRef<'tcx> { |
6962 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6963 | self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) || | |
6964 | self.substs.regions.has_regions_escaping_depth(depth) | |
6965 | } | |
223e47cc LB |
6966 | } |
6967 | ||
1a4d82fc JJ |
6968 | impl<'tcx> RegionEscape for subst::RegionSubsts { |
6969 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
223e47cc | 6970 | match *self { |
1a4d82fc JJ |
6971 | subst::ErasedRegions => false, |
6972 | subst::NonerasedRegions(ref r) => { | |
6973 | r.iter().any(|t| t.has_regions_escaping_depth(depth)) | |
6974 | } | |
223e47cc LB |
6975 | } |
6976 | } | |
1a4d82fc | 6977 | } |
970d7e83 | 6978 | |
1a4d82fc JJ |
6979 | impl<'tcx,T:RegionEscape> RegionEscape for Binder<T> { |
6980 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6981 | self.0.has_regions_escaping_depth(depth + 1) | |
223e47cc | 6982 | } |
1a4d82fc | 6983 | } |
970d7e83 | 6984 | |
c1a9b12d SL |
6985 | impl<'tcx> RegionEscape for FnOutput<'tcx> { |
6986 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6987 | match *self { | |
6988 | FnConverging(t) => t.has_regions_escaping_depth(depth), | |
6989 | FnDiverging => false | |
6990 | } | |
6991 | } | |
6992 | } | |
6993 | ||
1a4d82fc JJ |
6994 | impl<'tcx> RegionEscape for EquatePredicate<'tcx> { |
6995 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
6996 | self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth) | |
970d7e83 | 6997 | } |
223e47cc LB |
6998 | } |
6999 | ||
1a4d82fc JJ |
7000 | impl<'tcx> RegionEscape for TraitPredicate<'tcx> { |
7001 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7002 | self.trait_ref.has_regions_escaping_depth(depth) | |
223e47cc LB |
7003 | } |
7004 | } | |
7005 | ||
1a4d82fc JJ |
7006 | impl<T:RegionEscape,U:RegionEscape> RegionEscape for OutlivesPredicate<T,U> { |
7007 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7008 | self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth) | |
7009 | } | |
223e47cc LB |
7010 | } |
7011 | ||
1a4d82fc JJ |
7012 | impl<'tcx> RegionEscape for ProjectionPredicate<'tcx> { |
7013 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7014 | self.projection_ty.has_regions_escaping_depth(depth) || | |
7015 | self.ty.has_regions_escaping_depth(depth) | |
7016 | } | |
7017 | } | |
223e47cc | 7018 | |
1a4d82fc JJ |
7019 | impl<'tcx> RegionEscape for ProjectionTy<'tcx> { |
7020 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7021 | self.trait_ref.has_regions_escaping_depth(depth) | |
223e47cc LB |
7022 | } |
7023 | } | |
7024 | ||
c1a9b12d SL |
7025 | pub trait HasTypeFlags { |
7026 | fn has_type_flags(&self, flags: TypeFlags) -> bool; | |
1a4d82fc | 7027 | fn has_projection_types(&self) -> bool { |
c1a9b12d | 7028 | self.has_type_flags(TypeFlags::HAS_PROJECTION) |
223e47cc | 7029 | } |
c1a9b12d SL |
7030 | fn references_error(&self) -> bool { |
7031 | self.has_type_flags(TypeFlags::HAS_TY_ERR) | |
223e47cc | 7032 | } |
c1a9b12d SL |
7033 | fn has_param_types(&self) -> bool { |
7034 | self.has_type_flags(TypeFlags::HAS_PARAMS) | |
1a4d82fc | 7035 | } |
c1a9b12d SL |
7036 | fn has_self_ty(&self) -> bool { |
7037 | self.has_type_flags(TypeFlags::HAS_SELF) | |
1a4d82fc | 7038 | } |
c1a9b12d SL |
7039 | fn has_infer_types(&self) -> bool { |
7040 | self.has_type_flags(TypeFlags::HAS_TY_INFER) | |
970d7e83 | 7041 | } |
c1a9b12d SL |
7042 | fn needs_infer(&self) -> bool { |
7043 | self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER) | |
223e47cc | 7044 | } |
c1a9b12d SL |
7045 | fn needs_subst(&self) -> bool { |
7046 | self.has_type_flags(TypeFlags::NEEDS_SUBST) | |
1a4d82fc | 7047 | } |
c1a9b12d SL |
7048 | fn has_closure_types(&self) -> bool { |
7049 | self.has_type_flags(TypeFlags::HAS_TY_CLOSURE) | |
1a4d82fc | 7050 | } |
c1a9b12d SL |
7051 | fn has_erasable_regions(&self) -> bool { |
7052 | self.has_type_flags(TypeFlags::HAS_RE_EARLY_BOUND | | |
7053 | TypeFlags::HAS_RE_INFER | | |
7054 | TypeFlags::HAS_FREE_REGIONS) | |
223e47cc | 7055 | } |
c1a9b12d SL |
7056 | /// Indicates whether this value references only 'global' |
7057 | /// types/lifetimes that are the same regardless of what fn we are | |
7058 | /// in. This is used for caching. Errs on the side of returning | |
7059 | /// false. | |
7060 | fn is_global(&self) -> bool { | |
7061 | !self.has_type_flags(TypeFlags::HAS_LOCAL_NAMES) | |
223e47cc LB |
7062 | } |
7063 | } | |
7064 | ||
c1a9b12d SL |
7065 | impl<'tcx,T:HasTypeFlags> HasTypeFlags for Vec<T> { |
7066 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7067 | self[..].has_type_flags(flags) | |
223e47cc LB |
7068 | } |
7069 | } | |
7070 | ||
c1a9b12d SL |
7071 | impl<'tcx,T:HasTypeFlags> HasTypeFlags for [T] { |
7072 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7073 | self.iter().any(|p| p.has_type_flags(flags)) | |
223e47cc LB |
7074 | } |
7075 | } | |
7076 | ||
c1a9b12d SL |
7077 | impl<'tcx,T:HasTypeFlags> HasTypeFlags for VecPerParamSpace<T> { |
7078 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7079 | self.iter().any(|p| p.has_type_flags(flags)) | |
1a4d82fc JJ |
7080 | } |
7081 | } | |
223e47cc | 7082 | |
c1a9b12d SL |
7083 | impl<'tcx> HasTypeFlags for ClosureTy<'tcx> { |
7084 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7085 | self.sig.has_type_flags(flags) | |
223e47cc | 7086 | } |
1a4d82fc | 7087 | } |
223e47cc | 7088 | |
c1a9b12d SL |
7089 | impl<'tcx> HasTypeFlags for ClosureUpvar<'tcx> { |
7090 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7091 | self.ty.has_type_flags(flags) | |
1a4d82fc JJ |
7092 | } |
7093 | } | |
223e47cc | 7094 | |
c1a9b12d SL |
7095 | impl<'tcx> HasTypeFlags for ty::InstantiatedPredicates<'tcx> { |
7096 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7097 | self.predicates.has_type_flags(flags) | |
1a4d82fc JJ |
7098 | } |
7099 | } | |
223e47cc | 7100 | |
c1a9b12d SL |
7101 | impl<'tcx> HasTypeFlags for Predicate<'tcx> { |
7102 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7103 | match *self { | |
7104 | Predicate::Trait(ref data) => data.has_type_flags(flags), | |
7105 | Predicate::Equate(ref data) => data.has_type_flags(flags), | |
7106 | Predicate::RegionOutlives(ref data) => data.has_type_flags(flags), | |
7107 | Predicate::TypeOutlives(ref data) => data.has_type_flags(flags), | |
7108 | Predicate::Projection(ref data) => data.has_type_flags(flags), | |
7109 | } | |
1a4d82fc | 7110 | } |
223e47cc LB |
7111 | } |
7112 | ||
c1a9b12d SL |
7113 | impl<'tcx> HasTypeFlags for TraitPredicate<'tcx> { |
7114 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7115 | self.trait_ref.has_type_flags(flags) | |
1a4d82fc | 7116 | } |
223e47cc LB |
7117 | } |
7118 | ||
c1a9b12d SL |
7119 | impl<'tcx> HasTypeFlags for EquatePredicate<'tcx> { |
7120 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7121 | self.0.has_type_flags(flags) || self.1.has_type_flags(flags) | |
223e47cc | 7122 | } |
1a4d82fc JJ |
7123 | } |
7124 | ||
c1a9b12d SL |
7125 | impl HasTypeFlags for Region { |
7126 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7127 | if flags.intersects(TypeFlags::HAS_LOCAL_NAMES) { | |
7128 | // does this represent a region that cannot be named in a global | |
7129 | // way? used in fulfillment caching. | |
7130 | match *self { | |
7131 | ty::ReStatic | ty::ReEmpty => {} | |
7132 | _ => return true | |
7133 | } | |
7134 | } | |
7135 | if flags.intersects(TypeFlags::HAS_RE_INFER) { | |
7136 | if let ty::ReInfer(_) = *self { | |
7137 | return true; | |
7138 | } | |
223e47cc | 7139 | } |
c1a9b12d | 7140 | false |
223e47cc | 7141 | } |
1a4d82fc | 7142 | } |
223e47cc | 7143 | |
c1a9b12d SL |
7144 | impl<T:HasTypeFlags,U:HasTypeFlags> HasTypeFlags for OutlivesPredicate<T,U> { |
7145 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7146 | self.0.has_type_flags(flags) || self.1.has_type_flags(flags) | |
223e47cc | 7147 | } |
1a4d82fc | 7148 | } |
223e47cc | 7149 | |
c1a9b12d SL |
7150 | impl<'tcx> HasTypeFlags for ProjectionPredicate<'tcx> { |
7151 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7152 | self.projection_ty.has_type_flags(flags) || self.ty.has_type_flags(flags) | |
1a4d82fc JJ |
7153 | } |
7154 | } | |
223e47cc | 7155 | |
c1a9b12d SL |
7156 | impl<'tcx> HasTypeFlags for ProjectionTy<'tcx> { |
7157 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7158 | self.trait_ref.has_type_flags(flags) | |
1a4d82fc JJ |
7159 | } |
7160 | } | |
223e47cc | 7161 | |
c1a9b12d SL |
7162 | impl<'tcx> HasTypeFlags for Ty<'tcx> { |
7163 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7164 | self.flags.get().intersects(flags) | |
7165 | } | |
1a4d82fc | 7166 | } |
223e47cc | 7167 | |
c1a9b12d SL |
7168 | impl<'tcx> HasTypeFlags for TraitRef<'tcx> { |
7169 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7170 | self.substs.has_type_flags(flags) | |
1a4d82fc JJ |
7171 | } |
7172 | } | |
223e47cc | 7173 | |
c1a9b12d SL |
7174 | impl<'tcx> HasTypeFlags for subst::Substs<'tcx> { |
7175 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7176 | self.types.has_type_flags(flags) || match self.regions { | |
7177 | subst::ErasedRegions => false, | |
7178 | subst::NonerasedRegions(ref r) => r.has_type_flags(flags) | |
7179 | } | |
1a4d82fc | 7180 | } |
223e47cc LB |
7181 | } |
7182 | ||
c1a9b12d SL |
7183 | impl<'tcx,T> HasTypeFlags for Option<T> |
7184 | where T : HasTypeFlags | |
7185 | { | |
7186 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7187 | self.iter().any(|t| t.has_type_flags(flags)) | |
223e47cc LB |
7188 | } |
7189 | } | |
7190 | ||
c1a9b12d SL |
7191 | impl<'tcx,T> HasTypeFlags for Rc<T> |
7192 | where T : HasTypeFlags | |
7193 | { | |
7194 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7195 | (**self).has_type_flags(flags) | |
223e47cc LB |
7196 | } |
7197 | } | |
7198 | ||
c1a9b12d SL |
7199 | impl<'tcx,T> HasTypeFlags for Box<T> |
7200 | where T : HasTypeFlags | |
7201 | { | |
7202 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7203 | (**self).has_type_flags(flags) | |
1a4d82fc JJ |
7204 | } |
7205 | } | |
223e47cc | 7206 | |
c1a9b12d SL |
7207 | impl<T> HasTypeFlags for Binder<T> |
7208 | where T : HasTypeFlags | |
7209 | { | |
7210 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7211 | self.0.has_type_flags(flags) | |
1a4d82fc JJ |
7212 | } |
7213 | } | |
970d7e83 | 7214 | |
c1a9b12d SL |
7215 | impl<'tcx> HasTypeFlags for FnOutput<'tcx> { |
7216 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
1a4d82fc | 7217 | match *self { |
c1a9b12d SL |
7218 | FnConverging(t) => t.has_type_flags(flags), |
7219 | FnDiverging => false, | |
970d7e83 | 7220 | } |
223e47cc LB |
7221 | } |
7222 | } | |
7223 | ||
c1a9b12d SL |
7224 | impl<'tcx> HasTypeFlags for FnSig<'tcx> { |
7225 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7226 | self.inputs.iter().any(|t| t.has_type_flags(flags)) || | |
7227 | self.output.has_type_flags(flags) | |
223e47cc | 7228 | } |
223e47cc LB |
7229 | } |
7230 | ||
c1a9b12d SL |
7231 | impl<'tcx> HasTypeFlags for Field<'tcx> { |
7232 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7233 | self.mt.ty.has_type_flags(flags) | |
223e47cc LB |
7234 | } |
7235 | } | |
7236 | ||
c1a9b12d SL |
7237 | impl<'tcx> HasTypeFlags for BareFnTy<'tcx> { |
7238 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7239 | self.sig.has_type_flags(flags) | |
7240 | } | |
7241 | } | |
7242 | ||
7243 | impl<'tcx> HasTypeFlags for ClosureSubsts<'tcx> { | |
7244 | fn has_type_flags(&self, flags: TypeFlags) -> bool { | |
7245 | self.func_substs.has_type_flags(flags) || | |
7246 | self.upvar_tys.iter().any(|t| t.has_type_flags(flags)) | |
1a4d82fc | 7247 | } |
970d7e83 LB |
7248 | } |
7249 | ||
62682a34 SL |
7250 | impl<'tcx> fmt::Debug for ClosureTy<'tcx> { |
7251 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7252 | write!(f, "ClosureTy({},{:?},{})", | |
7253 | self.unsafety, | |
7254 | self.sig, | |
7255 | self.abi) | |
1a4d82fc | 7256 | } |
970d7e83 LB |
7257 | } |
7258 | ||
62682a34 SL |
7259 | impl<'tcx> fmt::Debug for ClosureUpvar<'tcx> { |
7260 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7261 | write!(f, "ClosureUpvar({:?},{:?})", | |
7262 | self.def, | |
7263 | self.ty) | |
1a4d82fc JJ |
7264 | } |
7265 | } | |
7266 | ||
c1a9b12d | 7267 | impl<'tcx> fmt::Debug for Field<'tcx> { |
62682a34 SL |
7268 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
7269 | write!(f, "field({},{})", self.name, self.mt) | |
1a4d82fc | 7270 | } |
970d7e83 | 7271 | } |
85aaf69f | 7272 | |
62682a34 SL |
7273 | impl<'a, 'tcx> fmt::Debug for ParameterEnvironment<'a, 'tcx> { |
7274 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7275 | write!(f, "ParameterEnvironment(\ | |
7276 | free_substs={:?}, \ | |
7277 | implicit_region_bound={:?}, \ | |
7278 | caller_bounds={:?})", | |
7279 | self.free_substs, | |
7280 | self.implicit_region_bound, | |
7281 | self.caller_bounds) | |
85aaf69f SL |
7282 | } |
7283 | } | |
7284 | ||
62682a34 SL |
7285 | impl<'tcx> fmt::Debug for ObjectLifetimeDefault { |
7286 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
85aaf69f | 7287 | match *self { |
62682a34 SL |
7288 | ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"), |
7289 | ObjectLifetimeDefault::BaseDefault => write!(f, "BaseDefault"), | |
7290 | ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r), | |
85aaf69f SL |
7291 | } |
7292 | } | |
7293 | } |