]>
Commit | Line | Data |
---|---|---|
dc9dc135 | 1 | //! HIR datatypes. See the [rustc guide] for more info. |
0731742a XL |
2 | //! |
3 | //! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html | |
e9174d1e | 4 | |
e9174d1e SL |
5 | pub use self::BlockCheckMode::*; |
6 | pub use self::CaptureClause::*; | |
e9174d1e | 7 | pub use self::FunctionRetTy::*; |
e9174d1e | 8 | pub use self::Mutability::*; |
e9174d1e | 9 | pub use self::PrimTy::*; |
e9174d1e SL |
10 | pub use self::UnOp::*; |
11 | pub use self::UnsafeSource::*; | |
e9174d1e | 12 | |
48663c56 | 13 | use crate::hir::def::{Res, DefKind}; |
9fa01778 | 14 | use crate::hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; |
416331ca | 15 | use crate::hir::ptr::P; |
9fa01778 | 16 | use crate::mir::mono::Linkage; |
e1599b0c XL |
17 | use crate::ty::AdtKind; |
18 | use crate::ty::query::Providers; | |
19 | use crate::util::nodemap::{NodeMap, FxHashSet}; | |
54a0048b | 20 | |
9fa01778 | 21 | use errors::FatalError; |
e74abb32 | 22 | use syntax_pos::{Span, DUMMY_SP, MultiSpan}; |
9fa01778 | 23 | use syntax::source_map::Spanned; |
532ac7d7 | 24 | use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect}; |
48663c56 | 25 | use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; |
9fa01778 | 26 | use syntax::attr::{InlineAttr, OptimizeAttr}; |
dc9dc135 | 27 | use syntax::symbol::{Symbol, kw}; |
8bb4bdeb | 28 | use syntax::tokenstream::TokenStream; |
2c00a5a8 | 29 | use syntax::util::parser::ExprPrecedence; |
e1599b0c | 30 | use rustc_target::spec::abi::Abi; |
532ac7d7 | 31 | use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; |
b7449926 | 32 | use rustc_data_structures::thin_vec::ThinVec; |
532ac7d7 | 33 | use rustc_macros::HashStable; |
416331ca | 34 | use rustc_serialize::{self, Encoder, Encodable, Decoder, Decodable}; |
0731742a | 35 | use std::collections::{BTreeSet, BTreeMap}; |
e9174d1e | 36 | use std::fmt; |
48663c56 | 37 | use smallvec::SmallVec; |
92a42be0 | 38 | |
3b2f2976 | 39 | /// HIR doesn't commit to a concrete storage type and has its own alias for a vector. |
9cc50fc6 SL |
40 | /// It can be `Vec`, `P<[T]>` or potentially `Box<[T]>`, or some other container with similar |
41 | /// behavior. Unlike AST, HIR is mostly a static structure, so we can use an owned slice instead | |
42 | /// of `Vec` to avoid keeping extra capacity. | |
43 | pub type HirVec<T> = P<[T]>; | |
44 | ||
45 | macro_rules! hir_vec { | |
46 | ($elem:expr; $n:expr) => ( | |
47 | $crate::hir::HirVec::from(vec![$elem; $n]) | |
48 | ); | |
49 | ($($x:expr),*) => ( | |
50 | $crate::hir::HirVec::from(vec![$($x),*]) | |
51 | ); | |
9cc50fc6 SL |
52 | } |
53 | ||
54a0048b SL |
54 | pub mod check_attr; |
55 | pub mod def; | |
56 | pub mod def_id; | |
54a0048b | 57 | pub mod intravisit; |
476ff2be | 58 | pub mod itemlikevisit; |
54a0048b SL |
59 | pub mod lowering; |
60 | pub mod map; | |
61 | pub mod pat_util; | |
62 | pub mod print; | |
416331ca | 63 | pub mod ptr; |
dc9dc135 | 64 | pub mod upvars; |
54a0048b | 65 | |
9fa01778 XL |
66 | /// Uniquely identifies a node in the HIR of the current crate. It is |
67 | /// composed of the `owner`, which is the `DefIndex` of the directly enclosing | |
68 | /// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"), | |
cc61c64b XL |
69 | /// and the `local_id` which is unique within the given owner. |
70 | /// | |
71 | /// This two-level structure makes for more stable values: One can move an item | |
72 | /// around within the source code, or add or remove stuff before it, without | |
9fa01778 | 73 | /// the `local_id` part of the `HirId` changing, which is a very useful property in |
cc61c64b XL |
74 | /// incremental compilation where we have to persist things through changes to |
75 | /// the code base. | |
9fa01778 | 76 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] |
cc61c64b XL |
77 | pub struct HirId { |
78 | pub owner: DefIndex, | |
79 | pub local_id: ItemLocalId, | |
80 | } | |
81 | ||
ff7c6d11 XL |
82 | impl HirId { |
83 | pub fn owner_def_id(self) -> DefId { | |
84 | DefId::local(self.owner) | |
85 | } | |
86 | ||
87 | pub fn owner_local_def_id(self) -> LocalDefId { | |
88 | LocalDefId::from_def_id(DefId::local(self.owner)) | |
89 | } | |
90 | } | |
91 | ||
416331ca | 92 | impl rustc_serialize::UseSpecializedEncodable for HirId { |
abe05a73 XL |
93 | fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { |
94 | let HirId { | |
95 | owner, | |
96 | local_id, | |
97 | } = *self; | |
98 | ||
99 | owner.encode(s)?; | |
e1599b0c XL |
100 | local_id.encode(s)?; |
101 | Ok(()) | |
abe05a73 XL |
102 | } |
103 | } | |
104 | ||
416331ca | 105 | impl rustc_serialize::UseSpecializedDecodable for HirId { |
abe05a73 XL |
106 | fn default_decode<D: Decoder>(d: &mut D) -> Result<HirId, D::Error> { |
107 | let owner = DefIndex::decode(d)?; | |
108 | let local_id = ItemLocalId::decode(d)?; | |
109 | ||
110 | Ok(HirId { | |
111 | owner, | |
112 | local_id | |
113 | }) | |
114 | } | |
115 | } | |
116 | ||
532ac7d7 XL |
117 | impl fmt::Display for HirId { |
118 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
119 | write!(f, "{:?}", self) | |
120 | } | |
121 | } | |
122 | ||
e1599b0c | 123 | // Hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module. |
a1dfa0c6 | 124 | mod item_local_id_inner { |
e74abb32 | 125 | use rustc_index::vec::Idx; |
532ac7d7 | 126 | use rustc_macros::HashStable; |
e74abb32 | 127 | rustc_index::newtype_index! { |
dc9dc135 XL |
128 | /// An `ItemLocalId` uniquely identifies something within a given "item-like"; |
129 | /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no | |
532ac7d7 XL |
130 | /// guarantee that the numerical value of a given `ItemLocalId` corresponds to |
131 | /// the node's position within the owning item in any way, but there is a | |
132 | /// guarantee that the `LocalItemId`s within an owner occupy a dense range of | |
133 | /// integers starting at zero, so a mapping that maps all or most nodes within | |
48663c56 | 134 | /// an "item-like" to something else can be implemented by a `Vec` instead of a |
532ac7d7 XL |
135 | /// tree or hash map. |
136 | pub struct ItemLocalId { | |
137 | derive [HashStable] | |
138 | } | |
cc61c64b XL |
139 | } |
140 | } | |
141 | ||
a1dfa0c6 | 142 | pub use self::item_local_id_inner::ItemLocalId; |
cc61c64b | 143 | |
9fa01778 | 144 | /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`. |
cc61c64b XL |
145 | pub const CRATE_HIR_ID: HirId = HirId { |
146 | owner: CRATE_DEF_INDEX, | |
a1dfa0c6 | 147 | local_id: ItemLocalId::from_u32_const(0) |
cc61c64b XL |
148 | }; |
149 | ||
150 | pub const DUMMY_HIR_ID: HirId = HirId { | |
151 | owner: CRATE_DEF_INDEX, | |
3b2f2976 | 152 | local_id: DUMMY_ITEM_LOCAL_ID, |
cc61c64b XL |
153 | }; |
154 | ||
a1dfa0c6 | 155 | pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; |
3b2f2976 | 156 | |
dc9dc135 | 157 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] |
e9174d1e | 158 | pub struct Lifetime { |
9fa01778 | 159 | pub hir_id: HirId, |
e9174d1e | 160 | pub span: Span, |
32a655c1 | 161 | |
9fa01778 | 162 | /// Either "`'a`", referring to a named lifetime definition, |
dc9dc135 | 163 | /// or "``" (i.e., `kw::Invalid`), for elision placeholders. |
32a655c1 SL |
164 | /// |
165 | /// HIR lowering inserts these placeholders in type paths that | |
166 | /// refer to type definitions needing lifetime parameters, | |
167 | /// `&T` and `&mut T`, and trait objects without `... + 'a`. | |
ea8adc8c XL |
168 | pub name: LifetimeName, |
169 | } | |
170 | ||
532ac7d7 | 171 | #[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy, HashStable)] |
8faf50e0 XL |
172 | pub enum ParamName { |
173 | /// Some user-given name like `T` or `'x`. | |
174 | Plain(Ident), | |
0531ce1d | 175 | |
9fa01778 XL |
176 | /// Synthetic name generated when user elided a lifetime in an impl header. |
177 | /// | |
178 | /// E.g., the lifetimes in cases like these: | |
0531ce1d XL |
179 | /// |
180 | /// impl Foo for &u32 | |
181 | /// impl Foo<'_> for u32 | |
182 | /// | |
183 | /// in that case, we rewrite to | |
184 | /// | |
185 | /// impl<'f> Foo for &'f u32 | |
186 | /// impl<'f> Foo<'f> for u32 | |
187 | /// | |
188 | /// where `'f` is something like `Fresh(0)`. The indices are | |
189 | /// unique per impl, but not necessarily continuous. | |
190 | Fresh(usize), | |
0bf4aa26 XL |
191 | |
192 | /// Indicates an illegal name was given and an error has been | |
e1599b0c | 193 | /// reported (so we should squelch other derived errors). Occurs |
9fa01778 | 194 | /// when, e.g., `'_` is used in the wrong place. |
0bf4aa26 | 195 | Error, |
8faf50e0 XL |
196 | } |
197 | ||
198 | impl ParamName { | |
199 | pub fn ident(&self) -> Ident { | |
200 | match *self { | |
201 | ParamName::Plain(ident) => ident, | |
dc9dc135 | 202 | ParamName::Fresh(_) | |
e1599b0c | 203 | ParamName::Error => Ident::with_dummy_span(kw::UnderscoreLifetime), |
8faf50e0 XL |
204 | } |
205 | } | |
206 | ||
207 | pub fn modern(&self) -> ParamName { | |
208 | match *self { | |
209 | ParamName::Plain(ident) => ParamName::Plain(ident.modern()), | |
210 | param_name => param_name, | |
211 | } | |
212 | } | |
213 | } | |
214 | ||
532ac7d7 | 215 | #[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy, HashStable)] |
8faf50e0 XL |
216 | pub enum LifetimeName { |
217 | /// User-given names or fresh (synthetic) names. | |
218 | Param(ParamName), | |
219 | ||
9fa01778 | 220 | /// User wrote nothing (e.g., the lifetime in `&u32`). |
8faf50e0 XL |
221 | Implicit, |
222 | ||
e1599b0c XL |
223 | /// Implicit lifetime in a context like `dyn Foo`. This is |
224 | /// distinguished from implicit lifetimes elsewhere because the | |
225 | /// lifetime that they default to must appear elsewhere within the | |
226 | /// enclosing type. This means that, in an `impl Trait` context, we | |
227 | /// don't have to create a parameter for them. That is, `impl | |
228 | /// Trait<Item = &u32>` expands to an opaque type like `type | |
229 | /// Foo<'a> = impl Trait<Item = &'a u32>`, but `impl Trait<item = | |
230 | /// dyn Bar>` expands to `type Foo = impl Trait<Item = dyn Bar + | |
231 | /// 'static>`. The latter uses `ImplicitObjectLifetimeDefault` so | |
232 | /// that surrounding code knows not to create a lifetime | |
233 | /// parameter. | |
234 | ImplicitObjectLifetimeDefault, | |
235 | ||
0bf4aa26 XL |
236 | /// Indicates an error during lowering (usually `'_` in wrong place) |
237 | /// that was already reported. | |
238 | Error, | |
239 | ||
9fa01778 | 240 | /// User wrote specifies `'_`. |
8faf50e0 | 241 | Underscore, |
0531ce1d | 242 | |
9fa01778 | 243 | /// User wrote `'static`. |
ea8adc8c | 244 | Static, |
ea8adc8c XL |
245 | } |
246 | ||
247 | impl LifetimeName { | |
8faf50e0 XL |
248 | pub fn ident(&self) -> Ident { |
249 | match *self { | |
e1599b0c XL |
250 | LifetimeName::ImplicitObjectLifetimeDefault |
251 | | LifetimeName::Implicit | |
252 | | LifetimeName::Error => Ident::invalid(), | |
253 | LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), | |
254 | LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), | |
8faf50e0 XL |
255 | LifetimeName::Param(param_name) => param_name.ident(), |
256 | } | |
257 | } | |
258 | ||
259 | pub fn is_elided(&self) -> bool { | |
260 | match self { | |
e1599b0c XL |
261 | LifetimeName::ImplicitObjectLifetimeDefault |
262 | | LifetimeName::Implicit | |
263 | | LifetimeName::Underscore => true, | |
8faf50e0 XL |
264 | |
265 | // It might seem surprising that `Fresh(_)` counts as | |
266 | // *not* elided -- but this is because, as far as the code | |
267 | // in the compiler is concerned -- `Fresh(_)` variants act | |
268 | // equivalently to "some fresh name". They correspond to | |
269 | // early-bound regions on an impl, in other words. | |
0bf4aa26 | 270 | LifetimeName::Error | LifetimeName::Param(_) | LifetimeName::Static => false, |
8faf50e0 XL |
271 | } |
272 | } | |
273 | ||
274 | fn is_static(&self) -> bool { | |
275 | self == &LifetimeName::Static | |
276 | } | |
277 | ||
278 | pub fn modern(&self) -> LifetimeName { | |
ea8adc8c | 279 | match *self { |
8faf50e0 XL |
280 | LifetimeName::Param(param_name) => LifetimeName::Param(param_name.modern()), |
281 | lifetime_name => lifetime_name, | |
ea8adc8c XL |
282 | } |
283 | } | |
e9174d1e SL |
284 | } |
285 | ||
8faf50e0 | 286 | impl fmt::Display for Lifetime { |
0bf4aa26 | 287 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
8faf50e0 XL |
288 | self.name.ident().fmt(f) |
289 | } | |
290 | } | |
291 | ||
e9174d1e | 292 | impl fmt::Debug for Lifetime { |
0bf4aa26 | 293 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
b039eaaf SL |
294 | write!(f, |
295 | "lifetime({}: {})", | |
532ac7d7 | 296 | self.hir_id, |
32a655c1 SL |
297 | print::to_string(print::NO_ANN, |s| s.print_lifetime(self))) |
298 | } | |
299 | } | |
300 | ||
301 | impl Lifetime { | |
302 | pub fn is_elided(&self) -> bool { | |
8faf50e0 | 303 | self.name.is_elided() |
e9174d1e | 304 | } |
cc61c64b XL |
305 | |
306 | pub fn is_static(&self) -> bool { | |
8faf50e0 | 307 | self.name.is_static() |
cc61c64b | 308 | } |
e9174d1e SL |
309 | } |
310 | ||
9fa01778 | 311 | /// A `Path` is essentially Rust's notion of a name; for instance, |
2c00a5a8 | 312 | /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, |
e9174d1e | 313 | /// along with a bunch of supporting information. |
dc9dc135 | 314 | #[derive(RustcEncodable, RustcDecodable, HashStable)] |
e9174d1e SL |
315 | pub struct Path { |
316 | pub span: Span, | |
48663c56 XL |
317 | /// The resolution for the path. |
318 | pub res: Res, | |
e9174d1e | 319 | /// The segments in the path: the things separated by `::`. |
9cc50fc6 | 320 | pub segments: HirVec<PathSegment>, |
e9174d1e SL |
321 | } |
322 | ||
32a655c1 SL |
323 | impl Path { |
324 | pub fn is_global(&self) -> bool { | |
dc9dc135 | 325 | !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot |
e9174d1e SL |
326 | } |
327 | } | |
328 | ||
32a655c1 | 329 | impl fmt::Debug for Path { |
0bf4aa26 | 330 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 331 | write!(f, "path({})", self) |
ff7c6d11 XL |
332 | } |
333 | } | |
334 | ||
335 | impl fmt::Display for Path { | |
0bf4aa26 | 336 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
ff7c6d11 | 337 | write!(f, "{}", print::to_string(print::NO_ANN, |s| s.print_path(self, false))) |
54a0048b SL |
338 | } |
339 | } | |
340 | ||
e9174d1e SL |
341 | /// A segment of a path: an identifier, an optional lifetime, and a set of |
342 | /// types. | |
dc9dc135 | 343 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
344 | pub struct PathSegment { |
345 | /// The identifier portion of this path segment. | |
532ac7d7 | 346 | #[stable_hasher(project(name))] |
8faf50e0 | 347 | pub ident: Ident, |
48663c56 | 348 | // `id` and `res` are optional. We currently only use these in save-analysis, |
13cf67c4 XL |
349 | // any path segments without these will not have save-analysis info and |
350 | // therefore will not have 'jump to def' in IDEs, but otherwise will not be | |
351 | // affected. (In general, we don't bother to get the defs for synthesized | |
352 | // segments, only for segments which have come from the AST). | |
9fa01778 | 353 | pub hir_id: Option<HirId>, |
48663c56 | 354 | pub res: Option<Res>, |
e9174d1e SL |
355 | |
356 | /// Type/lifetime parameters attached to this path. They come in | |
357 | /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that | |
358 | /// this is more than just simple syntactic sugar; the use of | |
359 | /// parens affects the region binding rules, so we preserve the | |
360 | /// distinction. | |
8faf50e0 | 361 | pub args: Option<P<GenericArgs>>, |
ea8adc8c XL |
362 | |
363 | /// Whether to infer remaining type parameters, if any. | |
364 | /// This only applies to expression and pattern paths, and | |
365 | /// out of those only the segments with no type parameters | |
0731742a | 366 | /// to begin with, e.g., `Vec::new` is `<Vec<..>>::new::<..>`. |
dc9dc135 | 367 | pub infer_args: bool, |
e9174d1e SL |
368 | } |
369 | ||
476ff2be | 370 | impl PathSegment { |
9fa01778 | 371 | /// Converts an identifier to the corresponding segment. |
8faf50e0 | 372 | pub fn from_ident(ident: Ident) -> PathSegment { |
476ff2be | 373 | PathSegment { |
8faf50e0 | 374 | ident, |
9fa01778 | 375 | hir_id: None, |
48663c56 | 376 | res: None, |
dc9dc135 | 377 | infer_args: true, |
8faf50e0 | 378 | args: None, |
476ff2be SL |
379 | } |
380 | } | |
ea8adc8c | 381 | |
13cf67c4 XL |
382 | pub fn new( |
383 | ident: Ident, | |
9fa01778 | 384 | hir_id: Option<HirId>, |
48663c56 | 385 | res: Option<Res>, |
13cf67c4 | 386 | args: GenericArgs, |
dc9dc135 | 387 | infer_args: bool, |
13cf67c4 | 388 | ) -> Self { |
ea8adc8c | 389 | PathSegment { |
8faf50e0 | 390 | ident, |
9fa01778 | 391 | hir_id, |
48663c56 | 392 | res, |
dc9dc135 | 393 | infer_args, |
8faf50e0 | 394 | args: if args.is_empty() { |
ea8adc8c XL |
395 | None |
396 | } else { | |
8faf50e0 | 397 | Some(P(args)) |
ea8adc8c XL |
398 | } |
399 | } | |
400 | } | |
401 | ||
dc9dc135 XL |
402 | pub fn generic_args(&self) -> &GenericArgs { |
403 | if let Some(ref args) = self.args { | |
404 | args | |
ea8adc8c | 405 | } else { |
dc9dc135 XL |
406 | const DUMMY: &GenericArgs = &GenericArgs::none(); |
407 | DUMMY | |
408 | } | |
ea8adc8c | 409 | } |
476ff2be SL |
410 | } |
411 | ||
dc9dc135 | 412 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
9fa01778 XL |
413 | pub struct ConstArg { |
414 | pub value: AnonConst, | |
415 | pub span: Span, | |
416 | } | |
417 | ||
dc9dc135 | 418 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 XL |
419 | pub enum GenericArg { |
420 | Lifetime(Lifetime), | |
421 | Type(Ty), | |
9fa01778 | 422 | Const(ConstArg), |
8faf50e0 XL |
423 | } |
424 | ||
425 | impl GenericArg { | |
426 | pub fn span(&self) -> Span { | |
427 | match self { | |
428 | GenericArg::Lifetime(l) => l.span, | |
429 | GenericArg::Type(t) => t.span, | |
9fa01778 | 430 | GenericArg::Const(c) => c.span, |
8faf50e0 XL |
431 | } |
432 | } | |
b7449926 | 433 | |
532ac7d7 | 434 | pub fn id(&self) -> HirId { |
b7449926 | 435 | match self { |
532ac7d7 XL |
436 | GenericArg::Lifetime(l) => l.hir_id, |
437 | GenericArg::Type(t) => t.hir_id, | |
438 | GenericArg::Const(c) => c.value.hir_id, | |
b7449926 XL |
439 | } |
440 | } | |
dc9dc135 XL |
441 | |
442 | pub fn is_const(&self) -> bool { | |
443 | match self { | |
444 | GenericArg::Const(_) => true, | |
445 | _ => false, | |
446 | } | |
447 | } | |
8faf50e0 XL |
448 | } |
449 | ||
dc9dc135 | 450 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 XL |
451 | pub struct GenericArgs { |
452 | /// The generic arguments for this path segment. | |
453 | pub args: HirVec<GenericArg>, | |
e9174d1e | 454 | /// Bindings (equality constraints) on associated types, if present. |
0731742a | 455 | /// E.g., `Foo<A = Bar>`. |
9cc50fc6 | 456 | pub bindings: HirVec<TypeBinding>, |
8faf50e0 | 457 | /// Were arguments written in parenthesized form `Fn(T) -> U`? |
3b2f2976 XL |
458 | /// This is required mostly for pretty-printing and diagnostics, |
459 | /// but also for changing lifetime elision rules to be "function-like". | |
460 | pub parenthesized: bool, | |
e9174d1e SL |
461 | } |
462 | ||
8faf50e0 | 463 | impl GenericArgs { |
dc9dc135 | 464 | pub const fn none() -> Self { |
3b2f2976 | 465 | Self { |
8faf50e0 | 466 | args: HirVec::new(), |
3b2f2976 XL |
467 | bindings: HirVec::new(), |
468 | parenthesized: false, | |
469 | } | |
470 | } | |
e9174d1e | 471 | |
ea8adc8c | 472 | pub fn is_empty(&self) -> bool { |
8faf50e0 | 473 | self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized |
ea8adc8c XL |
474 | } |
475 | ||
8faf50e0 | 476 | pub fn inputs(&self) -> &[Ty] { |
3b2f2976 | 477 | if self.parenthesized { |
8faf50e0 XL |
478 | for arg in &self.args { |
479 | match arg { | |
480 | GenericArg::Lifetime(_) => {} | |
481 | GenericArg::Type(ref ty) => { | |
e74abb32 | 482 | if let TyKind::Tup(ref tys) = ty.kind { |
8faf50e0 XL |
483 | return tys; |
484 | } | |
485 | break; | |
486 | } | |
9fa01778 | 487 | GenericArg::Const(_) => {} |
3b2f2976 XL |
488 | } |
489 | } | |
490 | } | |
8faf50e0 | 491 | bug!("GenericArgs::inputs: not a `Fn(T) -> U`"); |
3b2f2976 | 492 | } |
b7449926 XL |
493 | |
494 | pub fn own_counts(&self) -> GenericParamCount { | |
495 | // We could cache this as a property of `GenericParamCount`, but | |
496 | // the aim is to refactor this away entirely eventually and the | |
497 | // presence of this method will be a constant reminder. | |
498 | let mut own_counts: GenericParamCount = Default::default(); | |
499 | ||
500 | for arg in &self.args { | |
501 | match arg { | |
502 | GenericArg::Lifetime(_) => own_counts.lifetimes += 1, | |
503 | GenericArg::Type(_) => own_counts.types += 1, | |
9fa01778 | 504 | GenericArg::Const(_) => own_counts.consts += 1, |
b7449926 XL |
505 | }; |
506 | } | |
507 | ||
508 | own_counts | |
509 | } | |
e9174d1e SL |
510 | } |
511 | ||
8faf50e0 XL |
512 | /// A modifier on a bound, currently this is only used for `?Sized`, where the |
513 | /// modifier is `Maybe`. Negative bounds should also be handled here. | |
532ac7d7 | 514 | #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] |
8faf50e0 XL |
515 | pub enum TraitBoundModifier { |
516 | None, | |
517 | Maybe, | |
518 | } | |
519 | ||
e9174d1e | 520 | /// The AST represents all type param bounds as types. |
a1dfa0c6 XL |
521 | /// `typeck::collect::compute_bounds` matches these against |
522 | /// the "special" built-in traits (see `middle::lang_items`) and | |
523 | /// detects `Copy`, `Send` and `Sync`. | |
dc9dc135 | 524 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 XL |
525 | pub enum GenericBound { |
526 | Trait(PolyTraitRef, TraitBoundModifier), | |
527 | Outlives(Lifetime), | |
e9174d1e SL |
528 | } |
529 | ||
8faf50e0 | 530 | impl GenericBound { |
0531ce1d XL |
531 | pub fn span(&self) -> Span { |
532 | match self { | |
8faf50e0 XL |
533 | &GenericBound::Trait(ref t, ..) => t.span, |
534 | &GenericBound::Outlives(ref l) => l.span, | |
0531ce1d XL |
535 | } |
536 | } | |
537 | } | |
538 | ||
8faf50e0 | 539 | pub type GenericBounds = HirVec<GenericBound>; |
e9174d1e | 540 | |
532ac7d7 | 541 | #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
0bf4aa26 | 542 | pub enum LifetimeParamKind { |
0731742a XL |
543 | // Indicates that the lifetime definition was explicitly declared (e.g., in |
544 | // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`). | |
0bf4aa26 XL |
545 | Explicit, |
546 | ||
547 | // Indicates that the lifetime definition was synthetically added | |
0731742a XL |
548 | // as a result of an in-band lifetime usage (e.g., in |
549 | // `fn foo(x: &'a u8) -> &'a u8 { x }`). | |
0bf4aa26 XL |
550 | InBand, |
551 | ||
0731742a XL |
552 | // Indication that the lifetime was elided (e.g., in both cases in |
553 | // `fn foo(x: &u8) -> &'_ u8 { x }`). | |
0bf4aa26 XL |
554 | Elided, |
555 | ||
556 | // Indication that the lifetime name was somehow in error. | |
557 | Error, | |
558 | } | |
559 | ||
dc9dc135 | 560 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 | 561 | pub enum GenericParamKind { |
0731742a | 562 | /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). |
8faf50e0 | 563 | Lifetime { |
0bf4aa26 | 564 | kind: LifetimeParamKind, |
8faf50e0 XL |
565 | }, |
566 | Type { | |
567 | default: Option<P<Ty>>, | |
568 | synthetic: Option<SyntheticTyParamKind>, | |
9fa01778 XL |
569 | }, |
570 | Const { | |
571 | ty: P<Ty>, | |
8faf50e0 XL |
572 | } |
573 | } | |
e9174d1e | 574 | |
dc9dc135 | 575 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 | 576 | pub struct GenericParam { |
9fa01778 | 577 | pub hir_id: HirId, |
8faf50e0 XL |
578 | pub name: ParamName, |
579 | pub attrs: HirVec<Attribute>, | |
580 | pub bounds: GenericBounds, | |
b039eaaf | 581 | pub span: Span, |
c30ab7b3 | 582 | pub pure_wrt_drop: bool, |
8faf50e0 | 583 | pub kind: GenericParamKind, |
ff7c6d11 XL |
584 | } |
585 | ||
b7449926 | 586 | #[derive(Default)] |
8faf50e0 XL |
587 | pub struct GenericParamCount { |
588 | pub lifetimes: usize, | |
589 | pub types: usize, | |
9fa01778 | 590 | pub consts: usize, |
ff7c6d11 XL |
591 | } |
592 | ||
e9174d1e SL |
593 | /// Represents lifetimes and type parameters attached to a declaration |
594 | /// of a function, enum, trait, etc. | |
dc9dc135 | 595 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 596 | pub struct Generics { |
ff7c6d11 | 597 | pub params: HirVec<GenericParam>, |
e9174d1e | 598 | pub where_clause: WhereClause, |
9e0c209e | 599 | pub span: Span, |
e9174d1e SL |
600 | } |
601 | ||
602 | impl Generics { | |
dc9dc135 | 603 | pub const fn empty() -> Generics { |
54a0048b | 604 | Generics { |
ff7c6d11 | 605 | params: HirVec::new(), |
54a0048b | 606 | where_clause: WhereClause { |
54a0048b | 607 | predicates: HirVec::new(), |
dc9dc135 | 608 | span: DUMMY_SP, |
54a0048b | 609 | }, |
9e0c209e | 610 | span: DUMMY_SP, |
54a0048b SL |
611 | } |
612 | } | |
613 | ||
8faf50e0 XL |
614 | pub fn own_counts(&self) -> GenericParamCount { |
615 | // We could cache this as a property of `GenericParamCount`, but | |
616 | // the aim is to refactor this away entirely eventually and the | |
617 | // presence of this method will be a constant reminder. | |
b7449926 | 618 | let mut own_counts: GenericParamCount = Default::default(); |
c30ab7b3 | 619 | |
8faf50e0 XL |
620 | for param in &self.params { |
621 | match param.kind { | |
622 | GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1, | |
623 | GenericParamKind::Type { .. } => own_counts.types += 1, | |
9fa01778 | 624 | GenericParamKind::Const { .. } => own_counts.consts += 1, |
8faf50e0 | 625 | }; |
c30ab7b3 | 626 | } |
8faf50e0 XL |
627 | |
628 | own_counts | |
c30ab7b3 | 629 | } |
c30ab7b3 | 630 | |
e74abb32 | 631 | pub fn get_named(&self, name: Symbol) -> Option<&GenericParam> { |
ff7c6d11 | 632 | for param in &self.params { |
e74abb32 | 633 | if name == param.name.ident().name { |
8faf50e0 | 634 | return Some(param); |
c30ab7b3 SL |
635 | } |
636 | } | |
ff7c6d11 | 637 | None |
c30ab7b3 | 638 | } |
dc9dc135 XL |
639 | |
640 | pub fn spans(&self) -> MultiSpan { | |
641 | if self.params.is_empty() { | |
642 | self.span.into() | |
643 | } else { | |
644 | self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into() | |
645 | } | |
646 | } | |
c30ab7b3 SL |
647 | } |
648 | ||
9fa01778 XL |
649 | /// Synthetic type parameters are converted to another form during lowering; this allows |
650 | /// us to track the original form they had, and is useful for error messages. | |
532ac7d7 | 651 | #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] |
ea8adc8c XL |
652 | pub enum SyntheticTyParamKind { |
653 | ImplTrait | |
654 | } | |
655 | ||
9fa01778 | 656 | /// A where-clause in a definition. |
dc9dc135 | 657 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 658 | pub struct WhereClause { |
9cc50fc6 | 659 | pub predicates: HirVec<WherePredicate>, |
dc9dc135 XL |
660 | // Only valid if predicates isn't empty. |
661 | span: Span, | |
e9174d1e SL |
662 | } |
663 | ||
94b46f34 XL |
664 | impl WhereClause { |
665 | pub fn span(&self) -> Option<Span> { | |
dc9dc135 XL |
666 | if self.predicates.is_empty() { |
667 | None | |
668 | } else { | |
669 | Some(self.span) | |
670 | } | |
94b46f34 | 671 | } |
e74abb32 XL |
672 | |
673 | /// The `WhereClause` under normal circumstances points at either the predicates or the empty | |
674 | /// space where the `where` clause should be. Only of use for diagnostic suggestions. | |
675 | pub fn span_for_predicates_or_empty_place(&self) -> Span { | |
676 | self.span | |
677 | } | |
94b46f34 XL |
678 | } |
679 | ||
9fa01778 | 680 | /// A single predicate in a where-clause. |
dc9dc135 | 681 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 682 | pub enum WherePredicate { |
0731742a | 683 | /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). |
e9174d1e | 684 | BoundPredicate(WhereBoundPredicate), |
0731742a | 685 | /// A lifetime predicate (e.g., `'a: 'b + 'c`). |
e9174d1e | 686 | RegionPredicate(WhereRegionPredicate), |
0731742a | 687 | /// An equality predicate (unsupported). |
b039eaaf | 688 | EqPredicate(WhereEqPredicate), |
e9174d1e SL |
689 | } |
690 | ||
0531ce1d XL |
691 | impl WherePredicate { |
692 | pub fn span(&self) -> Span { | |
693 | match self { | |
694 | &WherePredicate::BoundPredicate(ref p) => p.span, | |
695 | &WherePredicate::RegionPredicate(ref p) => p.span, | |
696 | &WherePredicate::EqPredicate(ref p) => p.span, | |
697 | } | |
698 | } | |
699 | } | |
700 | ||
9fa01778 | 701 | /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). |
dc9dc135 | 702 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
703 | pub struct WhereBoundPredicate { |
704 | pub span: Span, | |
9fa01778 | 705 | /// Any generics from a `for` binding. |
ff7c6d11 | 706 | pub bound_generic_params: HirVec<GenericParam>, |
9fa01778 | 707 | /// The type being bounded. |
e9174d1e | 708 | pub bounded_ty: P<Ty>, |
9fa01778 | 709 | /// Trait and lifetime bounds (e.g., `Clone + Send + 'static`). |
8faf50e0 | 710 | pub bounds: GenericBounds, |
e9174d1e SL |
711 | } |
712 | ||
9fa01778 | 713 | /// A lifetime predicate (e.g., `'a: 'b + 'c`). |
dc9dc135 | 714 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
715 | pub struct WhereRegionPredicate { |
716 | pub span: Span, | |
717 | pub lifetime: Lifetime, | |
8faf50e0 | 718 | pub bounds: GenericBounds, |
e9174d1e SL |
719 | } |
720 | ||
9fa01778 | 721 | /// An equality predicate (e.g., `T = int`); currently unsupported. |
dc9dc135 | 722 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 723 | pub struct WhereEqPredicate { |
9fa01778 | 724 | pub hir_id: HirId, |
e9174d1e | 725 | pub span: Span, |
32a655c1 SL |
726 | pub lhs_ty: P<Ty>, |
727 | pub rhs_ty: P<Ty>, | |
e9174d1e SL |
728 | } |
729 | ||
dc9dc135 | 730 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
0731742a XL |
731 | pub struct ModuleItems { |
732 | // Use BTreeSets here so items are in the same order as in the | |
733 | // list of all items in Crate | |
532ac7d7 | 734 | pub items: BTreeSet<HirId>, |
0731742a XL |
735 | pub trait_items: BTreeSet<TraitItemId>, |
736 | pub impl_items: BTreeSet<ImplItemId>, | |
737 | } | |
738 | ||
ea8adc8c XL |
739 | /// The top-level data structure that stores the entire contents of |
740 | /// the crate currently being compiled. | |
741 | /// | |
0531ce1d | 742 | /// For more details, see the [rustc guide]. |
ff7c6d11 | 743 | /// |
a1dfa0c6 | 744 | /// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html |
dc9dc135 | 745 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
e9174d1e SL |
746 | pub struct Crate { |
747 | pub module: Mod, | |
9cc50fc6 | 748 | pub attrs: HirVec<Attribute>, |
e9174d1e | 749 | pub span: Span, |
9cc50fc6 | 750 | pub exported_macros: HirVec<MacroDef>, |
416331ca XL |
751 | // Attributes from non-exported macros, kept only for collecting the library feature list. |
752 | pub non_exported_macro_attrs: HirVec<Attribute>, | |
92a42be0 | 753 | |
e1599b0c | 754 | // N.B., we use a `BTreeMap` here so that `visit_all_items` iterates |
92a42be0 SL |
755 | // over the ids in increasing order. In principle it should not |
756 | // matter what order we visit things in, but in *practice* it | |
757 | // does, because it can affect the order in which errors are | |
758 | // detected, which in turn can make compile-fail tests yield | |
759 | // slightly different results. | |
532ac7d7 | 760 | pub items: BTreeMap<HirId, Item>, |
476ff2be | 761 | |
32a655c1 | 762 | pub trait_items: BTreeMap<TraitItemId, TraitItem>, |
476ff2be | 763 | pub impl_items: BTreeMap<ImplItemId, ImplItem>, |
8bb4bdeb | 764 | pub bodies: BTreeMap<BodyId, Body>, |
532ac7d7 | 765 | pub trait_impls: BTreeMap<DefId, Vec<HirId>>, |
8bb4bdeb XL |
766 | |
767 | /// A list of the body ids written out in the order in which they | |
768 | /// appear in the crate. If you're going to process all the bodies | |
769 | /// in the crate, you should iterate over this list rather than the keys | |
770 | /// of bodies. | |
771 | pub body_ids: Vec<BodyId>, | |
0731742a XL |
772 | |
773 | /// A list of modules written out in the order in which they | |
774 | /// appear in the crate. This includes the main crate module. | |
e74abb32 | 775 | pub modules: BTreeMap<HirId, ModuleItems>, |
92a42be0 SL |
776 | } |
777 | ||
778 | impl Crate { | |
532ac7d7 | 779 | pub fn item(&self, id: HirId) -> &Item { |
92a42be0 SL |
780 | &self.items[&id] |
781 | } | |
782 | ||
32a655c1 SL |
783 | pub fn trait_item(&self, id: TraitItemId) -> &TraitItem { |
784 | &self.trait_items[&id] | |
785 | } | |
786 | ||
476ff2be SL |
787 | pub fn impl_item(&self, id: ImplItemId) -> &ImplItem { |
788 | &self.impl_items[&id] | |
789 | } | |
790 | ||
3b2f2976 | 791 | /// Visits all items in the crate in some deterministic (but |
92a42be0 SL |
792 | /// unspecified) order. If you just need to process every item, |
793 | /// but don't care about nesting, this method is the best choice. | |
794 | /// | |
795 | /// If you do care about nesting -- usually because your algorithm | |
796 | /// follows lexical scoping rules -- then you want a different | |
797 | /// approach. You should override `visit_nested_item` in your | |
798 | /// visitor and then call `intravisit::walk_crate` instead. | |
476ff2be SL |
799 | pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V) |
800 | where V: itemlikevisit::ItemLikeVisitor<'hir> | |
54a0048b | 801 | { |
92a42be0 SL |
802 | for (_, item) in &self.items { |
803 | visitor.visit_item(item); | |
804 | } | |
476ff2be | 805 | |
32a655c1 SL |
806 | for (_, trait_item) in &self.trait_items { |
807 | visitor.visit_trait_item(trait_item); | |
808 | } | |
809 | ||
476ff2be SL |
810 | for (_, impl_item) in &self.impl_items { |
811 | visitor.visit_impl_item(impl_item); | |
812 | } | |
813 | } | |
814 | ||
9fa01778 | 815 | /// A parallel version of `visit_all_item_likes`. |
94b46f34 XL |
816 | pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V) |
817 | where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send | |
818 | { | |
9fa01778 | 819 | parallel!({ |
532ac7d7 | 820 | par_for_each_in(&self.items, |(_, item)| { |
9fa01778 | 821 | visitor.visit_item(item); |
94b46f34 | 822 | }); |
9fa01778 | 823 | }, { |
532ac7d7 | 824 | par_for_each_in(&self.trait_items, |(_, trait_item)| { |
9fa01778 | 825 | visitor.visit_trait_item(trait_item); |
94b46f34 | 826 | }); |
9fa01778 | 827 | }, { |
532ac7d7 | 828 | par_for_each_in(&self.impl_items, |(_, impl_item)| { |
9fa01778 | 829 | visitor.visit_impl_item(impl_item); |
94b46f34 XL |
830 | }); |
831 | }); | |
832 | } | |
833 | ||
32a655c1 SL |
834 | pub fn body(&self, id: BodyId) -> &Body { |
835 | &self.bodies[&id] | |
92a42be0 | 836 | } |
e9174d1e SL |
837 | } |
838 | ||
839 | /// A macro definition, in this crate or imported from another. | |
840 | /// | |
841 | /// Not parsed directly, but created on macro import or `macro_rules!` expansion. | |
dc9dc135 | 842 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 843 | pub struct MacroDef { |
b039eaaf | 844 | pub name: Name, |
7cac9316 | 845 | pub vis: Visibility, |
9cc50fc6 | 846 | pub attrs: HirVec<Attribute>, |
9fa01778 | 847 | pub hir_id: HirId, |
e9174d1e | 848 | pub span: Span, |
8bb4bdeb | 849 | pub body: TokenStream, |
7cac9316 | 850 | pub legacy: bool, |
e9174d1e SL |
851 | } |
852 | ||
532ac7d7 XL |
853 | /// A block of statements `{ .. }`, which may have a label (in this case the |
854 | /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of | |
855 | /// the `rules` being anything but `DefaultBlock`. | |
dc9dc135 | 856 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 857 | pub struct Block { |
9fa01778 | 858 | /// Statements in a block. |
9cc50fc6 | 859 | pub stmts: HirVec<Stmt>, |
e9174d1e | 860 | /// An expression at the end of the block |
9fa01778 | 861 | /// without a semicolon, if any. |
e9174d1e | 862 | pub expr: Option<P<Expr>>, |
532ac7d7 | 863 | #[stable_hasher(ignore)] |
3b2f2976 | 864 | pub hir_id: HirId, |
9fa01778 | 865 | /// Distinguishes between `unsafe { ... }` and `{ ... }`. |
e9174d1e SL |
866 | pub rules: BlockCheckMode, |
867 | pub span: Span, | |
cc61c64b | 868 | /// If true, then there may exist `break 'a` values that aim to |
94b46f34 | 869 | /// break out of this block early. |
e74abb32 | 870 | /// Used by `'label: {}` blocks and by `try {}` blocks. |
cc61c64b | 871 | pub targeted_by_break: bool, |
e9174d1e SL |
872 | } |
873 | ||
dc9dc135 | 874 | #[derive(RustcEncodable, RustcDecodable, HashStable)] |
e9174d1e | 875 | pub struct Pat { |
532ac7d7 | 876 | #[stable_hasher(ignore)] |
3b2f2976 | 877 | pub hir_id: HirId, |
e74abb32 | 878 | pub kind: PatKind, |
e9174d1e SL |
879 | pub span: Span, |
880 | } | |
881 | ||
882 | impl fmt::Debug for Pat { | |
0bf4aa26 | 883 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
532ac7d7 | 884 | write!(f, "pat({}: {})", self.hir_id, |
32a655c1 | 885 | print::to_string(print::NO_ANN, |s| s.print_pat(self))) |
54a0048b SL |
886 | } |
887 | } | |
888 | ||
889 | impl Pat { | |
890 | // FIXME(#19596) this is a workaround, but there should be a better way | |
e74abb32 | 891 | fn walk_short_(&self, it: &mut impl FnMut(&Pat) -> bool) -> bool { |
54a0048b SL |
892 | if !it(self) { |
893 | return false; | |
894 | } | |
895 | ||
e74abb32 XL |
896 | use PatKind::*; |
897 | match &self.kind { | |
898 | Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, | |
899 | Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it), | |
900 | Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), | |
901 | TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), | |
902 | Slice(before, slice, after) => { | |
b7449926 XL |
903 | before.iter() |
904 | .chain(slice.iter()) | |
905 | .chain(after.iter()) | |
e74abb32 | 906 | .all(|p| p.walk_short_(it)) |
54a0048b | 907 | } |
e74abb32 XL |
908 | } |
909 | } | |
910 | ||
911 | /// Walk the pattern in left-to-right order, | |
912 | /// short circuiting (with `.all(..)`) if `false` is returned. | |
913 | /// | |
914 | /// Note that when visiting e.g. `Tuple(ps)`, | |
915 | /// if visiting `ps[0]` returns `false`, | |
916 | /// then `ps[1]` will not be visited. | |
917 | pub fn walk_short(&self, mut it: impl FnMut(&Pat) -> bool) -> bool { | |
918 | self.walk_short_(&mut it) | |
919 | } | |
920 | ||
921 | // FIXME(#19596) this is a workaround, but there should be a better way | |
922 | fn walk_(&self, it: &mut impl FnMut(&Pat) -> bool) { | |
923 | if !it(self) { | |
924 | return; | |
925 | } | |
926 | ||
927 | use PatKind::*; | |
928 | match &self.kind { | |
929 | Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}, | |
930 | Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it), | |
931 | Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), | |
932 | TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), | |
933 | Slice(before, slice, after) => { | |
934 | before.iter() | |
935 | .chain(slice.iter()) | |
936 | .chain(after.iter()) | |
937 | .for_each(|p| p.walk_(it)) | |
54a0048b SL |
938 | } |
939 | } | |
940 | } | |
941 | ||
e74abb32 XL |
942 | /// Walk the pattern in left-to-right order. |
943 | /// | |
944 | /// If `it(pat)` returns `false`, the children are not visited. | |
945 | pub fn walk(&self, mut it: impl FnMut(&Pat) -> bool) { | |
54a0048b | 946 | self.walk_(&mut it) |
e9174d1e SL |
947 | } |
948 | } | |
949 | ||
9fa01778 | 950 | /// A single field in a struct pattern. |
e9174d1e SL |
951 | /// |
952 | /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` | |
953 | /// are treated the same as` x: x, y: ref y, z: ref mut z`, | |
9fa01778 | 954 | /// except `is_shorthand` is true. |
dc9dc135 | 955 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 956 | pub struct FieldPat { |
532ac7d7 | 957 | #[stable_hasher(ignore)] |
9fa01778 XL |
958 | pub hir_id: HirId, |
959 | /// The identifier for the field. | |
532ac7d7 | 960 | #[stable_hasher(project(name))] |
94b46f34 | 961 | pub ident: Ident, |
9fa01778 | 962 | /// The pattern the field is destructured to. |
e9174d1e SL |
963 | pub pat: P<Pat>, |
964 | pub is_shorthand: bool, | |
e1599b0c | 965 | pub span: Span, |
e9174d1e SL |
966 | } |
967 | ||
3b2f2976 XL |
968 | /// Explicit binding annotations given in the HIR for a binding. Note |
969 | /// that this is not the final binding *mode* that we infer after type | |
970 | /// inference. | |
dc9dc135 | 971 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
3b2f2976 | 972 | pub enum BindingAnnotation { |
b7449926 XL |
973 | /// No binding annotation given: this means that the final binding mode |
974 | /// will depend on whether we have skipped through a `&` reference | |
975 | /// when matching. For example, the `x` in `Some(x)` will have binding | |
976 | /// mode `None`; if you do `let Some(x) = &Some(22)`, it will | |
977 | /// ultimately be inferred to be by-reference. | |
978 | /// | |
979 | /// Note that implicit reference skipping is not implemented yet (#42640). | |
980 | Unannotated, | |
3b2f2976 | 981 | |
b7449926 XL |
982 | /// Annotated with `mut x` -- could be either ref or not, similar to `None`. |
983 | Mutable, | |
3b2f2976 | 984 | |
b7449926 XL |
985 | /// Annotated as `ref`, like `ref x` |
986 | Ref, | |
3b2f2976 | 987 | |
b7449926 XL |
988 | /// Annotated as `ref mut x`. |
989 | RefMut, | |
e9174d1e SL |
990 | } |
991 | ||
532ac7d7 | 992 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
32a655c1 SL |
993 | pub enum RangeEnd { |
994 | Included, | |
995 | Excluded, | |
996 | } | |
997 | ||
e74abb32 XL |
998 | impl fmt::Display for RangeEnd { |
999 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1000 | f.write_str(match self { | |
1001 | RangeEnd::Included => "..=", | |
1002 | RangeEnd::Excluded => "..", | |
1003 | }) | |
1004 | } | |
1005 | } | |
1006 | ||
dc9dc135 | 1007 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
7453a54e | 1008 | pub enum PatKind { |
9fa01778 | 1009 | /// Represents a wildcard pattern (i.e., `_`). |
7453a54e | 1010 | Wild, |
e9174d1e | 1011 | |
3157f602 | 1012 | /// A fresh binding `ref mut binding @ OPT_SUBPATTERN`. |
532ac7d7 | 1013 | /// The `HirId` is the canonical ID for the variable being bound, |
9fa01778 | 1014 | /// (e.g., in `Ok(x) | Err(x)`, both `x` use the same canonical ID), |
ea8adc8c | 1015 | /// which is the pattern ID of the first `x`. |
532ac7d7 | 1016 | Binding(BindingAnnotation, HirId, Ident, Option<P<Pat>>), |
e9174d1e | 1017 | |
9fa01778 | 1018 | /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). |
7453a54e | 1019 | /// The `bool` is `true` in the presence of a `..`. |
e1599b0c | 1020 | Struct(QPath, HirVec<FieldPat>, bool), |
7453a54e | 1021 | |
3157f602 XL |
1022 | /// A tuple struct/variant pattern `Variant(x, y, .., z)`. |
1023 | /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. | |
9fa01778 | 1024 | /// `0 <= position <= subpats.len()` |
476ff2be | 1025 | TupleStruct(QPath, HirVec<P<Pat>>, Option<usize>), |
7453a54e | 1026 | |
e1599b0c XL |
1027 | /// An or-pattern `A | B | C`. |
1028 | /// Invariant: `pats.len() >= 2`. | |
1029 | Or(HirVec<P<Pat>>), | |
1030 | ||
476ff2be SL |
1031 | /// A path pattern for an unit struct/variant or a (maybe-associated) constant. |
1032 | Path(QPath), | |
e9174d1e | 1033 | |
9fa01778 | 1034 | /// A tuple pattern (e.g., `(a, b)`). |
3157f602 | 1035 | /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. |
9fa01778 | 1036 | /// `0 <= position <= subpats.len()` |
3157f602 | 1037 | Tuple(HirVec<P<Pat>>, Option<usize>), |
9fa01778 XL |
1038 | |
1039 | /// A `box` pattern. | |
7453a54e | 1040 | Box(P<Pat>), |
9fa01778 XL |
1041 | |
1042 | /// A reference pattern (e.g., `&mut (a, b)`). | |
7453a54e | 1043 | Ref(P<Pat>, Mutability), |
9fa01778 XL |
1044 | |
1045 | /// A literal. | |
7453a54e | 1046 | Lit(P<Expr>), |
9fa01778 | 1047 | |
dc9dc135 | 1048 | /// A range pattern (e.g., `1..=2` or `1..2`). |
32a655c1 | 1049 | Range(P<Expr>, P<Expr>, RangeEnd), |
9fa01778 | 1050 | |
92a42be0 | 1051 | /// `[a, b, ..i, y, z]` is represented as: |
9fa01778 | 1052 | /// `PatKind::Slice(box [a, b], Some(i), box [y, z])`. |
c30ab7b3 | 1053 | Slice(HirVec<P<Pat>>, Option<P<Pat>>, HirVec<P<Pat>>), |
e9174d1e SL |
1054 | } |
1055 | ||
dc9dc135 XL |
1056 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, |
1057 | RustcEncodable, RustcDecodable, Hash, Debug)] | |
e9174d1e SL |
1058 | pub enum Mutability { |
1059 | MutMutable, | |
1060 | MutImmutable, | |
1061 | } | |
1062 | ||
3b2f2976 | 1063 | impl Mutability { |
e1599b0c | 1064 | /// Returns `MutMutable` only if both `self` and `other` are mutable. |
3b2f2976 XL |
1065 | pub fn and(self, other: Self) -> Self { |
1066 | match self { | |
1067 | MutMutable => other, | |
1068 | MutImmutable => MutImmutable, | |
1069 | } | |
1070 | } | |
e74abb32 XL |
1071 | |
1072 | pub fn invert(self) -> Self { | |
1073 | match self { | |
1074 | MutMutable => MutImmutable, | |
1075 | MutImmutable => MutMutable, | |
1076 | } | |
1077 | } | |
3b2f2976 XL |
1078 | } |
1079 | ||
e74abb32 | 1080 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 | 1081 | pub enum BinOpKind { |
9fa01778 | 1082 | /// The `+` operator (addition). |
8faf50e0 | 1083 | Add, |
9fa01778 | 1084 | /// The `-` operator (subtraction). |
8faf50e0 | 1085 | Sub, |
9fa01778 | 1086 | /// The `*` operator (multiplication). |
8faf50e0 | 1087 | Mul, |
9fa01778 | 1088 | /// The `/` operator (division). |
8faf50e0 | 1089 | Div, |
9fa01778 | 1090 | /// The `%` operator (modulus). |
8faf50e0 | 1091 | Rem, |
9fa01778 | 1092 | /// The `&&` operator (logical and). |
8faf50e0 | 1093 | And, |
9fa01778 | 1094 | /// The `||` operator (logical or). |
8faf50e0 | 1095 | Or, |
9fa01778 | 1096 | /// The `^` operator (bitwise xor). |
8faf50e0 | 1097 | BitXor, |
9fa01778 | 1098 | /// The `&` operator (bitwise and). |
8faf50e0 | 1099 | BitAnd, |
9fa01778 | 1100 | /// The `|` operator (bitwise or). |
8faf50e0 | 1101 | BitOr, |
9fa01778 | 1102 | /// The `<<` operator (shift left). |
8faf50e0 | 1103 | Shl, |
9fa01778 | 1104 | /// The `>>` operator (shift right). |
8faf50e0 | 1105 | Shr, |
9fa01778 | 1106 | /// The `==` operator (equality). |
8faf50e0 | 1107 | Eq, |
9fa01778 | 1108 | /// The `<` operator (less than). |
8faf50e0 | 1109 | Lt, |
9fa01778 | 1110 | /// The `<=` operator (less than or equal to). |
8faf50e0 | 1111 | Le, |
9fa01778 | 1112 | /// The `!=` operator (not equal to). |
8faf50e0 | 1113 | Ne, |
9fa01778 | 1114 | /// The `>=` operator (greater than or equal to). |
8faf50e0 | 1115 | Ge, |
9fa01778 | 1116 | /// The `>` operator (greater than). |
8faf50e0 | 1117 | Gt, |
e9174d1e SL |
1118 | } |
1119 | ||
8faf50e0 | 1120 | impl BinOpKind { |
54a0048b SL |
1121 | pub fn as_str(self) -> &'static str { |
1122 | match self { | |
8faf50e0 XL |
1123 | BinOpKind::Add => "+", |
1124 | BinOpKind::Sub => "-", | |
1125 | BinOpKind::Mul => "*", | |
1126 | BinOpKind::Div => "/", | |
1127 | BinOpKind::Rem => "%", | |
1128 | BinOpKind::And => "&&", | |
1129 | BinOpKind::Or => "||", | |
1130 | BinOpKind::BitXor => "^", | |
1131 | BinOpKind::BitAnd => "&", | |
1132 | BinOpKind::BitOr => "|", | |
1133 | BinOpKind::Shl => "<<", | |
1134 | BinOpKind::Shr => ">>", | |
1135 | BinOpKind::Eq => "==", | |
1136 | BinOpKind::Lt => "<", | |
1137 | BinOpKind::Le => "<=", | |
1138 | BinOpKind::Ne => "!=", | |
1139 | BinOpKind::Ge => ">=", | |
1140 | BinOpKind::Gt => ">", | |
54a0048b SL |
1141 | } |
1142 | } | |
1143 | ||
1144 | pub fn is_lazy(self) -> bool { | |
1145 | match self { | |
8faf50e0 | 1146 | BinOpKind::And | BinOpKind::Or => true, |
54a0048b SL |
1147 | _ => false, |
1148 | } | |
1149 | } | |
1150 | ||
1151 | pub fn is_shift(self) -> bool { | |
1152 | match self { | |
8faf50e0 | 1153 | BinOpKind::Shl | BinOpKind::Shr => true, |
54a0048b SL |
1154 | _ => false, |
1155 | } | |
1156 | } | |
1157 | ||
1158 | pub fn is_comparison(self) -> bool { | |
1159 | match self { | |
8faf50e0 XL |
1160 | BinOpKind::Eq | |
1161 | BinOpKind::Lt | | |
1162 | BinOpKind::Le | | |
1163 | BinOpKind::Ne | | |
1164 | BinOpKind::Gt | | |
1165 | BinOpKind::Ge => true, | |
1166 | BinOpKind::And | | |
1167 | BinOpKind::Or | | |
1168 | BinOpKind::Add | | |
1169 | BinOpKind::Sub | | |
1170 | BinOpKind::Mul | | |
1171 | BinOpKind::Div | | |
1172 | BinOpKind::Rem | | |
1173 | BinOpKind::BitXor | | |
1174 | BinOpKind::BitAnd | | |
1175 | BinOpKind::BitOr | | |
1176 | BinOpKind::Shl | | |
1177 | BinOpKind::Shr => false, | |
54a0048b SL |
1178 | } |
1179 | } | |
1180 | ||
9fa01778 | 1181 | /// Returns `true` if the binary operator takes its arguments by value. |
54a0048b SL |
1182 | pub fn is_by_value(self) -> bool { |
1183 | !self.is_comparison() | |
1184 | } | |
1185 | } | |
1186 | ||
8faf50e0 | 1187 | impl Into<ast::BinOpKind> for BinOpKind { |
2c00a5a8 XL |
1188 | fn into(self) -> ast::BinOpKind { |
1189 | match self { | |
8faf50e0 XL |
1190 | BinOpKind::Add => ast::BinOpKind::Add, |
1191 | BinOpKind::Sub => ast::BinOpKind::Sub, | |
1192 | BinOpKind::Mul => ast::BinOpKind::Mul, | |
1193 | BinOpKind::Div => ast::BinOpKind::Div, | |
1194 | BinOpKind::Rem => ast::BinOpKind::Rem, | |
1195 | BinOpKind::And => ast::BinOpKind::And, | |
1196 | BinOpKind::Or => ast::BinOpKind::Or, | |
1197 | BinOpKind::BitXor => ast::BinOpKind::BitXor, | |
1198 | BinOpKind::BitAnd => ast::BinOpKind::BitAnd, | |
1199 | BinOpKind::BitOr => ast::BinOpKind::BitOr, | |
1200 | BinOpKind::Shl => ast::BinOpKind::Shl, | |
1201 | BinOpKind::Shr => ast::BinOpKind::Shr, | |
1202 | BinOpKind::Eq => ast::BinOpKind::Eq, | |
1203 | BinOpKind::Lt => ast::BinOpKind::Lt, | |
1204 | BinOpKind::Le => ast::BinOpKind::Le, | |
1205 | BinOpKind::Ne => ast::BinOpKind::Ne, | |
1206 | BinOpKind::Ge => ast::BinOpKind::Ge, | |
1207 | BinOpKind::Gt => ast::BinOpKind::Gt, | |
2c00a5a8 XL |
1208 | } |
1209 | } | |
1210 | } | |
1211 | ||
8faf50e0 | 1212 | pub type BinOp = Spanned<BinOpKind>; |
e9174d1e | 1213 | |
e74abb32 | 1214 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 1215 | pub enum UnOp { |
9fa01778 | 1216 | /// The `*` operator (deferencing). |
e9174d1e | 1217 | UnDeref, |
9fa01778 | 1218 | /// The `!` operator (logical negation). |
e9174d1e | 1219 | UnNot, |
9fa01778 | 1220 | /// The `-` operator (negation). |
b039eaaf | 1221 | UnNeg, |
e9174d1e SL |
1222 | } |
1223 | ||
54a0048b SL |
1224 | impl UnOp { |
1225 | pub fn as_str(self) -> &'static str { | |
1226 | match self { | |
1227 | UnDeref => "*", | |
1228 | UnNot => "!", | |
1229 | UnNeg => "-", | |
1230 | } | |
1231 | } | |
1232 | ||
9fa01778 | 1233 | /// Returns `true` if the unary operator takes its argument by value. |
54a0048b SL |
1234 | pub fn is_by_value(self) -> bool { |
1235 | match self { | |
1236 | UnNeg | UnNot => true, | |
1237 | _ => false, | |
1238 | } | |
1239 | } | |
1240 | } | |
1241 | ||
9fa01778 | 1242 | /// A statement. |
dc9dc135 | 1243 | #[derive(RustcEncodable, RustcDecodable)] |
9fa01778 | 1244 | pub struct Stmt { |
9fa01778 | 1245 | pub hir_id: HirId, |
e74abb32 | 1246 | pub kind: StmtKind, |
9fa01778 XL |
1247 | pub span: Span, |
1248 | } | |
e9174d1e | 1249 | |
9fa01778 | 1250 | impl fmt::Debug for Stmt { |
0bf4aa26 | 1251 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
532ac7d7 | 1252 | write!(f, "stmt({}: {})", self.hir_id, |
9fa01778 | 1253 | print::to_string(print::NO_ANN, |s| s.print_stmt(self))) |
e9174d1e SL |
1254 | } |
1255 | } | |
1256 | ||
532ac7d7 | 1257 | /// The contents of a statement. |
dc9dc135 | 1258 | #[derive(RustcEncodable, RustcDecodable, HashStable)] |
8faf50e0 | 1259 | pub enum StmtKind { |
9fa01778 XL |
1260 | /// A local (`let`) binding. |
1261 | Local(P<Local>), | |
1262 | ||
1263 | /// An item binding. | |
1264 | Item(ItemId), | |
e9174d1e | 1265 | |
9fa01778 XL |
1266 | /// An expression without a trailing semi-colon (must have unit type). |
1267 | Expr(P<Expr>), | |
e9174d1e | 1268 | |
9fa01778 XL |
1269 | /// An expression with a trailing semi-colon (may have any type). |
1270 | Semi(P<Expr>), | |
e9174d1e SL |
1271 | } |
1272 | ||
8faf50e0 | 1273 | impl StmtKind { |
54a0048b SL |
1274 | pub fn attrs(&self) -> &[Attribute] { |
1275 | match *self { | |
9fa01778 XL |
1276 | StmtKind::Local(ref l) => &l.attrs, |
1277 | StmtKind::Item(_) => &[], | |
1278 | StmtKind::Expr(ref e) | | |
1279 | StmtKind::Semi(ref e) => &e.attrs, | |
54a0048b SL |
1280 | } |
1281 | } | |
1282 | } | |
1283 | ||
9fa01778 | 1284 | /// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`). |
dc9dc135 | 1285 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
1286 | pub struct Local { |
1287 | pub pat: P<Pat>, | |
532ac7d7 | 1288 | /// Type annotation, if any (otherwise the type will be inferred). |
e9174d1e | 1289 | pub ty: Option<P<Ty>>, |
9fa01778 | 1290 | /// Initializer expression to set the value, if any. |
e9174d1e | 1291 | pub init: Option<P<Expr>>, |
3b2f2976 | 1292 | pub hir_id: HirId, |
e9174d1e | 1293 | pub span: Span, |
3157f602 | 1294 | pub attrs: ThinVec<Attribute>, |
532ac7d7 XL |
1295 | /// Can be `ForLoopDesugar` if the `let` statement is part of a `for` loop |
1296 | /// desugaring. Otherwise will be `Normal`. | |
7cac9316 | 1297 | pub source: LocalSource, |
e9174d1e SL |
1298 | } |
1299 | ||
532ac7d7 | 1300 | /// Represents a single arm of a `match` expression, e.g. |
e74abb32 | 1301 | /// `<pat> (if <guard>) => <body>`. |
dc9dc135 | 1302 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 1303 | pub struct Arm { |
dc9dc135 XL |
1304 | #[stable_hasher(ignore)] |
1305 | pub hir_id: HirId, | |
1306 | pub span: Span, | |
9cc50fc6 | 1307 | pub attrs: HirVec<Attribute>, |
e74abb32 XL |
1308 | /// If this pattern and the optional guard matches, then `body` is evaluated. |
1309 | pub pat: P<Pat>, | |
532ac7d7 | 1310 | /// Optional guard clause. |
b7449926 | 1311 | pub guard: Option<Guard>, |
532ac7d7 | 1312 | /// The expression the arm evaluates to if this arm matches. |
e9174d1e SL |
1313 | pub body: P<Expr>, |
1314 | } | |
1315 | ||
dc9dc135 | 1316 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
b7449926 XL |
1317 | pub enum Guard { |
1318 | If(P<Expr>), | |
1319 | } | |
1320 | ||
dc9dc135 | 1321 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 1322 | pub struct Field { |
532ac7d7 | 1323 | #[stable_hasher(ignore)] |
9fa01778 | 1324 | pub hir_id: HirId, |
94b46f34 | 1325 | pub ident: Ident, |
e9174d1e SL |
1326 | pub expr: P<Expr>, |
1327 | pub span: Span, | |
c30ab7b3 | 1328 | pub is_shorthand: bool, |
e9174d1e SL |
1329 | } |
1330 | ||
dc9dc135 | 1331 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
1332 | pub enum BlockCheckMode { |
1333 | DefaultBlock, | |
1334 | UnsafeBlock(UnsafeSource), | |
1335 | PushUnsafeBlock(UnsafeSource), | |
1336 | PopUnsafeBlock(UnsafeSource), | |
1337 | } | |
1338 | ||
dc9dc135 | 1339 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
1340 | pub enum UnsafeSource { |
1341 | CompilerGenerated, | |
1342 | UserProvided, | |
1343 | } | |
1344 | ||
32a655c1 SL |
1345 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)] |
1346 | pub struct BodyId { | |
9fa01778 | 1347 | pub hir_id: HirId, |
32a655c1 SL |
1348 | } |
1349 | ||
ea8adc8c XL |
1350 | /// The body of a function, closure, or constant value. In the case of |
1351 | /// a function, the body contains not only the function body itself | |
1352 | /// (which is an expression), but also the argument patterns, since | |
1353 | /// those are something that the caller doesn't really care about. | |
1354 | /// | |
1355 | /// # Examples | |
1356 | /// | |
1357 | /// ``` | |
1358 | /// fn foo((x, y): (u32, u32)) -> u32 { | |
1359 | /// x + y | |
1360 | /// } | |
1361 | /// ``` | |
1362 | /// | |
1363 | /// Here, the `Body` associated with `foo()` would contain: | |
1364 | /// | |
e1599b0c | 1365 | /// - an `params` array containing the `(x, y)` pattern |
ea8adc8c | 1366 | /// - a `value` containing the `x + y` expression (maybe wrapped in a block) |
dc9dc135 | 1367 | /// - `generator_kind` would be `None` |
ea8adc8c XL |
1368 | /// |
1369 | /// All bodies have an **owner**, which can be accessed via the HIR | |
1370 | /// map using `body_owner_def_id()`. | |
dc9dc135 | 1371 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
32a655c1 | 1372 | pub struct Body { |
e1599b0c | 1373 | pub params: HirVec<Param>, |
ea8adc8c | 1374 | pub value: Expr, |
dc9dc135 | 1375 | pub generator_kind: Option<GeneratorKind>, |
32a655c1 | 1376 | } |
476ff2be | 1377 | |
32a655c1 SL |
1378 | impl Body { |
1379 | pub fn id(&self) -> BodyId { | |
1380 | BodyId { | |
9fa01778 | 1381 | hir_id: self.value.hir_id, |
32a655c1 | 1382 | } |
476ff2be | 1383 | } |
e74abb32 XL |
1384 | |
1385 | pub fn generator_kind(&self) -> Option<GeneratorKind> { | |
1386 | self.generator_kind | |
1387 | } | |
476ff2be SL |
1388 | } |
1389 | ||
dc9dc135 | 1390 | /// The type of source expression that caused this generator to be created. |
e74abb32 | 1391 | #[derive(Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable, Debug, Copy)] |
dc9dc135 | 1392 | pub enum GeneratorKind { |
e74abb32 XL |
1393 | /// An explicit `async` block or the body of an async function. |
1394 | Async(AsyncGeneratorKind), | |
1395 | ||
dc9dc135 XL |
1396 | /// A generator literal created via a `yield` inside a closure. |
1397 | Gen, | |
1398 | } | |
1399 | ||
1400 | impl fmt::Display for GeneratorKind { | |
e74abb32 XL |
1401 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1402 | match self { | |
1403 | GeneratorKind::Async(k) => fmt::Display::fmt(k, f), | |
1404 | GeneratorKind::Gen => f.write_str("generator"), | |
1405 | } | |
1406 | } | |
1407 | } | |
1408 | ||
1409 | /// In the case of a generator created as part of an async construct, | |
1410 | /// which kind of async construct caused it to be created? | |
1411 | /// | |
1412 | /// This helps error messages but is also used to drive coercions in | |
1413 | /// type-checking (see #60424). | |
1414 | #[derive(Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable, Debug, Copy)] | |
1415 | pub enum AsyncGeneratorKind { | |
1416 | /// An explicit `async` block written by the user. | |
1417 | Block, | |
1418 | ||
1419 | /// An explicit `async` block written by the user. | |
1420 | Closure, | |
1421 | ||
1422 | /// The `async` block generated as the body of an async function. | |
1423 | Fn, | |
1424 | } | |
1425 | ||
1426 | impl fmt::Display for AsyncGeneratorKind { | |
dc9dc135 XL |
1427 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1428 | f.write_str(match self { | |
e74abb32 XL |
1429 | AsyncGeneratorKind::Block => "`async` block", |
1430 | AsyncGeneratorKind::Closure => "`async` closure body", | |
1431 | AsyncGeneratorKind::Fn => "`async fn` body", | |
dc9dc135 XL |
1432 | }) |
1433 | } | |
1434 | } | |
1435 | ||
abe05a73 XL |
1436 | #[derive(Copy, Clone, Debug)] |
1437 | pub enum BodyOwnerKind { | |
1438 | /// Functions and methods. | |
1439 | Fn, | |
1440 | ||
9fa01778 XL |
1441 | /// Closures |
1442 | Closure, | |
1443 | ||
abe05a73 XL |
1444 | /// Constants and associated constants. |
1445 | Const, | |
1446 | ||
1447 | /// Initializer of a `static` item. | |
1448 | Static(Mutability), | |
1449 | } | |
1450 | ||
9fa01778 XL |
1451 | impl BodyOwnerKind { |
1452 | pub fn is_fn_or_closure(self) -> bool { | |
1453 | match self { | |
1454 | BodyOwnerKind::Fn | BodyOwnerKind::Closure => true, | |
1455 | BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false, | |
1456 | } | |
1457 | } | |
1458 | } | |
1459 | ||
48663c56 XL |
1460 | /// A literal. |
1461 | pub type Lit = Spanned<LitKind>; | |
1462 | ||
94b46f34 XL |
1463 | /// A constant (expression) that's not an item or associated item, |
1464 | /// but needs its own `DefId` for type-checking, const-eval, etc. | |
0731742a XL |
1465 | /// These are usually found nested inside types (e.g., array lengths) |
1466 | /// or expressions (e.g., repeat counts), and also used to define | |
94b46f34 | 1467 | /// explicit discriminant values for enum variants. |
532ac7d7 | 1468 | #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
94b46f34 | 1469 | pub struct AnonConst { |
94b46f34 XL |
1470 | pub hir_id: HirId, |
1471 | pub body: BodyId, | |
1472 | } | |
1473 | ||
e1599b0c | 1474 | /// An expression. |
dc9dc135 | 1475 | #[derive(RustcEncodable, RustcDecodable)] |
e9174d1e | 1476 | pub struct Expr { |
e1599b0c | 1477 | pub hir_id: HirId, |
e74abb32 | 1478 | pub kind: ExprKind, |
3157f602 | 1479 | pub attrs: ThinVec<Attribute>, |
e1599b0c | 1480 | pub span: Span, |
e9174d1e SL |
1481 | } |
1482 | ||
9fa01778 XL |
1483 | // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. |
1484 | #[cfg(target_arch = "x86_64")] | |
48663c56 | 1485 | static_assert_size!(Expr, 72); |
9fa01778 | 1486 | |
2c00a5a8 XL |
1487 | impl Expr { |
1488 | pub fn precedence(&self) -> ExprPrecedence { | |
e74abb32 | 1489 | match self.kind { |
8faf50e0 XL |
1490 | ExprKind::Box(_) => ExprPrecedence::Box, |
1491 | ExprKind::Array(_) => ExprPrecedence::Array, | |
1492 | ExprKind::Call(..) => ExprPrecedence::Call, | |
1493 | ExprKind::MethodCall(..) => ExprPrecedence::MethodCall, | |
1494 | ExprKind::Tup(_) => ExprPrecedence::Tup, | |
1495 | ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node.into()), | |
1496 | ExprKind::Unary(..) => ExprPrecedence::Unary, | |
1497 | ExprKind::Lit(_) => ExprPrecedence::Lit, | |
1498 | ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast, | |
48663c56 | 1499 | ExprKind::DropTemps(ref expr, ..) => expr.precedence(), |
8faf50e0 XL |
1500 | ExprKind::Loop(..) => ExprPrecedence::Loop, |
1501 | ExprKind::Match(..) => ExprPrecedence::Match, | |
1502 | ExprKind::Closure(..) => ExprPrecedence::Closure, | |
1503 | ExprKind::Block(..) => ExprPrecedence::Block, | |
1504 | ExprKind::Assign(..) => ExprPrecedence::Assign, | |
1505 | ExprKind::AssignOp(..) => ExprPrecedence::AssignOp, | |
1506 | ExprKind::Field(..) => ExprPrecedence::Field, | |
1507 | ExprKind::Index(..) => ExprPrecedence::Index, | |
1508 | ExprKind::Path(..) => ExprPrecedence::Path, | |
1509 | ExprKind::AddrOf(..) => ExprPrecedence::AddrOf, | |
1510 | ExprKind::Break(..) => ExprPrecedence::Break, | |
1511 | ExprKind::Continue(..) => ExprPrecedence::Continue, | |
1512 | ExprKind::Ret(..) => ExprPrecedence::Ret, | |
1513 | ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm, | |
1514 | ExprKind::Struct(..) => ExprPrecedence::Struct, | |
1515 | ExprKind::Repeat(..) => ExprPrecedence::Repeat, | |
1516 | ExprKind::Yield(..) => ExprPrecedence::Yield, | |
0731742a | 1517 | ExprKind::Err => ExprPrecedence::Err, |
2c00a5a8 XL |
1518 | } |
1519 | } | |
0bf4aa26 XL |
1520 | |
1521 | pub fn is_place_expr(&self) -> bool { | |
e74abb32 | 1522 | match self.kind { |
0bf4aa26 | 1523 | ExprKind::Path(QPath::Resolved(_, ref path)) => { |
48663c56 XL |
1524 | match path.res { |
1525 | Res::Local(..) | |
48663c56 XL |
1526 | | Res::Def(DefKind::Static, _) |
1527 | | Res::Err => true, | |
0bf4aa26 XL |
1528 | _ => false, |
1529 | } | |
1530 | } | |
1531 | ||
1532 | ExprKind::Type(ref e, _) => { | |
1533 | e.is_place_expr() | |
1534 | } | |
1535 | ||
1536 | ExprKind::Unary(UnDeref, _) | | |
1537 | ExprKind::Field(..) | | |
1538 | ExprKind::Index(..) => { | |
1539 | true | |
1540 | } | |
1541 | ||
1542 | // Partially qualified paths in expressions can only legally | |
1543 | // refer to associated items which are always rvalues. | |
1544 | ExprKind::Path(QPath::TypeRelative(..)) | | |
1545 | ||
1546 | ExprKind::Call(..) | | |
1547 | ExprKind::MethodCall(..) | | |
1548 | ExprKind::Struct(..) | | |
1549 | ExprKind::Tup(..) | | |
0bf4aa26 XL |
1550 | ExprKind::Match(..) | |
1551 | ExprKind::Closure(..) | | |
1552 | ExprKind::Block(..) | | |
1553 | ExprKind::Repeat(..) | | |
1554 | ExprKind::Array(..) | | |
1555 | ExprKind::Break(..) | | |
1556 | ExprKind::Continue(..) | | |
1557 | ExprKind::Ret(..) | | |
0bf4aa26 XL |
1558 | ExprKind::Loop(..) | |
1559 | ExprKind::Assign(..) | | |
1560 | ExprKind::InlineAsm(..) | | |
1561 | ExprKind::AssignOp(..) | | |
1562 | ExprKind::Lit(_) | | |
1563 | ExprKind::Unary(..) | | |
1564 | ExprKind::Box(..) | | |
1565 | ExprKind::AddrOf(..) | | |
1566 | ExprKind::Binary(..) | | |
1567 | ExprKind::Yield(..) | | |
0731742a | 1568 | ExprKind::Cast(..) | |
48663c56 | 1569 | ExprKind::DropTemps(..) | |
0731742a | 1570 | ExprKind::Err => { |
0bf4aa26 XL |
1571 | false |
1572 | } | |
1573 | } | |
1574 | } | |
e74abb32 XL |
1575 | |
1576 | /// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps` | |
1577 | /// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically | |
1578 | /// silent, only signaling the ownership system. By doing this, suggestions that check the | |
1579 | /// `ExprKind` of any given `Expr` for presentation don't have to care about `DropTemps` | |
1580 | /// beyond remembering to call this function before doing analysis on it. | |
1581 | pub fn peel_drop_temps(&self) -> &Self { | |
1582 | let mut expr = self; | |
1583 | while let ExprKind::DropTemps(inner) = &expr.kind { | |
1584 | expr = inner; | |
1585 | } | |
1586 | expr | |
1587 | } | |
2c00a5a8 XL |
1588 | } |
1589 | ||
e9174d1e | 1590 | impl fmt::Debug for Expr { |
0bf4aa26 | 1591 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
532ac7d7 | 1592 | write!(f, "expr({}: {})", self.hir_id, |
32a655c1 | 1593 | print::to_string(print::NO_ANN, |s| s.print_expr(self))) |
e9174d1e SL |
1594 | } |
1595 | } | |
1596 | ||
dc9dc135 | 1597 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 | 1598 | pub enum ExprKind { |
b039eaaf | 1599 | /// A `box x` expression. |
8faf50e0 | 1600 | Box(P<Expr>), |
9fa01778 | 1601 | /// An array (e.g., `[a, b, c, d]`). |
8faf50e0 | 1602 | Array(HirVec<Expr>), |
9fa01778 | 1603 | /// A function call. |
e9174d1e | 1604 | /// |
8faf50e0 | 1605 | /// The first field resolves to the function itself (usually an `ExprKind::Path`), |
abe05a73 XL |
1606 | /// and the second field is the list of arguments. |
1607 | /// This also represents calling the constructor of | |
1608 | /// tuple-like ADTs such as tuple structs and enum variants. | |
8faf50e0 | 1609 | Call(P<Expr>, HirVec<Expr>), |
9fa01778 | 1610 | /// A method call (e.g., `x.foo::<'static, Bar, Baz>(a, b, c, d)`). |
e9174d1e | 1611 | /// |
041b39d2 | 1612 | /// The `PathSegment`/`Span` represent the method name and its generic arguments |
e9174d1e | 1613 | /// (within the angle brackets). |
041b39d2 XL |
1614 | /// The first element of the vector of `Expr`s is the expression that evaluates |
1615 | /// to the object on which the method is being called on (the receiver), | |
1616 | /// and the remaining elements are the rest of the arguments. | |
e9174d1e | 1617 | /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as |
041b39d2 | 1618 | /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. |
9fa01778 | 1619 | MethodCall(P<PathSegment>, Span, HirVec<Expr>), |
e74abb32 | 1620 | /// A tuple (e.g., `(a, b, c, d)`). |
8faf50e0 | 1621 | Tup(HirVec<Expr>), |
9fa01778 | 1622 | /// A binary operation (e.g., `a + b`, `a * b`). |
8faf50e0 | 1623 | Binary(BinOp, P<Expr>, P<Expr>), |
9fa01778 | 1624 | /// A unary operation (e.g., `!x`, `*x`). |
8faf50e0 | 1625 | Unary(UnOp, P<Expr>), |
9fa01778 XL |
1626 | /// A literal (e.g., `1`, `"foo"`). |
1627 | Lit(Lit), | |
1628 | /// A cast (e.g., `foo as f64`). | |
8faf50e0 | 1629 | Cast(P<Expr>, P<Ty>), |
9fa01778 | 1630 | /// A type reference (e.g., `Foo`). |
8faf50e0 | 1631 | Type(P<Expr>, P<Ty>), |
48663c56 XL |
1632 | /// Wraps the expression in a terminating scope. |
1633 | /// This makes it semantically equivalent to `{ let _t = expr; _t }`. | |
e9174d1e | 1634 | /// |
48663c56 XL |
1635 | /// This construct only exists to tweak the drop order in HIR lowering. |
1636 | /// An example of that is the desugaring of `for` loops. | |
1637 | DropTemps(P<Expr>), | |
9fa01778 | 1638 | /// A conditionless loop (can be exited with `break`, `continue`, or `return`). |
e9174d1e | 1639 | /// |
9fa01778 | 1640 | /// I.e., `'label: loop { <block> }`. |
8faf50e0 | 1641 | Loop(P<Block>, Option<Label>, LoopSource), |
e9174d1e SL |
1642 | /// A `match` block, with a source that indicates whether or not it is |
1643 | /// the result of a desugaring, and if so, which kind. | |
8faf50e0 | 1644 | Match(P<Expr>, HirVec<Arm>, MatchSource), |
9fa01778 | 1645 | /// A closure (e.g., `move |a, b, c| {a + b + c}`). |
a7813a04 | 1646 | /// |
e1599b0c | 1647 | /// The `Span` is the argument block `|...|`. |
ea8adc8c | 1648 | /// |
dc9dc135 XL |
1649 | /// This may also be a generator literal or an `async block` as indicated by the |
1650 | /// `Option<GeneratorMovability>`. | |
8faf50e0 | 1651 | Closure(CaptureClause, P<FnDecl>, BodyId, Span, Option<GeneratorMovability>), |
9fa01778 | 1652 | /// A block (e.g., `'label: { ... }`). |
8faf50e0 | 1653 | Block(P<Block>, Option<Label>), |
e9174d1e | 1654 | |
9fa01778 | 1655 | /// An assignment (e.g., `a = foo()`). |
8faf50e0 | 1656 | Assign(P<Expr>, P<Expr>), |
9fa01778 | 1657 | /// An assignment with an operator. |
e9174d1e | 1658 | /// |
9fa01778 | 1659 | /// E.g., `a += 1`. |
8faf50e0 | 1660 | AssignOp(BinOp, P<Expr>, P<Expr>), |
9fa01778 | 1661 | /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct or tuple field. |
8faf50e0 | 1662 | Field(P<Expr>, Ident), |
9fa01778 | 1663 | /// An indexing operation (`foo[2]`). |
8faf50e0 | 1664 | Index(P<Expr>, P<Expr>), |
e9174d1e | 1665 | |
476ff2be | 1666 | /// Path to a definition, possibly containing lifetime or type parameters. |
8faf50e0 | 1667 | Path(QPath), |
e9174d1e | 1668 | |
9fa01778 | 1669 | /// A referencing operation (i.e., `&a` or `&mut a`). |
8faf50e0 | 1670 | AddrOf(Mutability, P<Expr>), |
9fa01778 | 1671 | /// A `break`, with an optional label to break. |
8faf50e0 | 1672 | Break(Destination, Option<P<Expr>>), |
9fa01778 | 1673 | /// A `continue`, with an optional label. |
8faf50e0 | 1674 | Continue(Destination), |
9fa01778 | 1675 | /// A `return`, with an optional value to be returned. |
8faf50e0 | 1676 | Ret(Option<P<Expr>>), |
e9174d1e | 1677 | |
54a0048b | 1678 | /// Inline assembly (from `asm!`), with its outputs and inputs. |
8faf50e0 | 1679 | InlineAsm(P<InlineAsm>, HirVec<Expr>, HirVec<Expr>), |
e9174d1e | 1680 | |
5bcae85e | 1681 | /// A struct or struct-like variant literal expression. |
e9174d1e | 1682 | /// |
dc9dc135 XL |
1683 | /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. base}`, |
1684 | /// where `base` is the `Option<Expr>`. | |
9fa01778 | 1685 | Struct(P<QPath>, HirVec<Field>, Option<P<Expr>>), |
e9174d1e | 1686 | |
5bcae85e | 1687 | /// An array literal constructed from one repeated element. |
e9174d1e | 1688 | /// |
dc9dc135 | 1689 | /// E.g., `[1; 5]`. The first expression is the element |
e9174d1e | 1690 | /// to be repeated; the second is the number of times to repeat it. |
8faf50e0 | 1691 | Repeat(P<Expr>, AnonConst), |
ea8adc8c | 1692 | |
9fa01778 | 1693 | /// A suspension point for generators (i.e., `yield <expr>`). |
dc9dc135 | 1694 | Yield(P<Expr>, YieldSource), |
0731742a | 1695 | |
9fa01778 | 1696 | /// A placeholder for an expression that wasn't syntactically well formed in some way. |
0731742a | 1697 | Err, |
e9174d1e SL |
1698 | } |
1699 | ||
dc9dc135 XL |
1700 | /// Represents an optionally `Self`-qualified value/type path or associated extension. |
1701 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] | |
476ff2be SL |
1702 | pub enum QPath { |
1703 | /// Path to a definition, optionally "fully-qualified" with a `Self` | |
1704 | /// type, if the path points to an associated item in a trait. | |
1705 | /// | |
9fa01778 | 1706 | /// E.g., an unqualified path like `Clone::clone` has `None` for `Self`, |
476ff2be SL |
1707 | /// while `<Vec<T> as Clone>::clone` has `Some(Vec<T>)` for `Self`, |
1708 | /// even though they both have the same two-segment `Clone::clone` `Path`. | |
1709 | Resolved(Option<P<Ty>>, P<Path>), | |
1710 | ||
9fa01778 | 1711 | /// Type-related paths (e.g., `<T>::default` or `<T>::Output`). |
476ff2be SL |
1712 | /// Will be resolved by type-checking to an associated item. |
1713 | /// | |
1714 | /// UFCS source paths can desugar into this, with `Vec::new` turning into | |
1715 | /// `<Vec>::new`, and `T::X::Y::method` into `<<<T>::X>::Y>::method`, | |
8faf50e0 | 1716 | /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`. |
476ff2be SL |
1717 | TypeRelative(P<Ty>, P<PathSegment>) |
1718 | } | |
1719 | ||
9fa01778 | 1720 | /// Hints at the original code for a let statement. |
dc9dc135 | 1721 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] |
7cac9316 | 1722 | pub enum LocalSource { |
9fa01778 | 1723 | /// A `match _ { .. }`. |
7cac9316 | 1724 | Normal, |
9fa01778 | 1725 | /// A desugared `for _ in _ { .. }` loop. |
7cac9316 | 1726 | ForLoopDesugar, |
48663c56 | 1727 | /// When lowering async functions, we create locals within the `async move` so that |
e1599b0c | 1728 | /// all parameters are dropped after the future is polled. |
48663c56 XL |
1729 | /// |
1730 | /// ```ignore (pseudo-Rust) | |
1731 | /// async fn foo(<pattern> @ x: Type) { | |
1732 | /// async move { | |
1733 | /// let <pattern> = x; | |
1734 | /// } | |
1735 | /// } | |
1736 | /// ``` | |
1737 | AsyncFn, | |
1738 | /// A desugared `<expr>.await`. | |
1739 | AwaitDesugar, | |
7cac9316 XL |
1740 | } |
1741 | ||
9fa01778 | 1742 | /// Hints at the original code for a `match _ { .. }`. |
dc9dc135 | 1743 | #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] |
e9174d1e | 1744 | pub enum MatchSource { |
9fa01778 | 1745 | /// A `match _ { .. }`. |
e9174d1e | 1746 | Normal, |
48663c56 XL |
1747 | /// An `if _ { .. }` (optionally with `else { .. }`). |
1748 | IfDesugar { | |
1749 | contains_else_clause: bool, | |
1750 | }, | |
9fa01778 | 1751 | /// An `if let _ = _ { .. }` (optionally with `else { .. }`). |
b039eaaf SL |
1752 | IfLetDesugar { |
1753 | contains_else_clause: bool, | |
1754 | }, | |
416331ca XL |
1755 | /// A `while _ { .. }` (which was desugared to a `loop { match _ { .. } }`). |
1756 | WhileDesugar, | |
5bcae85e | 1757 | /// A `while let _ = _ { .. }` (which was desugared to a |
9fa01778 | 1758 | /// `loop { match _ { .. } }`). |
e9174d1e | 1759 | WhileLetDesugar, |
9fa01778 | 1760 | /// A desugared `for _ in _ { .. }` loop. |
e9174d1e | 1761 | ForLoopDesugar, |
9fa01778 | 1762 | /// A desugared `?` operator. |
54a0048b | 1763 | TryDesugar, |
48663c56 XL |
1764 | /// A desugared `<expr>.await`. |
1765 | AwaitDesugar, | |
e9174d1e SL |
1766 | } |
1767 | ||
9fa01778 | 1768 | /// The loop type that yielded an `ExprKind::Loop`. |
dc9dc135 | 1769 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
476ff2be | 1770 | pub enum LoopSource { |
9fa01778 | 1771 | /// A `loop { .. }` loop. |
476ff2be | 1772 | Loop, |
416331ca XL |
1773 | /// A `while _ { .. }` loop. |
1774 | While, | |
9fa01778 | 1775 | /// A `while let _ = _ { .. }` loop. |
476ff2be | 1776 | WhileLet, |
9fa01778 | 1777 | /// A `for _ in _ { .. }` loop. |
476ff2be SL |
1778 | ForLoop, |
1779 | } | |
1780 | ||
416331ca XL |
1781 | impl LoopSource { |
1782 | pub fn name(self) -> &'static str { | |
1783 | match self { | |
1784 | LoopSource::Loop => "loop", | |
1785 | LoopSource::While => "while", | |
1786 | LoopSource::WhileLet => "while let", | |
1787 | LoopSource::ForLoop => "for", | |
1788 | } | |
1789 | } | |
1790 | } | |
1791 | ||
dc9dc135 | 1792 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] |
8bb4bdeb XL |
1793 | pub enum LoopIdError { |
1794 | OutsideLoopScope, | |
1795 | UnlabeledCfInWhileCondition, | |
1796 | UnresolvedLabel, | |
1797 | } | |
1798 | ||
1799 | impl fmt::Display for LoopIdError { | |
0bf4aa26 | 1800 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
dc9dc135 | 1801 | f.write_str(match self { |
8bb4bdeb XL |
1802 | LoopIdError::OutsideLoopScope => "not inside loop scope", |
1803 | LoopIdError::UnlabeledCfInWhileCondition => | |
1804 | "unlabeled control flow (break or continue) in while condition", | |
1805 | LoopIdError::UnresolvedLabel => "label not found", | |
dc9dc135 | 1806 | }) |
8bb4bdeb XL |
1807 | } |
1808 | } | |
476ff2be | 1809 | |
dc9dc135 | 1810 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] |
8bb4bdeb XL |
1811 | pub struct Destination { |
1812 | // This is `Some(_)` iff there is an explicit user-specified `label | |
2c00a5a8 | 1813 | pub label: Option<Label>, |
8bb4bdeb XL |
1814 | |
1815 | // These errors are caught and then reported during the diagnostics pass in | |
1816 | // librustc_passes/loops.rs | |
532ac7d7 | 1817 | pub target_id: Result<HirId, LoopIdError>, |
476ff2be SL |
1818 | } |
1819 | ||
dc9dc135 XL |
1820 | /// Whether a generator contains self-references, causing it to be `!Unpin`. |
1821 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, | |
1822 | RustcEncodable, RustcDecodable, Hash, Debug)] | |
2c00a5a8 | 1823 | pub enum GeneratorMovability { |
dc9dc135 | 1824 | /// May contain self-references, `!Unpin`. |
2c00a5a8 | 1825 | Static, |
e74abb32 | 1826 | |
dc9dc135 | 1827 | /// Must not contain self-references, `Unpin`. |
2c00a5a8 XL |
1828 | Movable, |
1829 | } | |
1830 | ||
dc9dc135 XL |
1831 | /// The yield kind that caused an `ExprKind::Yield`. |
1832 | #[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)] | |
1833 | pub enum YieldSource { | |
1834 | /// An `<expr>.await`. | |
1835 | Await, | |
1836 | /// A plain `yield`. | |
1837 | Yield, | |
1838 | } | |
1839 | ||
1840 | impl fmt::Display for YieldSource { | |
1841 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1842 | f.write_str(match self { | |
1843 | YieldSource::Await => "`await`", | |
1844 | YieldSource::Yield => "`yield`", | |
1845 | }) | |
1846 | } | |
1847 | } | |
1848 | ||
1849 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] | |
e9174d1e SL |
1850 | pub enum CaptureClause { |
1851 | CaptureByValue, | |
1852 | CaptureByRef, | |
1853 | } | |
1854 | ||
0731742a | 1855 | // N.B., if you change this, you'll probably want to change the corresponding |
e9174d1e | 1856 | // type structure in middle/ty.rs as well. |
dc9dc135 | 1857 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
1858 | pub struct MutTy { |
1859 | pub ty: P<Ty>, | |
1860 | pub mutbl: Mutability, | |
1861 | } | |
1862 | ||
5bcae85e | 1863 | /// Represents a method's signature in a trait declaration or implementation. |
dc9dc135 | 1864 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 1865 | pub struct MethodSig { |
8faf50e0 | 1866 | pub header: FnHeader, |
e9174d1e | 1867 | pub decl: P<FnDecl>, |
e9174d1e SL |
1868 | } |
1869 | ||
32a655c1 SL |
1870 | // The bodies for items are stored "out of line", in a separate |
1871 | // hashmap in the `Crate`. Here we just record the node-id of the item | |
1872 | // so it can fetched later. | |
8faf50e0 | 1873 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)] |
32a655c1 | 1874 | pub struct TraitItemId { |
532ac7d7 | 1875 | pub hir_id: HirId, |
32a655c1 SL |
1876 | } |
1877 | ||
54a0048b SL |
1878 | /// Represents an item declaration within a trait declaration, |
1879 | /// possibly including a default implementation. A trait item is | |
1880 | /// either required (meaning it doesn't have an implementation, just a | |
1881 | /// signature) or provided (meaning it has a default implementation). | |
dc9dc135 | 1882 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
e9174d1e | 1883 | pub struct TraitItem { |
8faf50e0 | 1884 | pub ident: Ident, |
3b2f2976 | 1885 | pub hir_id: HirId, |
9cc50fc6 | 1886 | pub attrs: HirVec<Attribute>, |
abe05a73 | 1887 | pub generics: Generics, |
e74abb32 | 1888 | pub kind: TraitItemKind, |
e9174d1e SL |
1889 | pub span: Span, |
1890 | } | |
1891 | ||
dc9dc135 XL |
1892 | /// Represents a trait method's body (or just argument names). |
1893 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] | |
32a655c1 SL |
1894 | pub enum TraitMethod { |
1895 | /// No default body in the trait, just a signature. | |
8faf50e0 | 1896 | Required(HirVec<Ident>), |
32a655c1 SL |
1897 | |
1898 | /// Both signature and body are provided in the trait. | |
1899 | Provided(BodyId), | |
1900 | } | |
1901 | ||
5bcae85e | 1902 | /// Represents a trait method or associated constant or type |
dc9dc135 | 1903 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
32a655c1 | 1904 | pub enum TraitItemKind { |
dc9dc135 | 1905 | /// An associated constant with an optional value (otherwise `impl`s must contain a value). |
32a655c1 | 1906 | Const(P<Ty>, Option<BodyId>), |
dc9dc135 | 1907 | /// A method with an optional body. |
32a655c1 | 1908 | Method(MethodSig, TraitMethod), |
5bcae85e | 1909 | /// An associated type with (possibly empty) bounds and optional concrete |
dc9dc135 | 1910 | /// type. |
8faf50e0 | 1911 | Type(GenericBounds, Option<P<Ty>>), |
e9174d1e SL |
1912 | } |
1913 | ||
476ff2be SL |
1914 | // The bodies for items are stored "out of line", in a separate |
1915 | // hashmap in the `Crate`. Here we just record the node-id of the item | |
1916 | // so it can fetched later. | |
8faf50e0 | 1917 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)] |
476ff2be | 1918 | pub struct ImplItemId { |
532ac7d7 | 1919 | pub hir_id: HirId, |
476ff2be SL |
1920 | } |
1921 | ||
416331ca | 1922 | /// Represents anything within an `impl` block. |
dc9dc135 | 1923 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
e9174d1e | 1924 | pub struct ImplItem { |
8faf50e0 | 1925 | pub ident: Ident, |
3b2f2976 | 1926 | pub hir_id: HirId, |
e9174d1e | 1927 | pub vis: Visibility, |
54a0048b | 1928 | pub defaultness: Defaultness, |
9cc50fc6 | 1929 | pub attrs: HirVec<Attribute>, |
abe05a73 | 1930 | pub generics: Generics, |
e74abb32 | 1931 | pub kind: ImplItemKind, |
e9174d1e SL |
1932 | pub span: Span, |
1933 | } | |
1934 | ||
dc9dc135 XL |
1935 | /// Represents various kinds of content within an `impl`. |
1936 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] | |
92a42be0 | 1937 | pub enum ImplItemKind { |
5bcae85e | 1938 | /// An associated constant of the given type, set to the constant result |
416331ca | 1939 | /// of the expression. |
32a655c1 | 1940 | Const(P<Ty>, BodyId), |
416331ca | 1941 | /// A method implementation with the given signature and body. |
32a655c1 | 1942 | Method(MethodSig, BodyId), |
416331ca XL |
1943 | /// An associated type. |
1944 | TyAlias(P<Ty>), | |
1945 | /// An associated `type = impl Trait`. | |
1946 | OpaqueTy(GenericBounds), | |
e9174d1e SL |
1947 | } |
1948 | ||
dc9dc135 XL |
1949 | /// Bind a type to an associated type (i.e., `A = Foo`). |
1950 | /// | |
1951 | /// Bindings like `A: Debug` are represented as a special type `A = | |
1952 | /// $::Debug` that is understood by the astconv code. | |
1953 | /// | |
1954 | /// FIXME(alexreg) -- why have a separate type for the binding case, | |
1955 | /// wouldn't it be better to make the `ty` field an enum like: | |
1956 | /// | |
1957 | /// ``` | |
1958 | /// enum TypeBindingKind { | |
1959 | /// Equals(...), | |
1960 | /// Binding(...), | |
1961 | /// } | |
1962 | /// ``` | |
1963 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] | |
e9174d1e | 1964 | pub struct TypeBinding { |
9fa01778 | 1965 | pub hir_id: HirId, |
532ac7d7 | 1966 | #[stable_hasher(project(name))] |
8faf50e0 | 1967 | pub ident: Ident, |
dc9dc135 | 1968 | pub kind: TypeBindingKind, |
e9174d1e SL |
1969 | pub span: Span, |
1970 | } | |
1971 | ||
dc9dc135 XL |
1972 | // Represents the two kinds of type bindings. |
1973 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] | |
1974 | pub enum TypeBindingKind { | |
1975 | /// E.g., `Foo<Bar: Send>`. | |
1976 | Constraint { | |
1977 | bounds: HirVec<GenericBound>, | |
1978 | }, | |
1979 | /// E.g., `Foo<Bar = ()>`. | |
1980 | Equality { | |
1981 | ty: P<Ty>, | |
1982 | }, | |
1983 | } | |
1984 | ||
1985 | impl TypeBinding { | |
1986 | pub fn ty(&self) -> &Ty { | |
1987 | match self.kind { | |
1988 | TypeBindingKind::Equality { ref ty } => ty, | |
1989 | _ => bug!("expected equality type binding for parenthesized generic args"), | |
1990 | } | |
1991 | } | |
1992 | } | |
1993 | ||
1994 | #[derive(RustcEncodable, RustcDecodable)] | |
e9174d1e | 1995 | pub struct Ty { |
dc9dc135 | 1996 | pub hir_id: HirId, |
e74abb32 | 1997 | pub kind: TyKind, |
e9174d1e SL |
1998 | pub span: Span, |
1999 | } | |
2000 | ||
2001 | impl fmt::Debug for Ty { | |
0bf4aa26 | 2002 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
32a655c1 SL |
2003 | write!(f, "type({})", |
2004 | print::to_string(print::NO_ANN, |s| s.print_type(self))) | |
e9174d1e SL |
2005 | } |
2006 | } | |
2007 | ||
9fa01778 | 2008 | /// Not represented directly in the AST; referred to by name through a `ty_path`. |
dc9dc135 | 2009 | #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] |
e9174d1e | 2010 | pub enum PrimTy { |
b7449926 XL |
2011 | Int(IntTy), |
2012 | Uint(UintTy), | |
2013 | Float(FloatTy), | |
2014 | Str, | |
2015 | Bool, | |
2016 | Char, | |
e9174d1e SL |
2017 | } |
2018 | ||
dc9dc135 | 2019 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
2020 | pub struct BareFnTy { |
2021 | pub unsafety: Unsafety, | |
2022 | pub abi: Abi, | |
ff7c6d11 | 2023 | pub generic_params: HirVec<GenericParam>, |
b039eaaf | 2024 | pub decl: P<FnDecl>, |
e1599b0c | 2025 | pub param_names: HirVec<Ident>, |
e9174d1e SL |
2026 | } |
2027 | ||
dc9dc135 | 2028 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
416331ca | 2029 | pub struct OpaqueTy { |
ff7c6d11 | 2030 | pub generics: Generics, |
8faf50e0 | 2031 | pub bounds: GenericBounds, |
94b46f34 | 2032 | pub impl_trait_fn: Option<DefId>, |
416331ca | 2033 | pub origin: OpaqueTyOrigin, |
532ac7d7 XL |
2034 | } |
2035 | ||
416331ca | 2036 | /// From whence the opaque type came. |
532ac7d7 | 2037 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] |
416331ca XL |
2038 | pub enum OpaqueTyOrigin { |
2039 | /// `type Foo = impl Trait;` | |
2040 | TypeAlias, | |
532ac7d7 | 2041 | /// `-> impl Trait` |
416331ca | 2042 | FnReturn, |
532ac7d7 XL |
2043 | /// `async fn` |
2044 | AsyncFn, | |
ff7c6d11 XL |
2045 | } |
2046 | ||
9fa01778 | 2047 | /// The various kinds of types recognized by the compiler. |
dc9dc135 | 2048 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 | 2049 | pub enum TyKind { |
9fa01778 | 2050 | /// A variable length slice (i.e., `[T]`). |
8faf50e0 | 2051 | Slice(P<Ty>), |
9fa01778 | 2052 | /// A fixed length array (i.e., `[T; n]`). |
8faf50e0 | 2053 | Array(P<Ty>, AnonConst), |
9fa01778 | 2054 | /// A raw pointer (i.e., `*const T` or `*mut T`). |
8faf50e0 | 2055 | Ptr(MutTy), |
9fa01778 | 2056 | /// A reference (i.e., `&'a T` or `&'a mut T`). |
8faf50e0 | 2057 | Rptr(Lifetime, MutTy), |
9fa01778 | 2058 | /// A bare function (e.g., `fn(usize) -> bool`). |
8faf50e0 | 2059 | BareFn(P<BareFnTy>), |
9fa01778 | 2060 | /// The never type (`!`). |
8faf50e0 | 2061 | Never, |
dc9dc135 | 2062 | /// A tuple (`(A, B, C, D, ...)`). |
8faf50e0 | 2063 | Tup(HirVec<Ty>), |
476ff2be | 2064 | /// A path to a type definition (`module::module::...::Type`), or an |
9fa01778 | 2065 | /// associated type (e.g., `<Vec<T> as Trait>::Type` or `<T>::Target`). |
e9174d1e | 2066 | /// |
476ff2be | 2067 | /// Type parameters may be stored in each `PathSegment`. |
8faf50e0 | 2068 | Path(QPath), |
416331ca | 2069 | /// A type definition itself. This is currently only used for the `type Foo = impl Trait` |
0bf4aa26 XL |
2070 | /// item that `impl Trait` in return position desugars to. |
2071 | /// | |
9fa01778 XL |
2072 | /// The generic argument list contains the lifetimes (and in the future possibly parameters) |
2073 | /// that are actually bound on the `impl Trait`. | |
0bf4aa26 | 2074 | Def(ItemId, HirVec<GenericArg>), |
32a655c1 SL |
2075 | /// A trait object type `Bound1 + Bound2 + Bound3` |
2076 | /// where `Bound` is a trait or a lifetime. | |
8faf50e0 | 2077 | TraitObject(HirVec<PolyTraitRef>, Lifetime), |
9fa01778 | 2078 | /// Unused for now. |
8faf50e0 | 2079 | Typeof(AnonConst), |
0731742a | 2080 | /// `TyKind::Infer` means the type should be inferred instead of it having been |
e9174d1e | 2081 | /// specified. This can appear anywhere in a type. |
8faf50e0 | 2082 | Infer, |
cc61c64b | 2083 | /// Placeholder for a type that has failed to be defined. |
8faf50e0 | 2084 | Err, |
e9174d1e SL |
2085 | } |
2086 | ||
dc9dc135 | 2087 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] |
9cc50fc6 | 2088 | pub struct InlineAsmOutput { |
476ff2be | 2089 | pub constraint: Symbol, |
9cc50fc6 SL |
2090 | pub is_rw: bool, |
2091 | pub is_indirect: bool, | |
0bf4aa26 | 2092 | pub span: Span, |
9cc50fc6 SL |
2093 | } |
2094 | ||
416331ca XL |
2095 | // NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR, |
2096 | // it needs to be `Clone` and use plain `Vec<T>` instead of `HirVec<T>`. | |
532ac7d7 | 2097 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 2098 | pub struct InlineAsm { |
476ff2be | 2099 | pub asm: Symbol, |
e9174d1e | 2100 | pub asm_str_style: StrStyle, |
416331ca XL |
2101 | pub outputs: Vec<InlineAsmOutput>, |
2102 | pub inputs: Vec<Symbol>, | |
2103 | pub clobbers: Vec<Symbol>, | |
e9174d1e SL |
2104 | pub volatile: bool, |
2105 | pub alignstack: bool, | |
2106 | pub dialect: AsmDialect, | |
e9174d1e SL |
2107 | } |
2108 | ||
e1599b0c | 2109 | /// Represents a parameter in a function header. |
dc9dc135 | 2110 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e1599b0c | 2111 | pub struct Param { |
416331ca | 2112 | pub attrs: HirVec<Attribute>, |
3b2f2976 | 2113 | pub hir_id: HirId, |
416331ca XL |
2114 | pub pat: P<Pat>, |
2115 | pub span: Span, | |
e9174d1e SL |
2116 | } |
2117 | ||
9fa01778 | 2118 | /// Represents the header (not the body) of a function declaration. |
dc9dc135 | 2119 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 2120 | pub struct FnDecl { |
e1599b0c | 2121 | /// The types of the function's parameters. |
48663c56 | 2122 | /// |
e1599b0c | 2123 | /// Additional argument data is stored in the function's [body](Body::parameters). |
8faf50e0 | 2124 | pub inputs: HirVec<Ty>, |
e9174d1e | 2125 | pub output: FunctionRetTy, |
532ac7d7 | 2126 | pub c_variadic: bool, |
0bf4aa26 XL |
2127 | /// Does the function have an implicit self? |
2128 | pub implicit_self: ImplicitSelfKind, | |
2129 | } | |
2130 | ||
2131 | /// Represents what type of implicit self a function has, if any. | |
dc9dc135 | 2132 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] |
0bf4aa26 XL |
2133 | pub enum ImplicitSelfKind { |
2134 | /// Represents a `fn x(self);`. | |
2135 | Imm, | |
2136 | /// Represents a `fn x(mut self);`. | |
2137 | Mut, | |
2138 | /// Represents a `fn x(&self);`. | |
2139 | ImmRef, | |
2140 | /// Represents a `fn x(&mut self);`. | |
2141 | MutRef, | |
2142 | /// Represents when a function does not have a self argument or | |
2143 | /// when a function has a `self: X` argument. | |
2144 | None | |
2145 | } | |
2146 | ||
2147 | impl ImplicitSelfKind { | |
2148 | /// Does this represent an implicit self? | |
2149 | pub fn has_implicit_self(&self) -> bool { | |
2150 | match *self { | |
2151 | ImplicitSelfKind::None => false, | |
2152 | _ => true, | |
2153 | } | |
2154 | } | |
e9174d1e SL |
2155 | } |
2156 | ||
abe05a73 | 2157 | /// Is the trait definition an auto trait? |
532ac7d7 | 2158 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
abe05a73 XL |
2159 | pub enum IsAuto { |
2160 | Yes, | |
2161 | No | |
2162 | } | |
2163 | ||
532ac7d7 XL |
2164 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, HashStable, |
2165 | Ord, RustcEncodable, RustcDecodable, Debug)] | |
8faf50e0 XL |
2166 | pub enum IsAsync { |
2167 | Async, | |
2168 | NotAsync, | |
2169 | } | |
2170 | ||
532ac7d7 XL |
2171 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, |
2172 | RustcEncodable, RustcDecodable, Hash, Debug)] | |
e9174d1e SL |
2173 | pub enum Unsafety { |
2174 | Unsafe, | |
2175 | Normal, | |
2176 | } | |
2177 | ||
532ac7d7 | 2178 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
2179 | pub enum Constness { |
2180 | Const, | |
2181 | NotConst, | |
2182 | } | |
2183 | ||
532ac7d7 | 2184 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
54a0048b | 2185 | pub enum Defaultness { |
476ff2be | 2186 | Default { has_value: bool }, |
54a0048b SL |
2187 | Final, |
2188 | } | |
2189 | ||
2190 | impl Defaultness { | |
476ff2be SL |
2191 | pub fn has_value(&self) -> bool { |
2192 | match *self { | |
2193 | Defaultness::Default { has_value, .. } => has_value, | |
2194 | Defaultness::Final => true, | |
2195 | } | |
2196 | } | |
2197 | ||
54a0048b SL |
2198 | pub fn is_final(&self) -> bool { |
2199 | *self == Defaultness::Final | |
2200 | } | |
2201 | ||
2202 | pub fn is_default(&self) -> bool { | |
476ff2be SL |
2203 | match *self { |
2204 | Defaultness::Default { .. } => true, | |
2205 | _ => false, | |
2206 | } | |
54a0048b SL |
2207 | } |
2208 | } | |
2209 | ||
e9174d1e | 2210 | impl fmt::Display for Unsafety { |
0bf4aa26 | 2211 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
dc9dc135 XL |
2212 | f.write_str(match self { |
2213 | Unsafety::Normal => "normal", | |
2214 | Unsafety::Unsafe => "unsafe", | |
2215 | }) | |
e9174d1e SL |
2216 | } |
2217 | } | |
2218 | ||
532ac7d7 | 2219 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] |
e9174d1e SL |
2220 | pub enum ImplPolarity { |
2221 | /// `impl Trait for Type` | |
2222 | Positive, | |
2223 | /// `impl !Trait for Type` | |
2224 | Negative, | |
2225 | } | |
2226 | ||
2227 | impl fmt::Debug for ImplPolarity { | |
0bf4aa26 | 2228 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
dc9dc135 XL |
2229 | f.write_str(match self { |
2230 | ImplPolarity::Positive => "positive", | |
2231 | ImplPolarity::Negative => "negative", | |
2232 | }) | |
e9174d1e SL |
2233 | } |
2234 | } | |
2235 | ||
2236 | ||
dc9dc135 | 2237 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 2238 | pub enum FunctionRetTy { |
e9174d1e SL |
2239 | /// Return type is not specified. |
2240 | /// | |
2241 | /// Functions default to `()` and | |
2242 | /// closures default to inference. Span points to where return | |
2243 | /// type would be inserted. | |
2244 | DefaultReturn(Span), | |
9fa01778 | 2245 | /// Everything else. |
e9174d1e SL |
2246 | Return(P<Ty>), |
2247 | } | |
2248 | ||
0731742a XL |
2249 | impl fmt::Display for FunctionRetTy { |
2250 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
2251 | match self { | |
2252 | Return(ref ty) => print::to_string(print::NO_ANN, |s| s.print_type(ty)).fmt(f), | |
2253 | DefaultReturn(_) => "()".fmt(f), | |
2254 | } | |
2255 | } | |
2256 | } | |
2257 | ||
e9174d1e SL |
2258 | impl FunctionRetTy { |
2259 | pub fn span(&self) -> Span { | |
2260 | match *self { | |
e9174d1e | 2261 | DefaultReturn(span) => span, |
b039eaaf | 2262 | Return(ref ty) => ty.span, |
e9174d1e SL |
2263 | } |
2264 | } | |
2265 | } | |
2266 | ||
dc9dc135 | 2267 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
e9174d1e SL |
2268 | pub struct Mod { |
2269 | /// A span from the first token past `{` to the last token until `}`. | |
2270 | /// For `mod foo;`, the inner span ranges from the first token | |
2271 | /// to the last token in the external file. | |
2272 | pub inner: Span, | |
9cc50fc6 | 2273 | pub item_ids: HirVec<ItemId>, |
e9174d1e SL |
2274 | } |
2275 | ||
dc9dc135 | 2276 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e SL |
2277 | pub struct ForeignMod { |
2278 | pub abi: Abi, | |
9cc50fc6 | 2279 | pub items: HirVec<ForeignItem>, |
e9174d1e SL |
2280 | } |
2281 | ||
dc9dc135 | 2282 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
cc61c64b XL |
2283 | pub struct GlobalAsm { |
2284 | pub asm: Symbol, | |
cc61c64b XL |
2285 | } |
2286 | ||
dc9dc135 | 2287 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 2288 | pub struct EnumDef { |
9cc50fc6 | 2289 | pub variants: HirVec<Variant>, |
e9174d1e SL |
2290 | } |
2291 | ||
dc9dc135 | 2292 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e1599b0c | 2293 | pub struct Variant { |
532ac7d7 XL |
2294 | /// Name of the variant. |
2295 | #[stable_hasher(project(name))] | |
0731742a | 2296 | pub ident: Ident, |
532ac7d7 | 2297 | /// Attributes of the variant. |
9cc50fc6 | 2298 | pub attrs: HirVec<Attribute>, |
532ac7d7 XL |
2299 | /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`). |
2300 | pub id: HirId, | |
2301 | /// Fields and constructor id of the variant. | |
b039eaaf | 2302 | pub data: VariantData, |
9fa01778 | 2303 | /// Explicit discriminant (e.g., `Foo = 1`). |
94b46f34 | 2304 | pub disr_expr: Option<AnonConst>, |
e1599b0c XL |
2305 | /// Span |
2306 | pub span: Span | |
e9174d1e SL |
2307 | } |
2308 | ||
532ac7d7 | 2309 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
476ff2be | 2310 | pub enum UseKind { |
0731742a | 2311 | /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. |
476ff2be | 2312 | /// Also produced for each element of a list `use`, e.g. |
532ac7d7 | 2313 | /// `use foo::{a, b}` lowers to `use foo::a; use foo::b;`. |
476ff2be | 2314 | Single, |
e9174d1e | 2315 | |
0731742a | 2316 | /// Glob import, e.g., `use foo::*`. |
476ff2be | 2317 | Glob, |
e9174d1e | 2318 | |
0731742a | 2319 | /// Degenerate list import, e.g., `use foo::{a, b}` produces |
476ff2be SL |
2320 | /// an additional `use foo::{}` for performing checks such as |
2321 | /// unstable feature gating. May be removed in the future. | |
2322 | ListStem, | |
e9174d1e SL |
2323 | } |
2324 | ||
dc9dc135 | 2325 | /// References to traits in impls. |
e9174d1e | 2326 | /// |
dc9dc135 XL |
2327 | /// `resolve` maps each `TraitRef`'s `ref_id` to its defining trait; that's all |
2328 | /// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the | |
2329 | /// trait being referred to but just a unique `HirId` that serves as a key | |
48663c56 | 2330 | /// within the resolution map. |
dc9dc135 | 2331 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 2332 | pub struct TraitRef { |
416331ca XL |
2333 | pub path: P<Path>, |
2334 | // Don't hash the `ref_id`. It is tracked via the thing it is used to access. | |
532ac7d7 | 2335 | #[stable_hasher(ignore)] |
b7449926 | 2336 | pub hir_ref_id: HirId, |
e9174d1e SL |
2337 | } |
2338 | ||
9fa01778 XL |
2339 | impl TraitRef { |
2340 | /// Gets the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias. | |
2341 | pub fn trait_def_id(&self) -> DefId { | |
48663c56 XL |
2342 | match self.path.res { |
2343 | Res::Def(DefKind::Trait, did) => did, | |
2344 | Res::Def(DefKind::TraitAlias, did) => did, | |
2345 | Res::Err => { | |
9fa01778 XL |
2346 | FatalError.raise(); |
2347 | } | |
2348 | _ => unreachable!(), | |
2349 | } | |
2350 | } | |
2351 | } | |
2352 | ||
dc9dc135 | 2353 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 2354 | pub struct PolyTraitRef { |
9fa01778 | 2355 | /// The `'a` in `<'a> Foo<&'a T>`. |
ff7c6d11 | 2356 | pub bound_generic_params: HirVec<GenericParam>, |
e9174d1e | 2357 | |
9fa01778 | 2358 | /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`. |
e9174d1e SL |
2359 | pub trait_ref: TraitRef, |
2360 | ||
2361 | pub span: Span, | |
2362 | } | |
2363 | ||
8faf50e0 XL |
2364 | pub type Visibility = Spanned<VisibilityKind>; |
2365 | ||
dc9dc135 | 2366 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
8faf50e0 | 2367 | pub enum VisibilityKind { |
e9174d1e | 2368 | Public, |
94b46f34 | 2369 | Crate(CrateSugar), |
532ac7d7 | 2370 | Restricted { path: P<Path>, hir_id: HirId }, |
e9174d1e SL |
2371 | Inherited, |
2372 | } | |
2373 | ||
8faf50e0 XL |
2374 | impl VisibilityKind { |
2375 | pub fn is_pub(&self) -> bool { | |
2376 | match *self { | |
2377 | VisibilityKind::Public => true, | |
2378 | _ => false | |
2379 | } | |
2380 | } | |
2381 | ||
cc61c64b | 2382 | pub fn is_pub_restricted(&self) -> bool { |
8faf50e0 XL |
2383 | match *self { |
2384 | VisibilityKind::Public | | |
2385 | VisibilityKind::Inherited => false, | |
2386 | VisibilityKind::Crate(..) | | |
2387 | VisibilityKind::Restricted { .. } => true, | |
cc61c64b XL |
2388 | } |
2389 | } | |
0731742a XL |
2390 | |
2391 | pub fn descr(&self) -> &'static str { | |
2392 | match *self { | |
2393 | VisibilityKind::Public => "public", | |
2394 | VisibilityKind::Inherited => "private", | |
2395 | VisibilityKind::Crate(..) => "crate-visible", | |
2396 | VisibilityKind::Restricted { .. } => "restricted", | |
2397 | } | |
2398 | } | |
cc61c64b XL |
2399 | } |
2400 | ||
dc9dc135 | 2401 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
54a0048b SL |
2402 | pub struct StructField { |
2403 | pub span: Span, | |
532ac7d7 | 2404 | #[stable_hasher(project(name))] |
94b46f34 | 2405 | pub ident: Ident, |
54a0048b | 2406 | pub vis: Visibility, |
9fa01778 | 2407 | pub hir_id: HirId, |
e9174d1e | 2408 | pub ty: P<Ty>, |
9cc50fc6 | 2409 | pub attrs: HirVec<Attribute>, |
e9174d1e SL |
2410 | } |
2411 | ||
54a0048b SL |
2412 | impl StructField { |
2413 | // Still necessary in couple of places | |
2414 | pub fn is_positional(&self) -> bool { | |
94b46f34 | 2415 | let first = self.ident.as_str().as_bytes()[0]; |
54a0048b | 2416 | first >= b'0' && first <= b'9' |
92a42be0 | 2417 | } |
e9174d1e SL |
2418 | } |
2419 | ||
dc9dc135 XL |
2420 | /// Fields and constructor IDs of enum variants and structs. |
2421 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] | |
b039eaaf | 2422 | pub enum VariantData { |
dc9dc135 | 2423 | /// A struct variant. |
532ac7d7 | 2424 | /// |
dc9dc135 | 2425 | /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. |
532ac7d7 | 2426 | Struct(HirVec<StructField>, /* recovered */ bool), |
dc9dc135 | 2427 | /// A tuple variant. |
532ac7d7 XL |
2428 | /// |
2429 | /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. | |
2430 | Tuple(HirVec<StructField>, HirId), | |
dc9dc135 | 2431 | /// A unit variant. |
532ac7d7 XL |
2432 | /// |
2433 | /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`. | |
2434 | Unit(HirId), | |
b039eaaf SL |
2435 | } |
2436 | ||
2437 | impl VariantData { | |
532ac7d7 | 2438 | /// Return the fields of this variant. |
b039eaaf SL |
2439 | pub fn fields(&self) -> &[StructField] { |
2440 | match *self { | |
9fa01778 | 2441 | VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => fields, |
b039eaaf SL |
2442 | _ => &[], |
2443 | } | |
2444 | } | |
532ac7d7 XL |
2445 | |
2446 | /// Return the `HirId` of this variant's constructor, if it has one. | |
2447 | pub fn ctor_hir_id(&self) -> Option<HirId> { | |
9fa01778 | 2448 | match *self { |
532ac7d7 XL |
2449 | VariantData::Struct(_, _) => None, |
2450 | VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id), | |
92a42be0 | 2451 | } |
b039eaaf | 2452 | } |
e9174d1e SL |
2453 | } |
2454 | ||
92a42be0 SL |
2455 | // The bodies for items are stored "out of line", in a separate |
2456 | // hashmap in the `Crate`. Here we just record the node-id of the item | |
2457 | // so it can fetched later. | |
8faf50e0 | 2458 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] |
92a42be0 | 2459 | pub struct ItemId { |
532ac7d7 | 2460 | pub id: HirId, |
92a42be0 SL |
2461 | } |
2462 | ||
e9174d1e SL |
2463 | /// An item |
2464 | /// | |
2465 | /// The name might be a dummy name in case of anonymous items | |
dc9dc135 | 2466 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
e9174d1e | 2467 | pub struct Item { |
0731742a | 2468 | pub ident: Ident, |
3b2f2976 XL |
2469 | pub hir_id: HirId, |
2470 | pub attrs: HirVec<Attribute>, | |
e74abb32 | 2471 | pub kind: ItemKind, |
e9174d1e SL |
2472 | pub vis: Visibility, |
2473 | pub span: Span, | |
2474 | } | |
2475 | ||
dc9dc135 | 2476 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 XL |
2477 | pub struct FnHeader { |
2478 | pub unsafety: Unsafety, | |
2479 | pub constness: Constness, | |
2480 | pub asyncness: IsAsync, | |
2481 | pub abi: Abi, | |
2482 | } | |
2483 | ||
48663c56 XL |
2484 | impl FnHeader { |
2485 | pub fn is_const(&self) -> bool { | |
2486 | match &self.constness { | |
2487 | Constness::Const => true, | |
2488 | _ => false, | |
2489 | } | |
2490 | } | |
2491 | } | |
2492 | ||
dc9dc135 | 2493 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 | 2494 | pub enum ItemKind { |
0531ce1d | 2495 | /// An `extern crate` item, with optional *original* crate name if the crate was renamed. |
e9174d1e | 2496 | /// |
9fa01778 | 2497 | /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. |
8faf50e0 | 2498 | ExternCrate(Option<Name>), |
476ff2be SL |
2499 | |
2500 | /// `use foo::bar::*;` or `use foo::bar::baz as quux;` | |
2501 | /// | |
2502 | /// or just | |
2503 | /// | |
e1599b0c | 2504 | /// `use foo::bar::baz;` (with `as baz` implicitly on the right). |
8faf50e0 | 2505 | Use(P<Path>, UseKind), |
e9174d1e | 2506 | |
e1599b0c | 2507 | /// A `static` item. |
8faf50e0 | 2508 | Static(P<Ty>, Mutability, BodyId), |
e1599b0c | 2509 | /// A `const` item. |
8faf50e0 | 2510 | Const(P<Ty>, BodyId), |
e1599b0c | 2511 | /// A function declaration. |
8faf50e0 | 2512 | Fn(P<FnDecl>, FnHeader, Generics, BodyId), |
e1599b0c | 2513 | /// A module. |
8faf50e0 | 2514 | Mod(Mod), |
e74abb32 | 2515 | /// An external module, e.g. `extern { .. }`. |
8faf50e0 | 2516 | ForeignMod(ForeignMod), |
e1599b0c | 2517 | /// Module-level inline assembly (from `global_asm!`). |
8faf50e0 | 2518 | GlobalAsm(P<GlobalAsm>), |
e1599b0c | 2519 | /// A type alias, e.g., `type Foo = Bar<u8>`. |
416331ca | 2520 | TyAlias(P<Ty>, Generics), |
e1599b0c | 2521 | /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`. |
416331ca | 2522 | OpaqueTy(OpaqueTy), |
e1599b0c | 2523 | /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`. |
8faf50e0 | 2524 | Enum(EnumDef, Generics), |
e1599b0c | 2525 | /// A struct definition, e.g., `struct Foo<A> {x: A}`. |
8faf50e0 | 2526 | Struct(VariantData, Generics), |
e1599b0c | 2527 | /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`. |
8faf50e0 | 2528 | Union(VariantData, Generics), |
e1599b0c | 2529 | /// A trait definition. |
8faf50e0 | 2530 | Trait(IsAuto, Unsafety, Generics, GenericBounds, HirVec<TraitItemRef>), |
e1599b0c | 2531 | /// A trait alias. |
8faf50e0 | 2532 | TraitAlias(Generics, GenericBounds), |
e9174d1e | 2533 | |
e1599b0c | 2534 | /// An implementation, e.g., `impl<A> Trait for Foo { .. }`. |
8faf50e0 XL |
2535 | Impl(Unsafety, |
2536 | ImplPolarity, | |
2537 | Defaultness, | |
2538 | Generics, | |
2539 | Option<TraitRef>, // (optional) trait this impl implements | |
2540 | P<Ty>, // self | |
2541 | HirVec<ImplItemRef>), | |
e9174d1e SL |
2542 | } |
2543 | ||
8faf50e0 | 2544 | impl ItemKind { |
e9174d1e SL |
2545 | pub fn descriptive_variant(&self) -> &str { |
2546 | match *self { | |
8faf50e0 XL |
2547 | ItemKind::ExternCrate(..) => "extern crate", |
2548 | ItemKind::Use(..) => "use", | |
2549 | ItemKind::Static(..) => "static item", | |
2550 | ItemKind::Const(..) => "constant item", | |
2551 | ItemKind::Fn(..) => "function", | |
2552 | ItemKind::Mod(..) => "module", | |
2553 | ItemKind::ForeignMod(..) => "foreign module", | |
2554 | ItemKind::GlobalAsm(..) => "global asm", | |
416331ca XL |
2555 | ItemKind::TyAlias(..) => "type alias", |
2556 | ItemKind::OpaqueTy(..) => "opaque type", | |
8faf50e0 XL |
2557 | ItemKind::Enum(..) => "enum", |
2558 | ItemKind::Struct(..) => "struct", | |
2559 | ItemKind::Union(..) => "union", | |
2560 | ItemKind::Trait(..) => "trait", | |
2561 | ItemKind::TraitAlias(..) => "trait alias", | |
9fa01778 | 2562 | ItemKind::Impl(..) => "impl", |
e9174d1e SL |
2563 | } |
2564 | } | |
3b2f2976 XL |
2565 | |
2566 | pub fn adt_kind(&self) -> Option<AdtKind> { | |
2567 | match *self { | |
8faf50e0 XL |
2568 | ItemKind::Struct(..) => Some(AdtKind::Struct), |
2569 | ItemKind::Union(..) => Some(AdtKind::Union), | |
2570 | ItemKind::Enum(..) => Some(AdtKind::Enum), | |
3b2f2976 XL |
2571 | _ => None, |
2572 | } | |
2573 | } | |
abe05a73 XL |
2574 | |
2575 | pub fn generics(&self) -> Option<&Generics> { | |
2576 | Some(match *self { | |
8faf50e0 | 2577 | ItemKind::Fn(_, _, ref generics, _) | |
416331ca XL |
2578 | ItemKind::TyAlias(_, ref generics) | |
2579 | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) | | |
8faf50e0 XL |
2580 | ItemKind::Enum(_, ref generics) | |
2581 | ItemKind::Struct(_, ref generics) | | |
2582 | ItemKind::Union(_, ref generics) | | |
2583 | ItemKind::Trait(_, _, ref generics, _, _) | | |
2584 | ItemKind::Impl(_, _, _, ref generics, _, _, _)=> generics, | |
abe05a73 XL |
2585 | _ => return None |
2586 | }) | |
2587 | } | |
e9174d1e SL |
2588 | } |
2589 | ||
32a655c1 SL |
2590 | /// A reference from an trait to one of its associated items. This |
2591 | /// contains the item's id, naturally, but also the item's name and | |
2592 | /// some other high-level details (like whether it is an associated | |
2593 | /// type or method, and whether it is public). This allows other | |
9fa01778 | 2594 | /// passes to find the impl they want without loading the ID (which |
32a655c1 | 2595 | /// means fewer edges in the incremental compilation graph). |
dc9dc135 | 2596 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
32a655c1 SL |
2597 | pub struct TraitItemRef { |
2598 | pub id: TraitItemId, | |
532ac7d7 | 2599 | #[stable_hasher(project(name))] |
8faf50e0 | 2600 | pub ident: Ident, |
dc9dc135 | 2601 | pub kind: AssocItemKind, |
32a655c1 SL |
2602 | pub span: Span, |
2603 | pub defaultness: Defaultness, | |
2604 | } | |
2605 | ||
476ff2be | 2606 | /// A reference from an impl to one of its associated items. This |
9fa01778 | 2607 | /// contains the item's ID, naturally, but also the item's name and |
476ff2be SL |
2608 | /// some other high-level details (like whether it is an associated |
2609 | /// type or method, and whether it is public). This allows other | |
9fa01778 | 2610 | /// passes to find the impl they want without loading the ID (which |
476ff2be | 2611 | /// means fewer edges in the incremental compilation graph). |
dc9dc135 | 2612 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
476ff2be SL |
2613 | pub struct ImplItemRef { |
2614 | pub id: ImplItemId, | |
532ac7d7 | 2615 | #[stable_hasher(project(name))] |
8faf50e0 | 2616 | pub ident: Ident, |
dc9dc135 | 2617 | pub kind: AssocItemKind, |
476ff2be SL |
2618 | pub span: Span, |
2619 | pub vis: Visibility, | |
2620 | pub defaultness: Defaultness, | |
2621 | } | |
2622 | ||
532ac7d7 | 2623 | #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] |
dc9dc135 | 2624 | pub enum AssocItemKind { |
476ff2be SL |
2625 | Const, |
2626 | Method { has_self: bool }, | |
2627 | Type, | |
416331ca | 2628 | OpaqueTy, |
476ff2be SL |
2629 | } |
2630 | ||
dc9dc135 | 2631 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
e9174d1e | 2632 | pub struct ForeignItem { |
532ac7d7 | 2633 | #[stable_hasher(project(name))] |
0731742a | 2634 | pub ident: Ident, |
9cc50fc6 | 2635 | pub attrs: HirVec<Attribute>, |
e74abb32 | 2636 | pub kind: ForeignItemKind, |
9fa01778 | 2637 | pub hir_id: HirId, |
e9174d1e SL |
2638 | pub span: Span, |
2639 | pub vis: Visibility, | |
2640 | } | |
2641 | ||
9fa01778 | 2642 | /// An item within an `extern` block. |
dc9dc135 | 2643 | #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] |
8faf50e0 | 2644 | pub enum ForeignItemKind { |
9fa01778 | 2645 | /// A foreign function. |
8faf50e0 | 2646 | Fn(P<FnDecl>, HirVec<Ident>, Generics), |
48663c56 XL |
2647 | /// A foreign static item (`static ext: u8`). |
2648 | Static(P<Ty>, Mutability), | |
9fa01778 | 2649 | /// A foreign type. |
8faf50e0 | 2650 | Type, |
e9174d1e SL |
2651 | } |
2652 | ||
8faf50e0 | 2653 | impl ForeignItemKind { |
e9174d1e SL |
2654 | pub fn descriptive_variant(&self) -> &str { |
2655 | match *self { | |
8faf50e0 XL |
2656 | ForeignItemKind::Fn(..) => "foreign function", |
2657 | ForeignItemKind::Static(..) => "foreign static item", | |
2658 | ForeignItemKind::Type => "foreign type", | |
e9174d1e SL |
2659 | } |
2660 | } | |
2661 | } | |
54a0048b | 2662 | |
48663c56 | 2663 | /// A variable captured by a closure. |
532ac7d7 | 2664 | #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] |
dc9dc135 | 2665 | pub struct Upvar { |
54a0048b SL |
2666 | // First span where it is accessed (there can be multiple). |
2667 | pub span: Span | |
2668 | } | |
2669 | ||
54a0048b SL |
2670 | pub type CaptureModeMap = NodeMap<CaptureClause>; |
2671 | ||
48663c56 XL |
2672 | // The TraitCandidate's import_ids is empty if the trait is defined in the same module, and |
2673 | // has length > 0 if the trait is found through an chain of imports, starting with the | |
2674 | // import/use statement in the scope where the trait is used. | |
9e0c209e | 2675 | #[derive(Clone, Debug)] |
a7813a04 XL |
2676 | pub struct TraitCandidate { |
2677 | pub def_id: DefId, | |
48663c56 | 2678 | pub import_ids: SmallVec<[NodeId; 1]>, |
a7813a04 XL |
2679 | } |
2680 | ||
54a0048b | 2681 | // Trait method resolution |
a7813a04 | 2682 | pub type TraitMap = NodeMap<Vec<TraitCandidate>>; |
54a0048b SL |
2683 | |
2684 | // Map from the NodeId of a glob import to a list of items which are actually | |
2685 | // imported. | |
476ff2be | 2686 | pub type GlobMap = NodeMap<FxHashSet<Name>>; |
0531ce1d | 2687 | |
0bf4aa26 | 2688 | pub fn provide(providers: &mut Providers<'_>) { |
0731742a | 2689 | check_attr::provide(providers); |
dc9dc135 XL |
2690 | map::provide(providers); |
2691 | upvars::provide(providers); | |
0531ce1d XL |
2692 | } |
2693 | ||
532ac7d7 | 2694 | #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] |
94b46f34 XL |
2695 | pub struct CodegenFnAttrs { |
2696 | pub flags: CodegenFnAttrFlags, | |
b7449926 | 2697 | /// Parsed representation of the `#[inline]` attribute |
0531ce1d | 2698 | pub inline: InlineAttr, |
9fa01778 XL |
2699 | /// Parsed representation of the `#[optimize]` attribute |
2700 | pub optimize: OptimizeAttr, | |
b7449926 XL |
2701 | /// The `#[export_name = "..."]` attribute, indicating a custom symbol a |
2702 | /// function should be exported under | |
0531ce1d | 2703 | pub export_name: Option<Symbol>, |
b7449926 XL |
2704 | /// The `#[link_name = "..."]` attribute, indicating a custom symbol an |
2705 | /// imported function should be imported as. Note that `export_name` | |
2706 | /// probably isn't set when this is set, this is for foreign items while | |
2707 | /// `#[export_name]` is for Rust-defined functions. | |
2708 | pub link_name: Option<Symbol>, | |
e74abb32 XL |
2709 | /// The `#[link_ordinal = "..."]` attribute, indicating an ordinal an |
2710 | /// imported function has in the dynamic library. Note that this must not | |
2711 | /// be set when `link_name` is set. This is for foreign items with the | |
2712 | /// "raw-dylib" kind. | |
2713 | pub link_ordinal: Option<usize>, | |
b7449926 XL |
2714 | /// The `#[target_feature(enable = "...")]` attribute and the enabled |
2715 | /// features (only enabled features are supported right now). | |
0531ce1d | 2716 | pub target_features: Vec<Symbol>, |
b7449926 | 2717 | /// The `#[linkage = "..."]` attribute and the value we found. |
0531ce1d | 2718 | pub linkage: Option<Linkage>, |
b7449926 XL |
2719 | /// The `#[link_section = "..."]` attribute, or what executable section this |
2720 | /// should be placed in. | |
8faf50e0 | 2721 | pub link_section: Option<Symbol>, |
0531ce1d XL |
2722 | } |
2723 | ||
2724 | bitflags! { | |
532ac7d7 | 2725 | #[derive(RustcEncodable, RustcDecodable, HashStable)] |
8faf50e0 | 2726 | pub struct CodegenFnAttrFlags: u32 { |
9fa01778 XL |
2727 | /// `#[cold]`: a hint to LLVM that this function, when called, is never on |
2728 | /// the hot path. | |
8faf50e0 | 2729 | const COLD = 1 << 0; |
dc9dc135 | 2730 | /// `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this |
9fa01778 | 2731 | /// function is never null. |
8faf50e0 | 2732 | const ALLOCATOR = 1 << 1; |
9fa01778 XL |
2733 | /// `#[unwind]`: an indicator that this function may unwind despite what |
2734 | /// its ABI signature may otherwise imply. | |
8faf50e0 | 2735 | const UNWIND = 1 << 2; |
9fa01778 | 2736 | /// `#[rust_allocator_nounwind]`, an indicator that an imported FFI |
b7449926 XL |
2737 | /// function will never unwind. Probably obsolete by recent changes with |
2738 | /// #[unwind], but hasn't been removed/migrated yet | |
8faf50e0 | 2739 | const RUSTC_ALLOCATOR_NOUNWIND = 1 << 3; |
9fa01778 XL |
2740 | /// `#[naked]`: an indicator to LLVM that no function prologue/epilogue |
2741 | /// should be generated. | |
8faf50e0 | 2742 | const NAKED = 1 << 4; |
9fa01778 XL |
2743 | /// `#[no_mangle]`: an indicator that the function's name should be the same |
2744 | /// as its symbol. | |
8faf50e0 | 2745 | const NO_MANGLE = 1 << 5; |
9fa01778 | 2746 | /// `#[rustc_std_internal_symbol]`: an indicator that this symbol is a |
b7449926 XL |
2747 | /// "weird symbol" for the standard library in that it has slightly |
2748 | /// different linkage, visibility, and reachability rules. | |
8faf50e0 | 2749 | const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6; |
9fa01778 XL |
2750 | /// `#[no_debug]`: an indicator that no debugging information should be |
2751 | /// generated for this function by LLVM. | |
8faf50e0 | 2752 | const NO_DEBUG = 1 << 7; |
9fa01778 | 2753 | /// `#[thread_local]`: indicates a static is actually a thread local |
b7449926 | 2754 | /// piece of memory |
8faf50e0 | 2755 | const THREAD_LOCAL = 1 << 8; |
9fa01778 XL |
2756 | /// `#[used]`: indicates that LLVM can't eliminate this function (but the |
2757 | /// linker can!). | |
8faf50e0 | 2758 | const USED = 1 << 9; |
e74abb32 | 2759 | /// `#[ffi_returns_twice]`, indicates that an extern function can return |
9fa01778 | 2760 | /// multiple times |
e74abb32 XL |
2761 | const FFI_RETURNS_TWICE = 1 << 10; |
2762 | /// `#[track_caller]`: allow access to the caller location | |
2763 | const TRACK_CALLER = 1 << 11; | |
0531ce1d XL |
2764 | } |
2765 | } | |
2766 | ||
94b46f34 XL |
2767 | impl CodegenFnAttrs { |
2768 | pub fn new() -> CodegenFnAttrs { | |
2769 | CodegenFnAttrs { | |
2770 | flags: CodegenFnAttrFlags::empty(), | |
0531ce1d | 2771 | inline: InlineAttr::None, |
9fa01778 | 2772 | optimize: OptimizeAttr::None, |
0531ce1d | 2773 | export_name: None, |
b7449926 | 2774 | link_name: None, |
e74abb32 | 2775 | link_ordinal: None, |
0531ce1d XL |
2776 | target_features: vec![], |
2777 | linkage: None, | |
8faf50e0 | 2778 | link_section: None, |
0531ce1d XL |
2779 | } |
2780 | } | |
2781 | ||
9fa01778 | 2782 | /// Returns `true` if `#[inline]` or `#[inline(always)]` is present. |
0531ce1d XL |
2783 | pub fn requests_inline(&self) -> bool { |
2784 | match self.inline { | |
2785 | InlineAttr::Hint | InlineAttr::Always => true, | |
2786 | InlineAttr::None | InlineAttr::Never => false, | |
2787 | } | |
2788 | } | |
2789 | ||
dc9dc135 | 2790 | /// Returns `true` if it looks like this symbol needs to be exported, for example: |
0bf4aa26 XL |
2791 | /// |
2792 | /// * `#[no_mangle]` is present | |
2793 | /// * `#[export_name(...)]` is present | |
2794 | /// * `#[linkage]` is present | |
0531ce1d | 2795 | pub fn contains_extern_indicator(&self) -> bool { |
0bf4aa26 XL |
2796 | self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) || |
2797 | self.export_name.is_some() || | |
2798 | match self.linkage { | |
dc9dc135 XL |
2799 | // These are private, so make sure we don't try to consider |
2800 | // them external. | |
0bf4aa26 XL |
2801 | None | |
2802 | Some(Linkage::Internal) | | |
2803 | Some(Linkage::Private) => false, | |
2804 | Some(_) => true, | |
2805 | } | |
0531ce1d XL |
2806 | } |
2807 | } | |
b7449926 XL |
2808 | |
2809 | #[derive(Copy, Clone, Debug)] | |
2810 | pub enum Node<'hir> { | |
e1599b0c | 2811 | Param(&'hir Param), |
b7449926 XL |
2812 | Item(&'hir Item), |
2813 | ForeignItem(&'hir ForeignItem), | |
2814 | TraitItem(&'hir TraitItem), | |
2815 | ImplItem(&'hir ImplItem), | |
2816 | Variant(&'hir Variant), | |
2817 | Field(&'hir StructField), | |
2818 | AnonConst(&'hir AnonConst), | |
2819 | Expr(&'hir Expr), | |
2820 | Stmt(&'hir Stmt), | |
13cf67c4 | 2821 | PathSegment(&'hir PathSegment), |
b7449926 XL |
2822 | Ty(&'hir Ty), |
2823 | TraitRef(&'hir TraitRef), | |
2824 | Binding(&'hir Pat), | |
2825 | Pat(&'hir Pat), | |
dc9dc135 | 2826 | Arm(&'hir Arm), |
b7449926 XL |
2827 | Block(&'hir Block), |
2828 | Local(&'hir Local), | |
2829 | MacroDef(&'hir MacroDef), | |
2830 | ||
532ac7d7 XL |
2831 | /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants |
2832 | /// with synthesized constructors. | |
2833 | Ctor(&'hir VariantData), | |
b7449926 XL |
2834 | |
2835 | Lifetime(&'hir Lifetime), | |
2836 | GenericParam(&'hir GenericParam), | |
2837 | Visibility(&'hir Visibility), | |
2838 | ||
2839 | Crate, | |
2840 | } | |
e1599b0c XL |
2841 | |
2842 | impl Node<'_> { | |
2843 | pub fn ident(&self) -> Option<Ident> { | |
2844 | match self { | |
2845 | Node::TraitItem(TraitItem { ident, .. }) | | |
2846 | Node::ImplItem(ImplItem { ident, .. }) | | |
2847 | Node::ForeignItem(ForeignItem { ident, .. }) | | |
2848 | Node::Item(Item { ident, .. }) => Some(*ident), | |
2849 | _ => None, | |
2850 | } | |
2851 | } | |
2852 | } |