forked from rust-lang/rust
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmod.rs
384 lines (352 loc) · 10.6 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
//! The MIR is built from some typed high-level IR
//! (THIR). This section defines the THIR along with a trait for
//! accessing it. The intention is to allow MIR construction to be
//! unit-tested and separated from the Rust source and compiler data
//! structures.
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::infer::canonical::Canonical;
use rustc_middle::middle::region;
use rustc_middle::mir::{BinOp, BorrowKind, Field, UnOp};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{AdtDef, Const, Ty, UpvarSubsts, UserType};
use rustc_span::Span;
use rustc_target::abi::VariantIdx;
use rustc_target::asm::InlineAsmRegOrRegClass;
crate mod constant;
crate mod cx;
pub use cx::build_thir;
crate mod pattern;
pub use self::pattern::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
mod arena;
pub use arena::Arena;
mod util;
#[derive(Copy, Clone, Debug)]
pub enum LintLevel {
Inherited,
Explicit(hir::HirId),
}
#[derive(Debug)]
pub struct Block<'thir, 'tcx> {
pub targeted_by_break: bool,
pub region_scope: region::Scope,
pub opt_destruction_scope: Option<region::Scope>,
pub span: Span,
pub stmts: &'thir [Stmt<'thir, 'tcx>],
pub expr: Option<&'thir Expr<'thir, 'tcx>>,
pub safety_mode: BlockSafety,
}
#[derive(Copy, Clone, Debug)]
pub enum BlockSafety {
Safe,
ExplicitUnsafe(hir::HirId),
PushUnsafe,
PopUnsafe,
}
#[derive(Debug)]
pub struct Stmt<'thir, 'tcx> {
pub kind: StmtKind<'thir, 'tcx>,
pub opt_destruction_scope: Option<region::Scope>,
}
#[derive(Debug)]
pub enum StmtKind<'thir, 'tcx> {
Expr {
/// scope for this statement; may be used as lifetime of temporaries
scope: region::Scope,
/// expression being evaluated in this statement
expr: &'thir Expr<'thir, 'tcx>,
},
Let {
/// scope for variables bound in this let; covers this and
/// remaining statements in block
remainder_scope: region::Scope,
/// scope for the initialization itself; might be used as
/// lifetime of temporaries
init_scope: region::Scope,
/// `let <PAT> = ...`
///
/// if a type is included, it is added as an ascription pattern
pattern: Pat<'tcx>,
/// let pat: ty = <INIT> ...
initializer: Option<&'thir Expr<'thir, 'tcx>>,
/// the lint level for this let-statement
lint_level: LintLevel,
},
}
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Expr<'_, '_>, 144);
/// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
/// into instances of this `Expr` enum. This lowering can be done
/// basically as lazily or as eagerly as desired: every recursive
/// reference to an expression in this enum is an `&'thir Expr<'thir, 'tcx>`, which
/// may in turn be another instance of this enum (boxed), or else an
/// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
/// short-lived. They are created by `Thir::to_expr`, analyzed and
/// converted into MIR, and then discarded.
///
/// If you compare `Expr` to the full compiler AST, you will see it is
/// a good bit simpler. In fact, a number of the more straight-forward
/// MIR simplifications are already done in the impl of `Thir`. For
/// example, method calls and overloaded operators are absent: they are
/// expected to be converted into `Expr::Call` instances.
#[derive(Debug)]
pub struct Expr<'thir, 'tcx> {
/// type of this expression
pub ty: Ty<'tcx>,
/// lifetime of this expression if it should be spilled into a
/// temporary; should be None only if in a constant context
pub temp_lifetime: Option<region::Scope>,
/// span of the expression in the source
pub span: Span,
/// kind of expression
pub kind: ExprKind<'thir, 'tcx>,
}
#[derive(Debug)]
pub enum ExprKind<'thir, 'tcx> {
Scope {
region_scope: region::Scope,
lint_level: LintLevel,
value: &'thir Expr<'thir, 'tcx>,
},
Box {
value: &'thir Expr<'thir, 'tcx>,
},
If {
cond: &'thir Expr<'thir, 'tcx>,
then: &'thir Expr<'thir, 'tcx>,
else_opt: Option<&'thir Expr<'thir, 'tcx>>,
},
Call {
ty: Ty<'tcx>,
fun: &'thir Expr<'thir, 'tcx>,
args: &'thir [Expr<'thir, 'tcx>],
/// Whether this is from a call in HIR, rather than from an overloaded
/// operator. `true` for overloaded function call.
from_hir_call: bool,
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
fn_span: Span,
},
Deref {
arg: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded!
Binary {
op: BinOp,
lhs: &'thir Expr<'thir, 'tcx>,
rhs: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded!
LogicalOp {
op: LogicalOp,
lhs: &'thir Expr<'thir, 'tcx>,
rhs: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded!
// LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
Unary {
op: UnOp,
arg: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded!
Cast {
source: &'thir Expr<'thir, 'tcx>,
},
Use {
source: &'thir Expr<'thir, 'tcx>,
}, // Use a lexpr to get a vexpr.
NeverToAny {
source: &'thir Expr<'thir, 'tcx>,
},
Pointer {
cast: PointerCast,
source: &'thir Expr<'thir, 'tcx>,
},
Loop {
body: &'thir Expr<'thir, 'tcx>,
},
Match {
scrutinee: &'thir Expr<'thir, 'tcx>,
arms: &'thir [Arm<'thir, 'tcx>],
},
Block {
body: Block<'thir, 'tcx>,
},
Assign {
lhs: &'thir Expr<'thir, 'tcx>,
rhs: &'thir Expr<'thir, 'tcx>,
},
AssignOp {
op: BinOp,
lhs: &'thir Expr<'thir, 'tcx>,
rhs: &'thir Expr<'thir, 'tcx>,
},
Field {
lhs: &'thir Expr<'thir, 'tcx>,
name: Field,
},
Index {
lhs: &'thir Expr<'thir, 'tcx>,
index: &'thir Expr<'thir, 'tcx>,
},
VarRef {
id: hir::HirId,
},
/// Used to represent upvars mentioned in a closure/generator
UpvarRef {
/// DefId of the closure/generator
closure_def_id: DefId,
/// HirId of the root variable
var_hir_id: hir::HirId,
},
Borrow {
borrow_kind: BorrowKind,
arg: &'thir Expr<'thir, 'tcx>,
},
/// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
AddressOf {
mutability: hir::Mutability,
arg: &'thir Expr<'thir, 'tcx>,
},
Break {
label: region::Scope,
value: Option<&'thir Expr<'thir, 'tcx>>,
},
Continue {
label: region::Scope,
},
Return {
value: Option<&'thir Expr<'thir, 'tcx>>,
},
ConstBlock {
value: &'tcx Const<'tcx>,
},
Repeat {
value: &'thir Expr<'thir, 'tcx>,
count: &'tcx Const<'tcx>,
},
Array {
fields: &'thir [Expr<'thir, 'tcx>],
},
Tuple {
fields: &'thir [Expr<'thir, 'tcx>],
},
Adt {
adt_def: &'tcx AdtDef,
variant_index: VariantIdx,
substs: SubstsRef<'tcx>,
/// Optional user-given substs: for something like `let x =
/// Bar::<T> { ... }`.
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
fields: &'thir [FieldExpr<'thir, 'tcx>],
base: Option<FruInfo<'thir, 'tcx>>,
},
PlaceTypeAscription {
source: &'thir Expr<'thir, 'tcx>,
/// Type that the user gave to this expression
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
},
ValueTypeAscription {
source: &'thir Expr<'thir, 'tcx>,
/// Type that the user gave to this expression
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
},
Closure {
closure_id: DefId,
substs: UpvarSubsts<'tcx>,
upvars: &'thir [Expr<'thir, 'tcx>],
movability: Option<hir::Movability>,
},
Literal {
literal: &'tcx Const<'tcx>,
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
/// The `DefId` of the `const` item this literal
/// was produced from, if this is not a user-written
/// literal value.
const_id: Option<DefId>,
},
/// A literal containing the address of a `static`.
///
/// This is only distinguished from `Literal` so that we can register some
/// info for diagnostics.
StaticRef {
literal: &'tcx Const<'tcx>,
def_id: DefId,
},
InlineAsm {
template: &'tcx [InlineAsmTemplatePiece],
operands: &'thir [InlineAsmOperand<'thir, 'tcx>],
options: InlineAsmOptions,
line_spans: &'tcx [Span],
},
/// An expression taking a reference to a thread local.
ThreadLocalRef(DefId),
LlvmInlineAsm {
asm: &'tcx hir::LlvmInlineAsmInner,
outputs: &'thir [Expr<'thir, 'tcx>],
inputs: &'thir [Expr<'thir, 'tcx>],
},
Yield {
value: &'thir Expr<'thir, 'tcx>,
},
}
#[derive(Debug)]
pub struct FieldExpr<'thir, 'tcx> {
pub name: Field,
pub expr: &'thir Expr<'thir, 'tcx>,
}
#[derive(Debug)]
pub struct FruInfo<'thir, 'tcx> {
pub base: &'thir Expr<'thir, 'tcx>,
pub field_types: &'thir [Ty<'tcx>],
}
#[derive(Debug)]
pub struct Arm<'thir, 'tcx> {
pub pattern: Pat<'tcx>,
pub guard: Option<Guard<'thir, 'tcx>>,
pub body: &'thir Expr<'thir, 'tcx>,
pub lint_level: LintLevel,
pub scope: region::Scope,
pub span: Span,
}
#[derive(Debug)]
pub enum Guard<'thir, 'tcx> {
If(&'thir Expr<'thir, 'tcx>),
IfLet(Pat<'tcx>, &'thir Expr<'thir, 'tcx>),
}
#[derive(Copy, Clone, Debug)]
pub enum LogicalOp {
And,
Or,
}
#[derive(Debug)]
pub enum InlineAsmOperand<'thir, 'tcx> {
In {
reg: InlineAsmRegOrRegClass,
expr: &'thir Expr<'thir, 'tcx>,
},
Out {
reg: InlineAsmRegOrRegClass,
late: bool,
expr: Option<&'thir Expr<'thir, 'tcx>>,
},
InOut {
reg: InlineAsmRegOrRegClass,
late: bool,
expr: &'thir Expr<'thir, 'tcx>,
},
SplitInOut {
reg: InlineAsmRegOrRegClass,
late: bool,
in_expr: &'thir Expr<'thir, 'tcx>,
out_expr: Option<&'thir Expr<'thir, 'tcx>>,
},
Const {
expr: &'thir Expr<'thir, 'tcx>,
},
SymFn {
expr: &'thir Expr<'thir, 'tcx>,
},
SymStatic {
def_id: DefId,
},
}